Fix crash when a test fails inside RealmReactTests
This also appears to fix crashes when running ReactTests with Chrome debugging enabled! The crash when tests failed was due to JavaScriptCore trying to create a backtrace with the native call stack.
This commit is contained in:
parent
7f5902b021
commit
5d59431860
|
@ -17,11 +17,10 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@import Foundation;
|
||||
@import JavaScriptCore;
|
||||
|
||||
extern JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor);
|
||||
|
||||
@interface RealmReact : NSObject
|
||||
|
||||
@property (nonatomic, readonly) id executor;
|
||||
|
||||
+ (id)executor;
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
@import GCDWebServers;
|
||||
@import RealmJS;
|
||||
@import JavaScriptCore;
|
||||
@import ObjectiveC;
|
||||
@import Darwin;
|
||||
|
||||
|
@ -30,11 +29,16 @@
|
|||
- (JSGlobalContextRef)ctx;
|
||||
@end
|
||||
|
||||
JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor) {
|
||||
Ivar contextIvar = class_getInstanceVariable([executor class], "_context");
|
||||
id rctJSContext = contextIvar ? object_getIvar(executor, contextIvar) : nil;
|
||||
|
||||
return [rctJSContext ctx];
|
||||
}
|
||||
|
||||
@interface RealmReact () <RCTBridgeModule>
|
||||
@end
|
||||
|
||||
static id s_executor;
|
||||
|
||||
@implementation RealmReact
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
@ -54,16 +58,12 @@ static id s_executor;
|
|||
return @"Realm";
|
||||
}
|
||||
|
||||
+ (id)executor {
|
||||
return s_executor;
|
||||
}
|
||||
|
||||
- (void)setBridge:(RCTBridge *)bridge {
|
||||
_bridge = bridge;
|
||||
|
||||
Ivar executorIvar = class_getInstanceVariable([bridge class], "_javaScriptExecutor");
|
||||
s_executor = object_getIvar(bridge, executorIvar);
|
||||
Ivar contextIvar = class_getInstanceVariable([s_executor class], "_context");
|
||||
id executor = object_getIvar(bridge, executorIvar);
|
||||
Ivar contextIvar = class_getInstanceVariable([executor class], "_context");
|
||||
|
||||
// The executor could be a RCTWebSocketExecutor, in which case it won't have a JS context.
|
||||
if (!contextIvar) {
|
||||
|
@ -96,8 +96,8 @@ static id s_executor;
|
|||
return;
|
||||
}
|
||||
|
||||
[s_executor executeBlockOnJavaScriptQueue:^{
|
||||
id rctJSContext = object_getIvar(s_executor, contextIvar);
|
||||
[executor executeBlockOnJavaScriptQueue:^{
|
||||
id rctJSContext = object_getIvar(executor, contextIvar);
|
||||
JSGlobalContextRef ctx;
|
||||
|
||||
if (rctJSContext) {
|
||||
|
@ -108,7 +108,7 @@ static id s_executor;
|
|||
|
||||
if (RCTJavaScriptContext) {
|
||||
ctx = JSGlobalContextCreate(NULL);
|
||||
object_setIvar(s_executor, contextIvar, [[RCTJavaScriptContext alloc] initWithJSContext:ctx]);
|
||||
object_setIvar(executor, contextIvar, [[RCTJavaScriptContext alloc] initWithJSContext:ctx]);
|
||||
}
|
||||
else {
|
||||
NSLog(@"Failed to load RCTJavaScriptContext class");
|
||||
|
|
|
@ -22,13 +22,31 @@
|
|||
|
||||
@import RealmReact;
|
||||
|
||||
extern void JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(JSGlobalContextRef ctx, bool includesNativeCallStack);
|
||||
|
||||
static id<RCTJavaScriptExecutor> s_currentJavaScriptExecutor;
|
||||
|
||||
@interface RealmReactTests : RealmJSTests
|
||||
@end
|
||||
|
||||
@implementation RealmReactTests
|
||||
|
||||
+ (XCTestSuite *)defaultTestSuite {
|
||||
[self waitForNotification:RCTJavaScriptDidLoadNotification];
|
||||
NSNotification *notification = [self waitForNotification:RCTJavaScriptDidLoadNotification];
|
||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
||||
|
||||
if (!bridge) {
|
||||
NSLog(@"No RCTBridge provided by RCTJavaScriptDidLoadNotification");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
s_currentJavaScriptExecutor = [bridge valueForKey:@"javaScriptExecutor"];
|
||||
|
||||
// FIXME: Remove this nonsense once the crashes go away when a test fails!
|
||||
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(s_currentJavaScriptExecutor);
|
||||
if (ctx) {
|
||||
JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false);
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
NSDictionary *testCaseNames = [self invokeMethod:@"getTestNames" inModule:@"index" error:&error];
|
||||
|
@ -47,34 +65,34 @@
|
|||
return suite;
|
||||
}
|
||||
|
||||
+ (void)waitForNotification:(NSString *)notificationName {
|
||||
+ (NSNotification *)waitForNotification:(NSString *)notificationName {
|
||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||
__block BOOL received = NO;
|
||||
__block NSNotification *notification;
|
||||
|
||||
id token = [nc addObserverForName:notificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
received = YES;
|
||||
notification = note;
|
||||
}];
|
||||
|
||||
while (!received) {
|
||||
while (!notification) {
|
||||
@autoreleasepool {
|
||||
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||
}
|
||||
}
|
||||
|
||||
[nc removeObserver:token];
|
||||
return notification;
|
||||
}
|
||||
|
||||
+ (id)invokeMethod:(NSString *)method inModule:(NSString *)module error:(NSError * __strong *)outError {
|
||||
module = [NSString stringWithFormat:@"realm-tests/%@.js", module];
|
||||
|
||||
id<RCTJavaScriptExecutor> executor = [RealmReact executor];
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
__block id result;
|
||||
|
||||
dispatch_group_enter(group);
|
||||
|
||||
[executor executeJSCall:module method:method arguments:@[] callback:^(id json, NSError *error) {
|
||||
[s_currentJavaScriptExecutor executeJSCall:module method:method arguments:@[] callback:^(id json, NSError *error) {
|
||||
result = json;
|
||||
|
||||
if (error && outError) {
|
||||
|
|
Loading…
Reference in New Issue