diff --git a/doric-iOS/Devkit/Classes/DoricDebugDriver.m b/doric-iOS/Devkit/Classes/DoricDebugDriver.m index 82f4ae49..11a8e661 100644 --- a/doric-iOS/Devkit/Classes/DoricDebugDriver.m +++ b/doric-iOS/Devkit/Classes/DoricDebugDriver.m @@ -55,7 +55,7 @@ - (DoricRegistry *)registry { - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args { DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -64,7 +64,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } @@ -76,7 +76,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr [array addObject:arg]; } __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -85,7 +85,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } @@ -108,7 +108,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString arg = va_arg(args, JSValue *); } __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -117,7 +117,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } @@ -130,7 +130,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString [array addObject:arg]; } __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -139,14 +139,14 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source { DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -155,14 +155,14 @@ - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scr } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } - (DoricAsyncResult *)destroyContext:(NSString *)contextId { DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -171,7 +171,7 @@ - (DoricAsyncResult *)destroyContext:(NSString *)contextId { } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } diff --git a/doric-iOS/Pod/Classes/DoricNativeDriver.m b/doric-iOS/Pod/Classes/DoricNativeDriver.m index 1ddef1a1..b0f96025 100644 --- a/doric-iOS/Pod/Classes/DoricNativeDriver.m +++ b/doric-iOS/Pod/Classes/DoricNativeDriver.m @@ -56,7 +56,7 @@ + (instancetype)instance { - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args { DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -65,7 +65,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } @@ -85,7 +85,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr [array addObject:arg]; } __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -94,7 +94,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr } @catch (NSException *exception) { [ret setupError:exception]; } - }); + }]; return ret; } @@ -117,7 +117,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString arg = va_arg(args, JSValue *); } __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -127,7 +127,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString [ret setupError:exception]; [self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; } - }); + }]; return ret; } @@ -140,7 +140,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString [array addObject:arg]; } __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -150,14 +150,14 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString [ret setupError:exception]; [self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; } - }); + }]; return ret; } - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source { DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -167,14 +167,14 @@ - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scr [ret setupError:exception]; [self.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; } - }); + }]; return ret; } - (DoricAsyncResult *)destroyContext:(NSString *)contextId { DoricAsyncResult *ret = [[DoricAsyncResult alloc] init]; __weak typeof(self) _self = self; - dispatch_async(self.jsExecutor.jsQueue, ^() { + [self.jsExecutor ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; if (!self) return; @try { @@ -184,7 +184,7 @@ - (DoricAsyncResult *)destroyContext:(NSString *)contextId { [ret setupError:exception]; [self.jsExecutor.registry onException:exception inContext:[[DoricContextManager instance] getContext:contextId]]; } - }); + }]; return ret; } diff --git a/doric-iOS/Pod/Classes/Engine/DoricJSEngine.h b/doric-iOS/Pod/Classes/Engine/DoricJSEngine.h index 646366ad..32bd1de3 100644 --- a/doric-iOS/Pod/Classes/Engine/DoricJSEngine.h +++ b/doric-iOS/Pod/Classes/Engine/DoricJSEngine.h @@ -32,7 +32,6 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) id jsExecutor; -@property(nonatomic, strong) dispatch_queue_t jsQueue; @property(nonatomic, strong) DoricRegistry *registry; @@ -45,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN - (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args; - (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args; + +- (void)ensureRunOnJSThread:(dispatch_block_t)block; @end NS_ASSUME_NONNULL_END diff --git a/doric-iOS/Pod/Classes/Engine/DoricJSEngine.m b/doric-iOS/Pod/Classes/Engine/DoricJSEngine.m index ec692a6c..e28a5ed0 100644 --- a/doric-iOS/Pod/Classes/Engine/DoricJSEngine.m +++ b/doric-iOS/Pod/Classes/Engine/DoricJSEngine.m @@ -45,13 +45,16 @@ @interface DoricJSEngine () @property(nonatomic, strong) NSMutableDictionary *timers; @property(nonatomic, strong) DoricBridgeExtension *bridgeExtension; @property(nonatomic, strong) NSDictionary *innerEnvironmentDictionary; +@property(nonatomic, strong) NSThread *jsThread; +@property(nonatomic, assign) BOOL destroyed; @end @implementation DoricJSEngine - (instancetype)init { if (self = [super init]) { - _jsQueue = dispatch_queue_create("doric.jsengine", DISPATCH_QUEUE_SERIAL); + _jsThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun) object:nil]; + [_jsThread start]; NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; struct utsname systemInfo; uname(&systemInfo); @@ -72,7 +75,7 @@ - (instancetype)init { @"deviceBrand": @"Apple", @"deviceModel": platform, }; - dispatch_async(_jsQueue, ^() { + [self ensureRunOnJSThread:^() { self.timers = [[NSMutableDictionary alloc] init]; self.registry = [[DoricRegistry alloc] init]; self.bridgeExtension = [DoricBridgeExtension new]; @@ -80,11 +83,36 @@ - (instancetype)init { [self initJSEngine]; [self initJSExecutor]; [self initDoricEnvironment]; - }); + }]; } return self; } +- (void)dealloc { + _destroyed = YES; +}; + +- (void)ensureRunOnJSThread:(dispatch_block_t)block { + if (NSThread.currentThread == _jsThread) { + block(); + } else { + [self performSelector:@selector(ensureRunOnJSThread:) + onThread:_jsThread + withObject:[block copy] + waitUntilDone:NO]; + } +} + +- (void)threadRun { + [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; + [NSThread currentThread].name = @"doric.js.engine"; + while (!_destroyed) { + @autoreleasepool { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; + } + } +} + - (void)initJSEngine { [self.registry registerMonitor:[DoricDefaultMonitor new]]; self.jsExecutor = [DoricJSCoreExecutor new]; @@ -234,7 +262,7 @@ - (void)callbackTimer:(NSTimer *)timer { NSDictionary *userInfo = timer.userInfo; NSNumber *timerId = [userInfo valueForKey:@"timerId"]; NSNumber *repeat = [userInfo valueForKey:@"repeat"]; - dispatch_async(self.jsQueue, ^() { + [self ensureRunOnJSThread:^{ __strong typeof(_self) self = _self; @try { [self invokeDoricMethod:DORIC_TIMER_CALLBACK, timerId, nil]; @@ -246,6 +274,6 @@ - (void)callbackTimer:(NSTimer *)timer { if (![repeat boolValue]) { [self.timers removeObjectForKey:[timerId stringValue]]; } - }); + }]; } @end