mirror of
https://github.com/status-im/realm-js.git
synced 2025-01-10 14:25:58 +00:00
Make React reloads and testing more reliable
Changed where we wait on the previous JS thread, which ultimately makes it more reliable and no longer leak memory on reloads. Resolves #397
This commit is contained in:
parent
933e6070c5
commit
db1283255f
@ -79,8 +79,6 @@ extern "C" JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executo
|
||||
|
||||
@implementation RealmReact {
|
||||
NSMutableDictionary *_eventHandlers;
|
||||
__weak NSThread *_currentJSThread;
|
||||
__weak NSRunLoop *_currentJSRunLoop;
|
||||
|
||||
#if DEBUG
|
||||
GCDWebServer *_webServer;
|
||||
@ -261,17 +259,6 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
|
||||
// shutdown rpc if in chrome debug mode
|
||||
[self shutdownRPC];
|
||||
#endif
|
||||
|
||||
// block until JS thread exits
|
||||
NSRunLoop *runLoop = _currentJSRunLoop;
|
||||
if (runLoop) {
|
||||
CFRunLoopStop([runLoop getCFRunLoop]);
|
||||
while (_currentJSThread && !_currentJSThread.finished) {
|
||||
[NSThread sleepForTimeInterval:0.01];
|
||||
}
|
||||
}
|
||||
|
||||
realm::_impl::RealmCoordinator::clear_all_caches();
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
@ -296,15 +283,24 @@ RCT_REMAP_METHOD(emit, emitEvent:(NSString *)eventName withObject:(id)object) {
|
||||
}
|
||||
else {
|
||||
__weak __typeof__(self) weakSelf = self;
|
||||
__weak __typeof__(executor) weakExecutor = executor;
|
||||
|
||||
[executor executeBlockOnJavaScriptQueue:^{
|
||||
__typeof__(self) self = weakSelf;
|
||||
if (!self) {
|
||||
__typeof__(executor) executor = weakExecutor;
|
||||
if (!self || !executor) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->_currentJSThread = [NSThread currentThread];
|
||||
self->_currentJSRunLoop = [NSRunLoop currentRunLoop];
|
||||
// Make sure the previous JS thread is completely finished before continuing.
|
||||
static __weak NSThread *s_currentJSThread;
|
||||
while (s_currentJSThread && !s_currentJSThread.finished) {
|
||||
[NSThread sleepForTimeInterval:0.1];
|
||||
}
|
||||
s_currentJSThread = [NSThread currentThread];
|
||||
|
||||
// Close all cached Realms from the previous JS thread.
|
||||
realm::_impl::RealmCoordinator::clear_all_caches();
|
||||
|
||||
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, true);
|
||||
RJSInitializeInContext(ctx);
|
||||
|
@ -78,23 +78,26 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
||||
return nil;
|
||||
}
|
||||
|
||||
RCTBridge *bridge = [RCTBridge currentBridge];
|
||||
if (!bridge.valid) {
|
||||
[self waitForNotification:RCTJavaScriptDidLoadNotification];
|
||||
bridge = [RCTBridge currentBridge];
|
||||
@autoreleasepool {
|
||||
RCTBridge *bridge = [RCTBridge currentBridge];
|
||||
|
||||
if (!bridge.valid) {
|
||||
[self waitForNotification:RCTJavaScriptDidLoadNotification];
|
||||
bridge = [RCTBridge currentBridge];
|
||||
}
|
||||
|
||||
if (bridge.executorClass != executorClass) {
|
||||
bridge.executorClass = executorClass;
|
||||
|
||||
RCTBridge *parentBridge = [bridge valueForKey:@"parentBridge"];
|
||||
[parentBridge invalidate];
|
||||
[parentBridge setUp];
|
||||
|
||||
return [self currentBridge];
|
||||
}
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
if (bridge.executorClass != executorClass) {
|
||||
bridge.executorClass = executorClass;
|
||||
|
||||
RCTBridge *parentBridge = [bridge valueForKey:@"parentBridge"];
|
||||
[parentBridge invalidate];
|
||||
[parentBridge setUp];
|
||||
|
||||
return [self currentBridge];
|
||||
}
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
+ (id<RCTJavaScriptExecutor>)currentExecutor {
|
||||
@ -102,37 +105,39 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
||||
}
|
||||
|
||||
+ (XCTestSuite *)defaultTestSuite {
|
||||
XCTestSuite *suite = [super defaultTestSuite];
|
||||
id<RCTJavaScriptExecutor> executor = [self currentExecutor];
|
||||
@autoreleasepool {
|
||||
XCTestSuite *suite = [super defaultTestSuite];
|
||||
id<RCTJavaScriptExecutor> executor = [self currentExecutor];
|
||||
|
||||
// The executor may be nil if the executorClass was not found (i.e. release build).
|
||||
if (!executor) {
|
||||
return suite;
|
||||
}
|
||||
|
||||
// FIXME: Remove this nonsense once the crashes go away when a test fails!
|
||||
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, false);
|
||||
if (ctx) {
|
||||
JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false);
|
||||
}
|
||||
|
||||
NSDictionary *testCaseNames = [self waitForEvent:@"realm-test-names"];
|
||||
NSAssert(testCaseNames.count, @"No test names were provided by the JS");
|
||||
|
||||
NSString *nameSuffix = [self classNameSuffix];
|
||||
if (nameSuffix.length) {
|
||||
NSMutableDictionary *renamedTestCaseNames = [[NSMutableDictionary alloc] init];
|
||||
for (NSString *name in testCaseNames) {
|
||||
renamedTestCaseNames[[name stringByAppendingString:nameSuffix]] = testCaseNames[name];
|
||||
}
|
||||
testCaseNames = renamedTestCaseNames;
|
||||
}
|
||||
|
||||
for (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) {
|
||||
[suite addTest:testSuite];
|
||||
}
|
||||
|
||||
// The executor may be nil if the executorClass was not found (i.e. release build).
|
||||
if (!executor) {
|
||||
return suite;
|
||||
}
|
||||
|
||||
// FIXME: Remove this nonsense once the crashes go away when a test fails!
|
||||
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, false);
|
||||
if (ctx) {
|
||||
JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false);
|
||||
}
|
||||
|
||||
NSDictionary *testCaseNames = [self waitForEvent:@"realm-test-names"];
|
||||
NSAssert(testCaseNames.count, @"No test names were provided by the JS");
|
||||
|
||||
NSString *nameSuffix = [self classNameSuffix];
|
||||
if (nameSuffix.length) {
|
||||
NSMutableDictionary *renamedTestCaseNames = [[NSMutableDictionary alloc] init];
|
||||
for (NSString *name in testCaseNames) {
|
||||
renamedTestCaseNames[[name stringByAppendingString:nameSuffix]] = testCaseNames[name];
|
||||
}
|
||||
testCaseNames = renamedTestCaseNames;
|
||||
}
|
||||
|
||||
for (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) {
|
||||
[suite addTest:testSuite];
|
||||
}
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
+ (NSNotification *)waitForNotification:(NSString *)notificationName {
|
||||
|
Loading…
x
Reference in New Issue
Block a user