diff --git a/iOS/Pod/Classes/DoricContextManager.m b/iOS/Pod/Classes/DoricContextManager.m index 5e0e4de9..a6ddc2cf 100644 --- a/iOS/Pod/Classes/DoricContextManager.m +++ b/iOS/Pod/Classes/DoricContextManager.m @@ -51,7 +51,7 @@ + (instancetype)instance { } - (void)createContext:(DoricContext *)context script:(NSString *)script source:(NSString *)source { - context.contextId = [NSString stringWithFormat:@"%ld", (long) self.counter++]; + context.contextId = [NSString stringWithFormat:@"%ld", (long) ++self.counter]; [context.driver createContext:context.contextId script:script source:source]; dispatch_sync(self.mapQueue, ^() { NSValue *value = [NSValue valueWithNonretainedObject:context]; diff --git a/iOS/Pod/Classes/Engine/DoricJSEngine.m b/iOS/Pod/Classes/Engine/DoricJSEngine.m index 7d6928d3..d5a9a25e 100644 --- a/iOS/Pod/Classes/Engine/DoricJSEngine.m +++ b/iOS/Pod/Classes/Engine/DoricJSEngine.m @@ -42,7 +42,9 @@ - (instancetype)init { _bridgeExtension = [[DoricBridgeExtension alloc] init]; dispatch_async(_jsQueue, ^() { self.timers = [[NSMutableDictionary alloc] init]; - self.jsExecutor = [[DoricJSRemoteExecutor alloc] init]; + // Debug: 切换 + // self.jsExecutor = [[DoricJSRemoteExecutor alloc] init]; + self.jsExecutor = [DoricJSCoreExecutor new]; self.registry = [[DoricRegistry alloc] init]; [self initJSExecutor]; [self initDoricEnvironment]; diff --git a/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.h b/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.h index e626791e..b9145867 100644 --- a/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.h +++ b/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.h @@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, strong) dispatch_semaphore_t semaphore; +- (void)close; @end NS_ASSUME_NONNULL_END diff --git a/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.m b/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.m index 93393cc1..4875126f 100644 --- a/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.m +++ b/iOS/Pod/Classes/Engine/DoricJSRemoteExecutor.m @@ -22,28 +22,37 @@ #import "DoricJSRemoteExecutor.h" #import #import "DoricUtil.h" +#import "DoricJSRemoteArgType.h" +#import "NSString+JsonString.h" + +static NSString * const kUrlStr = @"ws://192.168.24.240:2080"; + +typedef id (^Block0)(void); +typedef id (^Block1)(id arg0); +typedef id (^Block2)(id arg0, id arg1); +typedef id (^Block3)(id arg0, id arg1, id arg2); +typedef id (^Block4)(id arg0, id arg1, id arg2, id arg3); +typedef id (^Block5)(id arg0, id arg1, id arg2, id arg3, id arg4); @interface DoricJSRemoteExecutor () - -@property(nonatomic, strong) SRWebSocket *websocket; - +@property(nonatomic, strong) SRWebSocket *srWebSocket; +@property(nonatomic, strong) NSMutableDictionary *blockMDic; +@property(nonatomic, strong) JSValue *temp; @end @implementation DoricJSRemoteExecutor - (instancetype)init { if (self = [super init]) { - _websocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:@"ws://192.168.24.166:2080"]]; - _websocket.delegate = self; - [_websocket open]; + [self srWebSocket]; _semaphore = dispatch_semaphore_create(0); - dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER); + DC_LOCK(self.semaphore); } return self; } - (void)webSocketDidOpen:(SRWebSocket *)webSocket { DoricLog(@"debugger webSocketDidOpen"); - dispatch_semaphore_signal(_semaphore); + DC_UNLOCK(self.semaphore); } - (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload { @@ -57,15 +66,49 @@ - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message { options:NSJSONReadingMutableContainers error:&err]; if (err) { - DoricLog(@"webSocketdidReceiveMessage parse error:%@", err); + DoricLog(@"debugger webSocketdidReceiveMessage parse error:%@", err); return; } - NSString *source = [[dic valueForKey:@"source"] mutableCopy]; + NSString *cmd = [[dic valueForKey:@"cmd"] copy]; + + if ([cmd isEqualToString:@"injectGlobalJSFunction"]) { + NSString *name = [dic valueForKey:@"name"]; + NSArray *argsArr = [dic valueForKey:@"arguments"]; + NSMutableArray *argsMarr = [NSMutableArray new]; + for (NSUInteger i = 0; i < argsArr.count; i++) { + [argsMarr addObject:argsArr[i]]; + } + + id result; + id tmpBlk = self.blockMDic[name]; + if (argsArr.count == 0) { + result = ((Block0) tmpBlk)(); + } else if (argsArr.count == 1) { + result = ((Block1) tmpBlk)(argsArr[0]); + } else if (argsArr.count == 2) { + result = ((Block2)tmpBlk)(argsArr[0], argsArr[1]); + } else if (argsArr.count == 3) { + result = ((Block3)tmpBlk)(argsArr[0], argsArr[1], argsArr[2]); + } else if (argsArr.count == 4) { + result = ((Block4)tmpBlk)(argsArr[0], argsArr[1], argsArr[2], argsArr[3]); + } else if (argsArr.count == 5) { + result = ((Block5)tmpBlk)(argsArr[0], argsArr[1], argsArr[2], argsArr[3], argsArr[4]); + } + + } else if ([cmd isEqualToString:@"invokeMethod"]) { + @try { + self.temp = [JSValue valueWithObject:[dic valueForKey:@"result"] inContext:nil]; + } @catch (NSException *exception) { + DoricLog(@"debugger ", NSStringFromSelector(_cmd), exception.reason); + } @finally { + DC_UNLOCK(self.semaphore); + } + } } - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { DoricLog(@"debugger webSocketdidFailWithError"); - dispatch_semaphore_signal(_semaphore); + DC_UNLOCK(self.semaphore); } - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { @@ -73,14 +116,78 @@ - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reas } - (NSString *)loadJSScript:(NSString *)script source:(NSString *)source { + return nil; } - (void)injectGlobalJSObject:(NSString *)name obj:(id)obj { + if ([obj isKindOfClass:NSClassFromString(@"NSBlock")]) { + self.blockMDic[name] = obj; + } + NSDictionary *jsonDic = @{ + @"cmd": @"injectGlobalJSFunction", + @"name": name + }; + + NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic]; + if (!jsonStr) { + return; + } + + [self.srWebSocket send:jsonStr]; } - (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args { - return nil; + + NSMutableArray *argsMArr = [NSMutableArray new]; + for (id arg in args) { + NSDictionary *dic = @{ + @"type": @(DoricargTypeWithArg(arg)), + @"value": arg + }; + [argsMArr addObject:dic]; + } + + NSArray *argsArr = [argsMArr copy]; + + NSDictionary *jsonDic = @{ + @"cmd": @"invokeMethod", + @"objectName": objName, + @"functionName": funcName, + @"javaValues": argsArr + }; + + NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic]; + if (!jsonStr) { + return nil; + } + + [self.srWebSocket send:jsonStr]; + DC_LOCK(self.semaphore); + + return self.temp; +} + +- (void)close { + [self.srWebSocket close]; +} + +#pragma mark - Properties +- (SRWebSocket *)srWebSocket { + if (!_srWebSocket) { + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kUrlStr] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10]; + _srWebSocket = [[SRWebSocket alloc] initWithURLRequest:request]; + _srWebSocket.delegate = self; + [_srWebSocket open]; + } + return _srWebSocket; +} + +- (NSMutableDictionary *)blockMDic { + if (!_blockMDic) { + _blockMDic = [NSMutableDictionary new]; + } + return _blockMDic; } @end diff --git a/iOS/Pod/Classes/Util/Category/NSString+JsonString.h b/iOS/Pod/Classes/Util/Category/NSString+JsonString.h new file mode 100644 index 00000000..9581e9a3 --- /dev/null +++ b/iOS/Pod/Classes/Util/Category/NSString+JsonString.h @@ -0,0 +1,18 @@ +// +// NSString+JsonString.h +// Doric +// +// Created by Insomnia on 2019/11/7. +// + + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSString (JsonString) ++ (NSString *)dc_convertToJsonWithDic:(NSDictionary *)dic; +@end + +NS_ASSUME_NONNULL_END diff --git a/iOS/Pod/Classes/Util/Category/NSString+JsonString.m b/iOS/Pod/Classes/Util/Category/NSString+JsonString.m new file mode 100644 index 00000000..bcdd6437 --- /dev/null +++ b/iOS/Pod/Classes/Util/Category/NSString+JsonString.m @@ -0,0 +1,23 @@ +// +// NSString+JsonString.m +// Doric +// +// Created by Insomnia on 2019/11/7. +// + +#import "NSString+JsonString.h" +#import "DoricUtil.h" + +@implementation NSString (JsonString) ++ (NSString *)dc_convertToJsonWithDic:(NSDictionary *)dic { + NSError *err; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&err]; + NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + + if (err) { + DoricLog(NSStringFromSelector(_cmd), @"Convert dictionary to json string failed."); + return nil; + } + return jsonStr; +} +@end diff --git a/iOS/Pod/Classes/Util/DoricJSRemoteArgType.h b/iOS/Pod/Classes/Util/DoricJSRemoteArgType.h new file mode 100644 index 00000000..f18ea41d --- /dev/null +++ b/iOS/Pod/Classes/Util/DoricJSRemoteArgType.h @@ -0,0 +1,23 @@ +// +// DoricJSRemoteArgType.h +// Doric +// +// Created by Insomnia on 2019/11/7. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, DoricJSRemoteArgType) { + DoricJSRemoteArgTypeNil = 0, + DoricJSRemoteArgTypeInteger, + DoricJSRemoteArgTypeBool, + DoricJSRemoteArgTypeString, + DoricJSRemoteArgTypeObject, + DoricJSRemoteArgTypeArray, +}; + +DoricJSRemoteArgType DoricargTypeWithArg(id arg); + +NS_ASSUME_NONNULL_END diff --git a/iOS/Pod/Classes/Util/DoricJSRemoteArgType.m b/iOS/Pod/Classes/Util/DoricJSRemoteArgType.m new file mode 100644 index 00000000..1b018109 --- /dev/null +++ b/iOS/Pod/Classes/Util/DoricJSRemoteArgType.m @@ -0,0 +1,12 @@ +// +// DoricJSRemoteArgType.m +// Doric +// +// Created by Insomnia on 2019/11/7. +// + +#import "DoricJSRemoteArgType.h" +DoricJSRemoteArgType DoricargTypeWithArg(id arg) { + // TODO: 类型缺失 + return DoricJSRemoteArgTypeString; +} diff --git a/iOS/Pod/Classes/Util/DoricUtil.h b/iOS/Pod/Classes/Util/DoricUtil.h index dba4e355..ae606cc9 100644 --- a/iOS/Pod/Classes/Util/DoricUtil.h +++ b/iOS/Pod/Classes/Util/DoricUtil.h @@ -27,3 +27,11 @@ void DoricLog(NSString *_Nonnull format, ...); UIColor *_Nonnull DoricColor(NSNumber *_Nonnull number); NSBundle *DoricBundle(); + +#ifndef DC_LOCK +#define DC_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); +#endif + +#ifndef DC_UNLOCK +#define DC_UNLOCK(lock) dispatch_semaphore_signal(lock); +#endif diff --git a/setup.sh b/setup.sh index ae733f0b..3f06bc21 100755 --- a/setup.sh +++ b/setup.sh @@ -8,4 +8,4 @@ cd js-framework && npm install && npm run build && cd .. cd debugger && npm install && npm run build && cd .. cd demo && npm install && npm run build && cd .. -cd doric-cli && npm install && cd .. +cd doric-cli && npm install && npm link && cd ..