success run js on iOS

This commit is contained in:
pengfei.zhou
2019-07-29 13:48:27 +08:00
parent 0b285fe470
commit 2a53b24aff
21 changed files with 282 additions and 103 deletions

View File

@@ -15,12 +15,12 @@ typedef void(^DoricResultCallback)(R);
typedef void(^DoricExceptionCallback)(NSException *);
typedef void(^DoricFinishCallback)(void);
-(void)setupResult:(R)result;
-(void)setupError:(NSException*)exception;
-(BOOL)hasResult;
-(R)getResult;
-(void)setResultCallback:(DoricResultCallback) callback exceptionCallback:(DoricExceptionCallback) exceptionCallback;
-(void)setFinishCallback:(DoricFinishCallback) callback;
- (void)setupResult:(R)result;
- (void)setupError:(NSException*)exception;
- (BOOL)hasResult;
- (R)getResult;
- (void)setResultCallback:(DoricResultCallback) callback exceptionCallback:(DoricExceptionCallback) exceptionCallback;
- (void)setFinishCallback:(DoricFinishCallback) callback;
@end
NS_ASSUME_NONNULL_END

View File

@@ -16,7 +16,7 @@ @interface DoricAsyncResult()
@implementation DoricAsyncResult
-(void)setupResult:(id)result {
- (void)setupResult:(id)result {
self.result = result;
if(self.resultCallback){
self.resultCallback(result);
@@ -26,7 +26,7 @@ -(void)setupResult:(id)result {
}
}
-(void)setupError:(NSException *)exception {
- (void)setupError:(NSException *)exception {
self.result = exception;
if(self.exceptionCallback){
self.exceptionCallback(exception);
@@ -35,15 +35,15 @@ -(void)setupError:(NSException *)exception {
self.finishCallback();
}
}
-(BOOL)hasResult {
- (BOOL)hasResult {
return self.result;
}
-(id)getResult {
- (id)getResult {
return self.result;
}
-(void)setResultCallback:(DoricResultCallback)callback exceptionCallback:(DoricExceptionCallback)exceptionCallback {
- (void)setResultCallback:(DoricResultCallback)callback exceptionCallback:(DoricExceptionCallback)exceptionCallback {
self.resultCallback = callback;
self.exceptionCallback = exceptionCallback;
if([self.result isKindOfClass: [NSException class]]){
@@ -53,7 +53,7 @@ -(void)setResultCallback:(DoricResultCallback)callback exceptionCallback:(DoricE
}
}
-(void)setFinishCallback:(DoricFinishCallback)callback {
- (void)setFinishCallback:(DoricFinishCallback)callback {
self.finishCallback = callback;
if(self.result){
callback();

View File

@@ -0,0 +1,15 @@
//
// DoricComponent.h
// Doric
//
// Created by pengfei.zhou on 2019/7/29.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface DoricComponent : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// DoricComponent.m
// Doric
//
// Created by pengfei.zhou on 2019/7/29.
//
#import "DoricComponent.h"
@implementation DoricComponent
@end

View File

@@ -6,12 +6,18 @@
//
#import <Foundation/Foundation.h>
#import "DoricDriver.h"
NS_ASSUME_NONNULL_BEGIN
@interface DoricContext : NSObject
@property (nonatomic,strong) NSString *contextId;
@property (nonatomic,strong) DoricDriver *driver;
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source;
- (DoricAsyncResult *)callEntity:(NSString *)method, ...;
@end

View File

@@ -6,7 +6,31 @@
//
#import "DoricContext.h"
#import "DoricContextManager.h"
@implementation DoricContext
- (instancetype)init {
if(self = [super init]){
_driver = [DoricDriver instance];
}
return self;
}
- (instancetype)initWithScript:(NSString *)script source:(NSString *)source {
return [[DoricContextManager instance] createContext:script source:source];
}
- (void)dealloc {
[[DoricContextManager instance] destroyContext:self];
}
- (DoricAsyncResult *)callEntity:(NSString *)method, ... {
va_list args;
va_start(args, method);
DoricAsyncResult *ret = [self.driver invokeContextEntity:self.contextId method:method arguments:args];
va_end(args);
return ret;
}
@end

View File

@@ -0,0 +1,21 @@
//
// DoricContextManager.h
// Doric
//
// Created by pengfei.zhou on 2019/7/29.
//
#import <Foundation/Foundation.h>
#import "DoricContext.h"
NS_ASSUME_NONNULL_BEGIN
@interface DoricContextManager : NSObject
+ (instancetype) instance;
- (DoricContext *)createContext:(NSString *)script source:(NSString *)source;
- (void) destroyContext:(DoricContext *)context;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,57 @@
//
// DoricContextManager.m
// Doric
//
// Created by pengfei.zhou on 2019/7/29.
//
#import "DoricContextManager.h"
#import "DoricContext.h"
@interface DoricContextManager()
@property (nonatomic) NSInteger counter;
@property (nonatomic,strong) NSMutableDictionary *doricContextMap;
@property (nonatomic,strong) dispatch_queue_t mapQueue;
@end
@implementation DoricContextManager
- (instancetype)init {
if(self = [super init]){
_doricContextMap = [[NSMutableDictionary alloc] init];
_counter = 0;
_mapQueue = dispatch_queue_create("doric.contextmap", DISPATCH_QUEUE_SERIAL);
}
return self;
}
+ (instancetype)instance{
static DoricContextManager *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[DoricContextManager alloc] init];
});
return _instance;
}
- (DoricContext *)createContext:(NSString *)script source:(NSString *)source {
DoricContext *doricContext = [[DoricContext alloc] init];
doricContext.contextId = [NSString stringWithFormat:@"%ld", (long)self.counter++];
[doricContext.driver createContext:doricContext.contextId script:script source:source];
dispatch_sync(self.mapQueue, ^(){
[self.doricContextMap setValue:doricContext forKey:doricContext.contextId];
});
return doricContext;
}
- (void) destroyContext:(DoricContext *)context {
NSString *contextId = context.contextId;
[[context.driver destroyContext:contextId] setFinishCallback:^(){
dispatch_sync(self.mapQueue, ^(){
[self.doricContextMap removeObjectForKey:contextId];
});
}];
}
@end

View File

@@ -18,15 +18,17 @@ typedef NS_ENUM(NSInteger, QueueMode) {
NS_ASSUME_NONNULL_BEGIN
@interface DoricDriver : NSObject
+(instancetype) instance;
+ (instancetype) instance;
@property (nonatomic,strong) DoricRegistry *registry;
-(DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source;
-(DoricAsyncResult *)destroyContext:(NSString *)contextId;
- (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source;
- (DoricAsyncResult *)destroyContext:(NSString *)contextId;
- (DoricAsyncResult *)invokeDoricMethod:(NSString *)method, ...;
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method, ...;
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method arguments:(va_list) args;
-(DoricAsyncResult *)invokeDoricMethod:(NSString *)method, ...;
-(DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method, ...;
@end
NS_ASSUME_NONNULL_END

View File

@@ -17,7 +17,14 @@ @implementation DoricDriver
@dynamic registry;
-(DoricRegistry *)registry {
- (instancetype)init {
if(self = [super init]){
_jsExecutor = [[DoricJSEngine alloc] init];
}
return self;
}
- (DoricRegistry *)registry {
return self.jsExecutor.registry;
}
@@ -30,7 +37,7 @@ + (instancetype)instance{
return _instance;
}
-(DoricAsyncResult<JSValue *> *)invokeDoricMethod:(NSString *)method, ... {
- (DoricAsyncResult<JSValue *> *)invokeDoricMethod:(NSString *)method, ... {
va_list args;
va_start(args, method);
DoricAsyncResult *ret = [self invokeDoricMethod:method arguments:args];
@@ -38,7 +45,7 @@ + (instancetype)instance{
return ret;
}
-(DoricAsyncResult<JSValue *> *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
- (DoricAsyncResult<JSValue *> *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^(){
@@ -54,20 +61,24 @@ + (instancetype)instance{
return ret;
}
-(DoricAsyncResult<JSValue *> *)invokeContextEntity:(NSString *)contextId method:(NSString *)method,... {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:DORIC_CONTEXT_INVOKE];
[array addObject:contextId];
[array addObject:method];
- (DoricAsyncResult<JSValue *> *)invokeContextEntity:(NSString *)contextId method:(NSString *)method,... {
va_list args;
va_start(args, method);
DoricAsyncResult *ret = [self invokeContextEntity:contextId method:method arguments:args];
va_end(args);
return ret;
}
- (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString *)method arguments:(va_list)args {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:contextId];
[array addObject:method];
id arg = va_arg(args, id);
while(arg != nil){
[array addObject:arg];
arg = va_arg(args, JSValue *);
}
va_end(args);
__weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^(){
__strong typeof(_self) self = _self;
@@ -76,13 +87,13 @@ + (instancetype)instance{
JSValue *jsValue = [self.jsExecutor invokeDoricMethod:DORIC_CONTEXT_INVOKE argumentsArray:array];
[ret setupResult:jsValue];
} @catch (NSException *exception) {
[ret setupError:exception];
[ret setupError:exception];
}
});
return ret;
}
-(DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
- (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, ^(){
@@ -98,7 +109,7 @@ -(DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scri
return ret;
}
-(DoricAsyncResult *)destroyContext:(NSString *)contextId {
- (DoricAsyncResult *)destroyContext:(NSString *)contextId {
DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
__weak typeof(self) _self = self;
dispatch_async(self.jsExecutor.jsQueue, ^(){

View File

@@ -14,32 +14,32 @@ @interface DoricJSCoreExecutor()
@end
@implementation DoricJSCoreExecutor
-(instancetype)init {
- (instancetype)init {
if(self = [super init]){
_jsContext = [[JSContext alloc] init];
}
return self;
}
-(void)checkJSException {
- (void)checkJSException {
if(self.jsContext.exception){
NSString *errMsg = [NSString stringWithFormat:@"%@ (line %@ in the generated bundle)\n/***StackTrace***/\n%@/***StackTrace***/", self.jsContext.exception, self.jsContext.exception[@"line"],self.jsContext.exception[@"stack"]];
@throw [[NSException alloc] initWithName:@"DoricJS" reason:errMsg userInfo:nil];
}
}
-(NSString *)loadJSScript:(NSString *)script source:(NSString *)source {
- (NSString *)loadJSScript:(NSString *)script source:(NSString *)source {
NSString *ret = [[self.jsContext evaluateScript:script withSourceURL:[NSURL URLWithString:source]] toString];
[self checkJSException];
return ret;
}
-(void)injectGlobalJSObject:(NSString *)name obj:(id)obj {
- (void)injectGlobalJSObject:(NSString *)name obj:(id)obj {
self.jsContext[name] = obj;
[self checkJSException];
}
-(JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args {
- (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args {
JSValue *obj = [self.jsContext objectForKeyedSubscript:objName];
JSValue *ret = [obj invokeMethod:funcName withArguments:args];
[self checkJSException];

View File

@@ -17,15 +17,15 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic,strong) DoricRegistry *registry;
-(void)prepareContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source;
- (void)prepareContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source;
-(void)destroyContext:(NSString *)contextId;
- (void)destroyContext:(NSString *)contextId;
-(JSValue *)invokeDoricMethod:(NSString *)method, ...;
- (JSValue *)invokeDoricMethod:(NSString *)method, ...;
-(JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args;
- (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args;
-(JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args;
- (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args;
@end
NS_ASSUME_NONNULL_END

View File

@@ -18,20 +18,21 @@ @interface DoricJSEngine()
@implementation DoricJSEngine
-(instancetype)init {
- (instancetype)init {
if(self = [super init]){
_jsQueue = dispatch_queue_create("doric.jsengine", DISPATCH_QUEUE_SERIAL);
dispatch_async(_jsQueue, ^(){
self.timers = [[NSMutableDictionary alloc] init];
self.jsExecutor = [[DoricJSCoreExecutor alloc] init];
self.registry = [[DoricRegistry alloc] init];
[self initJSExecutor];
[self initDoricEnvironment];
});
}
return self;
}
-(void)initJSExecutor {
- (void)initJSExecutor {
__weak typeof(self) _self = self;
[self.jsExecutor injectGlobalJSObject:INJECT_LOG obj:^(NSString * type, NSString * message) {
@@ -78,7 +79,7 @@ -(void)initJSExecutor {
}
-(void)initDoricEnvironment {
- (void)initDoricEnvironment {
[self loadBuiltinJS:DORIC_BUNDLE_SANDBOX];
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:DORIC_BUNDLE_LIB ofType:@"js"];
NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
@@ -86,13 +87,13 @@ -(void)initDoricEnvironment {
source: [@"Module://" stringByAppendingString:DORIC_MODULE_LIB]];
}
-(void)loadBuiltinJS:(NSString *)fileName {
- (void)loadBuiltinJS:(NSString *)fileName {
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:DORIC_BUNDLE_SANDBOX ofType:@"js"];
NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[self.jsExecutor loadJSScript:jsContent source:[@"Assets://" stringByAppendingString:fileName]];
}
-(JSValue *)invokeDoricMethod:(NSString *)method,... {
- (JSValue *)invokeDoricMethod:(NSString *)method,... {
va_list args;
va_start(args, method);
JSValue *ret = [self invokeDoricMethod:method arguments:args];
@@ -100,7 +101,7 @@ -(JSValue *)invokeDoricMethod:(NSString *)method,... {
return ret;
}
-(JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
- (JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
NSMutableArray *array = [[NSMutableArray alloc] init];
id arg = va_arg(args, id);
while(arg != nil){
@@ -110,31 +111,31 @@ -(JSValue *)invokeDoricMethod:(NSString *)method arguments:(va_list)args {
return [self.jsExecutor invokeObject:GLOBAL_DORIC method:method args:array];
}
-(JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
- (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
return [self.jsExecutor invokeObject:GLOBAL_DORIC method:method args:args];
}
-(NSString *)packageContextScript:(NSString *)contextId content:(NSString *)content {
- (NSString *)packageContextScript:(NSString *)contextId content:(NSString *)content {
NSString *ret = [NSString stringWithFormat:TEMPLATE_CONTEXT_CREATE, content, contextId, contextId, contextId];
return ret;
}
-(NSString *)packageModuleScript:(NSString *)moduleName content:(NSString *)content {
- (NSString *)packageModuleScript:(NSString *)moduleName content:(NSString *)content {
NSString *ret = [NSString stringWithFormat:TEMPLATE_MODULE, moduleName, content];
return ret;
}
-(void)prepareContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
- (void)prepareContext:(NSString *)contextId script:(NSString *)script source:(NSString *)source {
[self.jsExecutor loadJSScript:[self packageContextScript:contextId content:script]
source:[@"Context://" stringByAppendingString:source]];
}
-(void)destroyContext:(NSString *)contextId {
- (void)destroyContext:(NSString *)contextId {
[self.jsExecutor loadJSScript:[NSString stringWithFormat:TEMPLATE_CONTEXT_DESTROY, contextId]
source:[@"_Context://" stringByAppendingString:contextId]];
}
-(void)callbackTimer:(NSTimer *)timer {
- (void)callbackTimer:(NSTimer *)timer {
NSDictionary *userInfo = timer.userInfo;
NSNumber *timerId = [userInfo valueForKey:@"timerId"];
NSNumber *repeat = [userInfo valueForKey:@"repeat"];

View File

@@ -12,11 +12,11 @@ NS_ASSUME_NONNULL_BEGIN
@protocol DoricJSExecutorProtocal <NSObject>
-(NSString *) loadJSScript:(NSString *)script source:(NSString *)source;
- (NSString *) loadJSScript:(NSString *)script source:(NSString *)source;
-(void) injectGlobalJSObject:(NSString *)name obj:(id)obj;
- (void) injectGlobalJSObject:(NSString *)name obj:(id)obj;
-(JSValue *) invokeObject: (NSString *)objName method:(NSString *)funcName args:(NSArray *)args;
- (JSValue *) invokeObject: (NSString *)objName method:(NSString *)funcName args:(NSArray *)args;
@end

View File

@@ -0,0 +1,16 @@
//
// DoricNativePlugin.h
// Doric
//
// Created by pengfei.zhou on 2019/7/29.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface DoricNativePlugin : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// DoricNativePlugin.m
// Doric
//
// Created by pengfei.zhou on 2019/7/29.
//
#import "DoricNativePlugin.h"
@implementation DoricNativePlugin
@end

View File

@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface DoricRegistry : NSObject
-(NSString *)acquireJSBundle:(NSString *)bundleName;
- (NSString *)acquireJSBundle:(NSString *)bundleName;
@end

View File

@@ -10,47 +10,47 @@
@implementation UIView(Doric)
-(CGFloat)x {
- (CGFloat)x {
return self.frame.origin.x;
}
-(void)setX:(CGFloat)x {
- (void)setX:(CGFloat)x {
CGRect frame = self.frame;
frame.origin.x = x;
[self setFrame:frame];
}
-(CGFloat)y {
- (CGFloat)y {
return self.frame.origin.y;
}
-(void)setY:(CGFloat)y {
- (void)setY:(CGFloat)y {
CGRect frame = self.frame;
frame.origin.y = y;
[self setFrame:frame];
}
-(CGFloat)left {
- (CGFloat)left {
return self.frame.origin.x;
}
-(void)setLeft:(CGFloat)left {
- (void)setLeft:(CGFloat)left {
CGRect frame = self.frame;
frame.origin.x = left;
[self setFrame:frame];
}
-(CGFloat)right {
- (CGFloat)right {
return self.frame.origin.x + self.frame.size.width;
}
-(void)setRight:(CGFloat)right {
- (void)setRight:(CGFloat)right {
CGRect frame = self.frame;
frame.origin.x = right - self.frame.size.width;
[self setFrame:frame];
}
-(CGFloat)top {
- (CGFloat)top {
return self.frame.origin.y;
}
@@ -60,11 +60,11 @@ - (void)setTop:(CGFloat)top {
[self setFrame:frame];
}
-(CGFloat)bottom {
- (CGFloat)bottom {
return self.frame.origin.y + self.frame.size.height;
}
-(void)setBottom:(CGFloat)bottom {
- (void)setBottom:(CGFloat)bottom {
CGRect frame = self.frame;
frame.origin.y = bottom - self.frame.size.height;
[self setFrame:frame];
@@ -74,17 +74,17 @@ - (CGFloat)width {
return self.frame.size.width;
}
-(void)setWidth:(CGFloat)width {
- (void)setWidth:(CGFloat)width {
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
-(CGFloat)height {
- (CGFloat)height {
return self.frame.size.height;
}
-(void)setHeight:(CGFloat)height {
- (void)setHeight:(CGFloat)height {
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;