feat:fix iOS memory leak in debugging
This commit is contained in:
		@@ -41,14 +41,12 @@ public class DoricDebugDriver implements IDoricDriver {
 | 
				
			|||||||
    private final DoricDebugJSEngine doricDebugJSEngine;
 | 
					    private final DoricDebugJSEngine doricDebugJSEngine;
 | 
				
			||||||
    private final ExecutorService mBridgeExecutor;
 | 
					    private final ExecutorService mBridgeExecutor;
 | 
				
			||||||
    private final Handler mUIHandler;
 | 
					    private final Handler mUIHandler;
 | 
				
			||||||
    private final Handler mJSHandler;
 | 
					 | 
				
			||||||
    private String theContextId = null;
 | 
					    private String theContextId = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public DoricDebugDriver(WSClient wsClient) {
 | 
					    public DoricDebugDriver(WSClient wsClient) {
 | 
				
			||||||
        doricDebugJSEngine = new DoricDebugJSEngine(wsClient);
 | 
					        doricDebugJSEngine = new DoricDebugJSEngine(wsClient);
 | 
				
			||||||
        mBridgeExecutor = Executors.newCachedThreadPool();
 | 
					        mBridgeExecutor = Executors.newCachedThreadPool();
 | 
				
			||||||
        mUIHandler = new Handler(Looper.getMainLooper());
 | 
					        mUIHandler = new Handler(Looper.getMainLooper());
 | 
				
			||||||
        mJSHandler = doricDebugJSEngine.getJSHandler();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -64,7 +62,7 @@ public class DoricDebugDriver implements IDoricDriver {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
 | 
					    public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
 | 
				
			||||||
        return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<JSDecoder>() {
 | 
					        return AsyncCall.ensureRunInExecutor(mBridgeExecutor, new Callable<JSDecoder>() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public JSDecoder call() {
 | 
					            public JSDecoder call() {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
@@ -80,11 +78,10 @@ public class DoricDebugDriver implements IDoricDriver {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public <T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode) {
 | 
					    public <T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode) {
 | 
				
			||||||
        switch (threadMode) {
 | 
					        switch (threadMode) {
 | 
				
			||||||
            case JS:
 | 
					 | 
				
			||||||
                return AsyncCall.ensureRunInHandler(mJSHandler, callable);
 | 
					 | 
				
			||||||
            case UI:
 | 
					            case UI:
 | 
				
			||||||
                return AsyncCall.ensureRunInHandler(mUIHandler, callable);
 | 
					                return AsyncCall.ensureRunInHandler(mUIHandler, callable);
 | 
				
			||||||
            case INDEPENDENT:
 | 
					            case INDEPENDENT:
 | 
				
			||||||
 | 
					            case JS:
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                return AsyncCall.ensureRunInExecutor(mBridgeExecutor, callable);
 | 
					                return AsyncCall.ensureRunInExecutor(mBridgeExecutor, callable);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -92,7 +89,7 @@ public class DoricDebugDriver implements IDoricDriver {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
 | 
					    public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
 | 
				
			||||||
        return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
 | 
					        return AsyncCall.ensureRunInExecutor(mBridgeExecutor, new Callable<Boolean>() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public Boolean call() {
 | 
					            public Boolean call() {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
@@ -108,7 +105,7 @@ public class DoricDebugDriver implements IDoricDriver {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public AsyncResult<Boolean> destroyContext(final String contextId) {
 | 
					    public AsyncResult<Boolean> destroyContext(final String contextId) {
 | 
				
			||||||
        return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
 | 
					        return AsyncCall.ensureRunInExecutor(mBridgeExecutor, new Callable<Boolean>() {
 | 
				
			||||||
            @Override
 | 
					            @Override
 | 
				
			||||||
            public Boolean call() {
 | 
					            public Boolean call() {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,16 +11,21 @@ import org.json.JSONObject;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.concurrent.atomic.AtomicInteger;
 | 
				
			||||||
import java.util.concurrent.locks.LockSupport;
 | 
					import java.util.concurrent.locks.LockSupport;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import pub.doric.devkit.WSClient;
 | 
					import pub.doric.devkit.WSClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class RemoteJSExecutor implements WSClient.Interceptor {
 | 
					public class RemoteJSExecutor implements WSClient.Interceptor {
 | 
				
			||||||
    private final Map<String, JavaFunction> globalFunctions = new HashMap<>();
 | 
					    private final Map<String, JavaFunction> globalFunctions = new HashMap<>();
 | 
				
			||||||
    private JSDecoder temp;
 | 
					 | 
				
			||||||
    private final WSClient wsClient;
 | 
					    private final WSClient wsClient;
 | 
				
			||||||
    private final Thread currentThread;
 | 
					    private final Thread currentThread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final AtomicInteger callIdCounter = new AtomicInteger();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Map<Integer, Thread> mThreads = new HashMap<>();
 | 
				
			||||||
 | 
					    private Map<Integer, JSDecoder> mResults = new HashMap<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public RemoteJSExecutor(WSClient wsClient) {
 | 
					    public RemoteJSExecutor(WSClient wsClient) {
 | 
				
			||||||
        this.wsClient = wsClient;
 | 
					        this.wsClient = wsClient;
 | 
				
			||||||
        this.wsClient.addInterceptor(this);
 | 
					        this.wsClient.addInterceptor(this);
 | 
				
			||||||
@@ -63,6 +68,7 @@ public class RemoteJSExecutor implements WSClient.Interceptor {
 | 
				
			|||||||
                    .put("value", javaValue.getValue())
 | 
					                    .put("value", javaValue.getValue())
 | 
				
			||||||
                    .toJSONObject());
 | 
					                    .toJSONObject());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        int callId = callIdCounter.incrementAndGet();
 | 
				
			||||||
        wsClient.sendToDebugger(
 | 
					        wsClient.sendToDebugger(
 | 
				
			||||||
                "invokeMethod",
 | 
					                "invokeMethod",
 | 
				
			||||||
                new JSONBuilder()
 | 
					                new JSONBuilder()
 | 
				
			||||||
@@ -70,11 +76,13 @@ public class RemoteJSExecutor implements WSClient.Interceptor {
 | 
				
			|||||||
                        .put("objectName", objectName)
 | 
					                        .put("objectName", objectName)
 | 
				
			||||||
                        .put("functionName", functionName)
 | 
					                        .put("functionName", functionName)
 | 
				
			||||||
                        .put("values", jsonArray)
 | 
					                        .put("values", jsonArray)
 | 
				
			||||||
 | 
					                        .put("callId", callId)
 | 
				
			||||||
                        .put("hashKey", hashKey)
 | 
					                        .put("hashKey", hashKey)
 | 
				
			||||||
                        .toJSONObject());
 | 
					                        .toJSONObject());
 | 
				
			||||||
 | 
					        Thread thread = Thread.currentThread();
 | 
				
			||||||
        LockSupport.park(Thread.currentThread());
 | 
					        mThreads.put(callId, thread);
 | 
				
			||||||
        return temp;
 | 
					        LockSupport.park(thread);
 | 
				
			||||||
 | 
					        return mResults.remove(callId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void destroy() {
 | 
					    public void destroy() {
 | 
				
			||||||
@@ -99,15 +107,16 @@ public class RemoteJSExecutor implements WSClient.Interceptor {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
                case "invokeMethod": {
 | 
					                case "invokeMethod": {
 | 
				
			||||||
 | 
					                    int callId = payload.optInt("callId");
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        Object result = payload.opt("result");
 | 
					                        Object result = payload.opt("result");
 | 
				
			||||||
                        ValueBuilder vb = new ValueBuilder(result);
 | 
					                        ValueBuilder vb = new ValueBuilder(result);
 | 
				
			||||||
                        temp = new JSDecoder(vb.build());
 | 
					                        mResults.put(callId, new JSDecoder(vb.build()));
 | 
				
			||||||
                        System.out.println(result);
 | 
					                        System.out.println(result);
 | 
				
			||||||
                    } catch (Exception ex) {
 | 
					                    } catch (Exception ex) {
 | 
				
			||||||
                        ex.printStackTrace();
 | 
					                        ex.printStackTrace();
 | 
				
			||||||
                    } finally {
 | 
					                    } finally {
 | 
				
			||||||
                        LockSupport.unpark(currentThread);
 | 
					                        LockSupport.unpark(mThreads.remove(callId));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,4 +166,11 @@ public abstract class GroupNode<F extends ViewGroup> extends SuperNode<F> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void clearSubModel() {
 | 
				
			||||||
 | 
					        super.clearSubModel();
 | 
				
			||||||
 | 
					        mChildNodes.clear();
 | 
				
			||||||
 | 
					        mChildViewIds.clear();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,10 +23,13 @@
 | 
				
			|||||||
#import <Foundation/Foundation.h>
 | 
					#import <Foundation/Foundation.h>
 | 
				
			||||||
#import <DoricCore/Doric.h>
 | 
					#import <DoricCore/Doric.h>
 | 
				
			||||||
#import "DoricWSClient.h"
 | 
					#import "DoricWSClient.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NS_ASSUME_NONNULL_BEGIN
 | 
					NS_ASSUME_NONNULL_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@interface DoricDebugDriver : NSObject <DoricDriverProtocol>
 | 
					@interface DoricDebugDriver : NSObject <DoricDriverProtocol>
 | 
				
			||||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
 | 
					- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)teardown;
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NS_ASSUME_NONNULL_END
 | 
					NS_ASSUME_NONNULL_END
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,7 @@ - (DoricRegistry *)registry {
 | 
				
			|||||||
- (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
 | 
					- (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args {
 | 
				
			||||||
    DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
 | 
					    DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
 | 
				
			||||||
    __weak typeof(self) _self = self;
 | 
					    __weak typeof(self) _self = self;
 | 
				
			||||||
    [self.jsExecutor ensureRunOnJSThread:^{
 | 
					    [self runInJSQueue:^{
 | 
				
			||||||
        __strong typeof(_self) self = _self;
 | 
					        __strong typeof(_self) self = _self;
 | 
				
			||||||
        if (!self) return;
 | 
					        if (!self) return;
 | 
				
			||||||
        @try {
 | 
					        @try {
 | 
				
			||||||
@@ -78,7 +78,7 @@ - (DoricAsyncResult *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArr
 | 
				
			|||||||
        [array addObject:arg];
 | 
					        [array addObject:arg];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    __weak typeof(self) _self = self;
 | 
					    __weak typeof(self) _self = self;
 | 
				
			||||||
    [self.jsExecutor ensureRunOnJSThread:^{
 | 
					    [self runInJSQueue:^{
 | 
				
			||||||
        __strong typeof(_self) self = _self;
 | 
					        __strong typeof(_self) self = _self;
 | 
				
			||||||
        if (!self) return;
 | 
					        if (!self) return;
 | 
				
			||||||
        @try {
 | 
					        @try {
 | 
				
			||||||
@@ -110,7 +110,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
 | 
				
			|||||||
        arg = va_arg(args, JSValue *);
 | 
					        arg = va_arg(args, JSValue *);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    __weak typeof(self) _self = self;
 | 
					    __weak typeof(self) _self = self;
 | 
				
			||||||
    [self.jsExecutor ensureRunOnJSThread:^{
 | 
					    [self runInJSQueue:^{
 | 
				
			||||||
        __strong typeof(_self) self = _self;
 | 
					        __strong typeof(_self) self = _self;
 | 
				
			||||||
        if (!self) return;
 | 
					        if (!self) return;
 | 
				
			||||||
        @try {
 | 
					        @try {
 | 
				
			||||||
@@ -132,7 +132,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
 | 
				
			|||||||
        [array addObject:arg];
 | 
					        [array addObject:arg];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    __weak typeof(self) _self = self;
 | 
					    __weak typeof(self) _self = self;
 | 
				
			||||||
    [self.jsExecutor ensureRunOnJSThread:^{
 | 
					    [self runInJSQueue:^{
 | 
				
			||||||
        __strong typeof(_self) self = _self;
 | 
					        __strong typeof(_self) self = _self;
 | 
				
			||||||
        if (!self) return;
 | 
					        if (!self) return;
 | 
				
			||||||
        @try {
 | 
					        @try {
 | 
				
			||||||
@@ -148,7 +148,7 @@ - (DoricAsyncResult *)invokeContextEntity:(NSString *)contextId method:(NSString
 | 
				
			|||||||
- (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];
 | 
					    DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
 | 
				
			||||||
    __weak typeof(self) _self = self;
 | 
					    __weak typeof(self) _self = self;
 | 
				
			||||||
    [self.jsExecutor ensureRunOnJSThread:^{
 | 
					    [self runInJSQueue:^{
 | 
				
			||||||
        __strong typeof(_self) self = _self;
 | 
					        __strong typeof(_self) self = _self;
 | 
				
			||||||
        if (!self) return;
 | 
					        if (!self) return;
 | 
				
			||||||
        @try {
 | 
					        @try {
 | 
				
			||||||
@@ -164,7 +164,7 @@ - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scr
 | 
				
			|||||||
- (DoricAsyncResult *)destroyContext:(NSString *)contextId {
 | 
					- (DoricAsyncResult *)destroyContext:(NSString *)contextId {
 | 
				
			||||||
    DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
 | 
					    DoricAsyncResult *ret = [[DoricAsyncResult alloc] init];
 | 
				
			||||||
    NSString *theContextId = self.theContextId;
 | 
					    NSString *theContextId = self.theContextId;
 | 
				
			||||||
    [self.jsExecutor ensureRunOnJSThread:^{
 | 
					    [self runInJSQueue:^{
 | 
				
			||||||
        @try {
 | 
					        @try {
 | 
				
			||||||
            if ([contextId isEqualToString:theContextId]) {
 | 
					            if ([contextId isEqualToString:theContextId]) {
 | 
				
			||||||
                [DoricDev.instance stopDebugging:NO];
 | 
					                [DoricDev.instance stopDebugging:NO];
 | 
				
			||||||
@@ -177,6 +177,12 @@ - (DoricAsyncResult *)destroyContext:(NSString *)contextId {
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)runInJSQueue:(dispatch_block_t)block {
 | 
				
			||||||
 | 
					    [self.jsExecutor ensureRunOnJSThread:^{
 | 
				
			||||||
 | 
					        block();
 | 
				
			||||||
 | 
					    }];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)ensureSyncInMainQueue:(dispatch_block_t)block {
 | 
					- (void)ensureSyncInMainQueue:(dispatch_block_t)block {
 | 
				
			||||||
    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {
 | 
					    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {
 | 
				
			||||||
        block();
 | 
					        block();
 | 
				
			||||||
@@ -184,4 +190,12 @@ - (void)ensureSyncInMainQueue:(dispatch_block_t)block {
 | 
				
			|||||||
        dispatch_async(dispatch_get_main_queue(), block);
 | 
					        dispatch_async(dispatch_get_main_queue(), block);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)dealloc {
 | 
				
			||||||
 | 
					    [self.jsExecutor teardown];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)teardown {
 | 
				
			||||||
 | 
					    [self.jsExecutor teardown];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,4 +42,21 @@ - (instancetype)initWithWSClient:(DoricWSClient *)wsClient {
 | 
				
			|||||||
- (void)initJSEngine {
 | 
					- (void)initJSEngine {
 | 
				
			||||||
    self.jsExecutor = [[DoricRemoteJSExecutor alloc] initWithWSClient:self.wsClient];
 | 
					    self.jsExecutor = [[DoricRemoteJSExecutor alloc] initWithWSClient:self.wsClient];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)teardown {
 | 
				
			||||||
 | 
					    [super teardown];
 | 
				
			||||||
 | 
					    if ([self.jsExecutor isKindOfClass:DoricRemoteJSExecutor.class]) {
 | 
				
			||||||
 | 
					        [((DoricRemoteJSExecutor *) (self.jsExecutor)) teardown];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)ensureRunOnJSThread:(dispatch_block_t)block {
 | 
				
			||||||
 | 
					    if ([self.jsExecutor isKindOfClass:DoricRemoteJSExecutor.class]
 | 
				
			||||||
 | 
					            && ((DoricRemoteJSExecutor *) (self.jsExecutor)).invokingMethod) {
 | 
				
			||||||
 | 
					        NSThread *thread = [[NSThread alloc] initWithBlock:block];
 | 
				
			||||||
 | 
					        [thread start];
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        [super ensureRunOnJSThread:block];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,8 @@ @interface DoricContextDebuggable : NSObject
 | 
				
			|||||||
@property(nonatomic, weak) DoricContext *doricContext;
 | 
					@property(nonatomic, weak) DoricContext *doricContext;
 | 
				
			||||||
@property(nonatomic, weak) id <DoricDriverProtocol> nativeDriver;
 | 
					@property(nonatomic, weak) id <DoricDriverProtocol> nativeDriver;
 | 
				
			||||||
@property(nonatomic, weak) DoricWSClient *wsClient;
 | 
					@property(nonatomic, weak) DoricWSClient *wsClient;
 | 
				
			||||||
 | 
					@property(nonatomic, weak) DoricDebugDriver *debugDriver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@implementation DoricContextDebuggable
 | 
					@implementation DoricContextDebuggable
 | 
				
			||||||
@@ -46,10 +48,12 @@ - (instancetype)initWithWSClient:(DoricWSClient *)client context:(DoricContext *
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- (void)startDebug {
 | 
					- (void)startDebug {
 | 
				
			||||||
    [self.doricContext setDriver:[[DoricDebugDriver alloc] initWithWSClient:self.wsClient]];
 | 
					    [self.doricContext setDriver:[[DoricDebugDriver alloc] initWithWSClient:self.wsClient]];
 | 
				
			||||||
 | 
					    self.debugDriver = self.doricContext.driver;
 | 
				
			||||||
    [self.doricContext reload:self.doricContext.script];
 | 
					    [self.doricContext reload:self.doricContext.script];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)stopDebug:(BOOL)resume {
 | 
					- (void)stopDebug:(BOOL)resume {
 | 
				
			||||||
 | 
					    [self.debugDriver teardown];
 | 
				
			||||||
    self.doricContext.driver = self.nativeDriver;
 | 
					    self.doricContext.driver = self.nativeDriver;
 | 
				
			||||||
    if (resume) {
 | 
					    if (resume) {
 | 
				
			||||||
        [self.doricContext reload:self.doricContext.script];
 | 
					        [self.doricContext reload:self.doricContext.script];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,11 @@
 | 
				
			|||||||
NS_ASSUME_NONNULL_BEGIN
 | 
					NS_ASSUME_NONNULL_BEGIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@interface DoricRemoteJSExecutor : NSObject <DoricJSExecutorProtocol>
 | 
					@interface DoricRemoteJSExecutor : NSObject <DoricJSExecutorProtocol>
 | 
				
			||||||
 | 
					@property(nonatomic, assign) BOOL invokingMethod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
 | 
					- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)teardown;
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NS_ASSUME_NONNULL_END
 | 
					NS_ASSUME_NONNULL_END
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,8 +49,9 @@ typedef NS_ENUM(NSUInteger, DoricJSRemoteArgType) {
 | 
				
			|||||||
@interface DoricRemoteJSExecutor () <DoricWSClientInterceptor>
 | 
					@interface DoricRemoteJSExecutor () <DoricWSClientInterceptor>
 | 
				
			||||||
@property(nonatomic, weak) DoricWSClient *wsClient;
 | 
					@property(nonatomic, weak) DoricWSClient *wsClient;
 | 
				
			||||||
@property(nonatomic, strong) NSMutableDictionary <NSString *, id> *blockMDic;
 | 
					@property(nonatomic, strong) NSMutableDictionary <NSString *, id> *blockMDic;
 | 
				
			||||||
@property(nonatomic, strong) JSValue *temp;
 | 
					@property(nonatomic) NSInteger counter;
 | 
				
			||||||
@property(nonatomic, strong) dispatch_semaphore_t semaphore;
 | 
					@property(nonatomic, strong) NSMutableDictionary <NSNumber *, dispatch_semaphore_t> *semaphores;
 | 
				
			||||||
 | 
					@property(nonatomic, strong) NSMutableDictionary <NSNumber *, JSValue *> *results;
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@implementation DoricRemoteJSExecutor
 | 
					@implementation DoricRemoteJSExecutor
 | 
				
			||||||
@@ -59,7 +60,9 @@ - (instancetype)initWithWSClient:(DoricWSClient *)wsClient {
 | 
				
			|||||||
        _wsClient = wsClient;
 | 
					        _wsClient = wsClient;
 | 
				
			||||||
        [_wsClient addInterceptor:self];
 | 
					        [_wsClient addInterceptor:self];
 | 
				
			||||||
        _blockMDic = [NSMutableDictionary new];
 | 
					        _blockMDic = [NSMutableDictionary new];
 | 
				
			||||||
        _semaphore = dispatch_semaphore_create(0);
 | 
					        _semaphores = [NSMutableDictionary new];
 | 
				
			||||||
 | 
					        _results = [NSMutableDictionary new];
 | 
				
			||||||
 | 
					        _counter = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return self;
 | 
					    return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -114,17 +117,23 @@ - (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(
 | 
				
			|||||||
        NSDictionary *dic = [self dicForArg:arg];
 | 
					        NSDictionary *dic = [self dicForArg:arg];
 | 
				
			||||||
        [argsMArr addObject:dic];
 | 
					        [argsMArr addObject:dic];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    NSInteger callId = ++self.counter;
 | 
				
			||||||
    [self.wsClient sendToDebugger:@"invokeMethod" payload:@{
 | 
					    [self.wsClient sendToDebugger:@"invokeMethod" payload:@{
 | 
				
			||||||
            @"cmd": @"invokeMethod",
 | 
					            @"cmd": @"invokeMethod",
 | 
				
			||||||
            @"objectName": objName,
 | 
					            @"objectName": objName,
 | 
				
			||||||
            @"functionName": funcName,
 | 
					            @"functionName": funcName,
 | 
				
			||||||
 | 
					            @"callId": @(callId),
 | 
				
			||||||
            @"values": [argsMArr copy]
 | 
					            @"values": [argsMArr copy]
 | 
				
			||||||
    }];
 | 
					    }];
 | 
				
			||||||
 | 
					    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
 | 
				
			||||||
    DC_LOCK(self.semaphore);
 | 
					    self.semaphores[@(callId)] = semaphore;
 | 
				
			||||||
 | 
					    self.invokingMethod = YES;
 | 
				
			||||||
    return self.temp;
 | 
					    DoricLog(@"Lock %@",@(callId));
 | 
				
			||||||
 | 
					    DC_LOCK(semaphore);
 | 
				
			||||||
 | 
					    JSValue *result = self.results[@(callId)];
 | 
				
			||||||
 | 
					    [self.results removeObjectForKey:@(callId)];
 | 
				
			||||||
 | 
					    self.invokingMethod = NO;
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (NSDictionary *)dicForArg:(id)arg {
 | 
					- (NSDictionary *)dicForArg:(id)arg {
 | 
				
			||||||
@@ -176,17 +185,28 @@ - (BOOL)interceptType:(NSString *)type command:(NSString *)cmd payload:(NSDictio
 | 
				
			|||||||
                DoricLog(@"error:args to more than 5. args:%@", argsArr);
 | 
					                DoricLog(@"error:args to more than 5. args:%@", argsArr);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else if ([cmd isEqualToString:@"invokeMethod"]) {
 | 
					        } else if ([cmd isEqualToString:@"invokeMethod"]) {
 | 
				
			||||||
 | 
					            NSNumber *callId = payload[@"callId"];
 | 
				
			||||||
            @try {
 | 
					            @try {
 | 
				
			||||||
                self.temp = [JSValue valueWithObject:payload[@"result"] inContext:nil];
 | 
					                JSValue *value = [JSValue valueWithObject:payload[@"result"] inContext:nil];
 | 
				
			||||||
 | 
					                self.results[callId] = value;
 | 
				
			||||||
            } @catch (NSException *exception) {
 | 
					            } @catch (NSException *exception) {
 | 
				
			||||||
                DoricLog(@"debugger ", NSStringFromSelector(_cmd), exception.reason);
 | 
					                DoricLog(@"debugger ", NSStringFromSelector(_cmd), exception.reason);
 | 
				
			||||||
            } @finally {
 | 
					            } @finally {
 | 
				
			||||||
                DC_UNLOCK(self.semaphore);
 | 
					                DoricLog(@"Unlock:%@",payload);
 | 
				
			||||||
 | 
					                dispatch_semaphore_t semaphore = self.semaphores[callId];
 | 
				
			||||||
 | 
					                [self.semaphores removeObjectForKey:callId];
 | 
				
			||||||
 | 
					                DC_UNLOCK(semaphore);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return NO;
 | 
					    return NO;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)teardown {
 | 
				
			||||||
 | 
					    [self.blockMDic removeAllObjects];
 | 
				
			||||||
 | 
					    [self.semaphores enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, dispatch_semaphore_t obj, BOOL *stop) {
 | 
				
			||||||
 | 
					        DC_UNLOCK(obj);
 | 
				
			||||||
 | 
					    }];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,6 +101,7 @@ - (void)build:(CGSize)size {
 | 
				
			|||||||
- (void)reload:(NSString *)script {
 | 
					- (void)reload:(NSString *)script {
 | 
				
			||||||
    [self.driver destroyContext:self.contextId];
 | 
					    [self.driver destroyContext:self.contextId];
 | 
				
			||||||
    self.rootNode.viewId = nil;
 | 
					    self.rootNode.viewId = nil;
 | 
				
			||||||
 | 
					    [self.rootNode clearSubModel];
 | 
				
			||||||
    self.script = script;
 | 
					    self.script = script;
 | 
				
			||||||
    [self.driver createContext:self.contextId script:script source:self.source];
 | 
					    [self.driver createContext:self.contextId script:script source:self.source];
 | 
				
			||||||
    [self init:self.extra];
 | 
					    [self init:self.extra];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -195,4 +195,8 @@ - (void)ensureSyncInMainQueue:(dispatch_block_t)block {
 | 
				
			|||||||
        dispatch_async(dispatch_get_main_queue(), block);
 | 
					        dispatch_async(dispatch_get_main_queue(), block);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)dealloc {
 | 
				
			||||||
 | 
					    [self.jsExecutor teardown];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,8 @@ NS_ASSUME_NONNULL_BEGIN
 | 
				
			|||||||
- (void)ensureRunOnJSThread:(dispatch_block_t)block;
 | 
					- (void)ensureRunOnJSThread:(dispatch_block_t)block;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)initJSEngine;
 | 
					- (void)initJSEngine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)teardown;
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NS_ASSUME_NONNULL_END
 | 
					NS_ASSUME_NONNULL_END
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,9 +101,9 @@ - (instancetype)init {
 | 
				
			|||||||
    return self;
 | 
					    return self;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)dealloc {
 | 
					- (void)teardown {
 | 
				
			||||||
    _destroyed = YES;
 | 
					    _destroyed = YES;
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)ensureRunOnJSThread:(dispatch_block_t)block {
 | 
					- (void)ensureRunOnJSThread:(dispatch_block_t)block {
 | 
				
			||||||
    if (NSThread.currentThread == _jsThread) {
 | 
					    if (NSThread.currentThread == _jsThread) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -181,4 +181,10 @@ - (void)requestLayout {
 | 
				
			|||||||
        [node requestLayout];
 | 
					        [node requestLayout];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)clearSubModel {
 | 
				
			||||||
 | 
					    [super clearSubModel];
 | 
				
			||||||
 | 
					    self.childNodes = @[];
 | 
				
			||||||
 | 
					    self.childViewIds = @[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user