iOS:Support debugging
This commit is contained in:
parent
5ca650c9cb
commit
9db60d94ba
@ -1,12 +1,15 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="pub.doric.devkit">
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
|
||||
<application>
|
||||
<activity android:name=".ui.DoricDevActivity" />
|
||||
<activity android:name=".qrcode.activity.CaptureActivity"/>
|
||||
<activity
|
||||
android:name=".ui.DoricDevActivity"
|
||||
android:exported="true" />
|
||||
<activity android:name=".qrcode.activity.CaptureActivity" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -6,7 +6,7 @@ import org.json.JSONObject;
|
||||
public interface IDevKit {
|
||||
|
||||
enum Command {
|
||||
HOT_RELOAD, EXCEPTION, LOG
|
||||
HOT_RELOAD, EXCEPTION, LOG, DEBUG
|
||||
}
|
||||
|
||||
void connectDevKit(String url);
|
||||
|
@ -49,7 +49,7 @@ public class WSClient extends WebSocketListener {
|
||||
boolean intercept(String type, String command, JSONObject payload) throws JSONException;
|
||||
}
|
||||
|
||||
private Set<Interceptor> interceptors = new HashSet<>();
|
||||
private final Set<Interceptor> interceptors = new HashSet<>();
|
||||
|
||||
public WSClient(String url) {
|
||||
OkHttpClient okHttpClient = new OkHttpClient
|
||||
|
@ -17,6 +17,8 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSONBuilder;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
@ -25,6 +27,7 @@ import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.devkit.DevKit;
|
||||
import pub.doric.devkit.DoricDev;
|
||||
import pub.doric.devkit.IDevKit;
|
||||
import pub.doric.devkit.R;
|
||||
import pub.doric.devkit.event.ConnectExceptionEvent;
|
||||
import pub.doric.devkit.event.EOFExceptionEvent;
|
||||
@ -150,7 +153,11 @@ public class DoricDevActivity extends AppCompatActivity {
|
||||
cell.findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
DevKit.getInstance().sendDevCommand(
|
||||
IDevKit.Command.DEBUG,
|
||||
new JSONBuilder()
|
||||
.put("source", doricContext.getSource())
|
||||
.toJSONObject());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
import WebSocket from "ws"
|
||||
import "colors";
|
||||
import path from "path";
|
||||
import { glob } from "./util";
|
||||
import { Shell } from "./shell";
|
||||
|
||||
export type MSG = {
|
||||
type: "D2C" | "C2D" | "C2S" | "D2S" | "S2C" | "S2D",
|
||||
@ -45,6 +48,26 @@ export async function createServer() {
|
||||
debug?.send(result);
|
||||
} else if (resultObject.type === "C2S") {
|
||||
switch (resultObject.cmd) {
|
||||
case 'DEBUG':
|
||||
let source = resultObject.payload.source as string;
|
||||
if (source.endsWith(".js")) {
|
||||
source = source.replace(".js", ".ts");
|
||||
} else if (!source.endsWith(".ts")) {
|
||||
source = source + ".ts"
|
||||
}
|
||||
const tsFiles = await glob(`**/${source}`, {
|
||||
cwd: path.resolve(process.cwd(), "src")
|
||||
})
|
||||
if (!!!tsFiles || tsFiles.length === 0) {
|
||||
console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "src")}`);
|
||||
}
|
||||
const sourceFile = tsFiles[0];
|
||||
Shell.exec("node", [
|
||||
"--inspect-brk",
|
||||
path.resolve(process.cwd(), "src", sourceFile)
|
||||
])
|
||||
console.log(`Debugger on ${sourceFile}`);
|
||||
break;
|
||||
case 'EXCEPTION':
|
||||
console.log(resultObject.payload.source.red);
|
||||
console.log(resultObject.payload.exception.red);
|
||||
|
@ -22,10 +22,11 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <DoricCore/Doric.h>
|
||||
|
||||
#import "DoricWSClient.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricDebugDriver : NSObject <DoricDriverProtocol>
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -23,19 +23,21 @@
|
||||
#import "DoricDebugDriver.h"
|
||||
#import "DoricDebugJSEngine.h"
|
||||
#import "DoricConstant.h"
|
||||
#import "DoricContextManager.h"
|
||||
#import "DoricDev.h"
|
||||
|
||||
@interface DoricDebugDriver ()
|
||||
@property(nonatomic, strong) DoricJSEngine *jsExecutor;
|
||||
@property(nonatomic, copy) NSString *theContextId;
|
||||
@end
|
||||
|
||||
@implementation DoricDebugDriver
|
||||
|
||||
@dynamic registry;
|
||||
|
||||
- (instancetype)init {
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient {
|
||||
if (self = [super init]) {
|
||||
_jsExecutor = [[DoricDebugJSEngine alloc] init];
|
||||
_jsExecutor = [[DoricDebugJSEngine alloc] initWithWSClient:wsClient];
|
||||
_theContextId = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -150,7 +152,7 @@ - (DoricAsyncResult *)createContext:(NSString *)contextId script:(NSString *)scr
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
[self.jsExecutor prepareContext:contextId script:script source:source];
|
||||
self.theContextId = contextId;
|
||||
[ret setupResult:@YES];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
@ -166,7 +168,9 @@ - (DoricAsyncResult *)destroyContext:(NSString *)contextId {
|
||||
__strong typeof(_self) self = _self;
|
||||
if (!self) return;
|
||||
@try {
|
||||
[self.jsExecutor destroyContext:contextId];
|
||||
if ([contextId isEqualToString:self.theContextId]) {
|
||||
[DoricDev.instance stopDebugging:NO];
|
||||
}
|
||||
[ret setupResult:@YES];
|
||||
} @catch (NSException *exception) {
|
||||
[ret setupError:exception];
|
||||
|
@ -24,11 +24,11 @@
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
|
||||
#import <DoricCore/DoricJSEngine.h>
|
||||
|
||||
#import "DoricWSClient.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricDebugJSEngine : DoricJSEngine
|
||||
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -22,68 +22,22 @@
|
||||
|
||||
#import "DoricContext.h"
|
||||
#import "DoricDebugJSEngine.h"
|
||||
#import "DoricJSRemoteExecutor.h"
|
||||
#import "DoricUtil.h"
|
||||
#import "NSString+JsonString.h"
|
||||
#import "DoricDev.h"
|
||||
|
||||
@interface DoricDebugMonitor : NSObject <DoricMonitorProtocol>
|
||||
@end
|
||||
|
||||
@implementation DoricDebugMonitor
|
||||
- (void)onException:(NSException *)exception inContext:(DoricContext *)context {
|
||||
DoricLog(@"DefaultMonitor - source: %@- onException - %@", context.source, exception.reason);
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"EXCEPTION",
|
||||
@"data": @{
|
||||
@"source": [context.source stringByReplacingOccurrencesOfString:@".js" withString:@".ts"],
|
||||
@"exception": exception.reason
|
||||
}
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
[[DoricDev instance] sendDevCommand:jsonStr];
|
||||
}
|
||||
|
||||
- (void)onLog:(DoricLogType)type message:(NSString *)message {
|
||||
DoricLog(message);
|
||||
|
||||
NSString *typeString = @"DEFAULT";
|
||||
if (type == DoricLogTypeDebug) {
|
||||
typeString = @"DEFAULT";
|
||||
} else if (type == DoricLogTypeWarning) {
|
||||
typeString = @"WARN";
|
||||
} else if (type == DoricLogTypeError) {
|
||||
typeString = @"ERROR";
|
||||
}
|
||||
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"LOG",
|
||||
@"data": @{
|
||||
@"type": typeString,
|
||||
@"message": message
|
||||
}
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
[[DoricDev instance] sendDevCommand:jsonStr];
|
||||
}
|
||||
@end
|
||||
#import "DoricRemoteJSExecutor.h"
|
||||
|
||||
@interface DoricDebugJSEngine ()
|
||||
@property(nonatomic, weak) DoricWSClient *wsClient;
|
||||
@end
|
||||
|
||||
@implementation DoricDebugJSEngine
|
||||
|
||||
- (instancetype)init {
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient {
|
||||
if (self = [super init]) {
|
||||
_wsClient = wsClient;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)initJSEngine {
|
||||
[self.registry registerMonitor:[DoricDebugMonitor new]];
|
||||
self.jsExecutor = [[DoricJSRemoteExecutor alloc] init];
|
||||
self.jsExecutor = [[DoricRemoteJSExecutor alloc] initWithWSClient:self.wsClient];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -19,10 +19,12 @@
|
||||
//
|
||||
// Created by jingpeng.wang on 2020/2/25.
|
||||
//
|
||||
#import "DoricWSClient.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricDev : NSObject
|
||||
@property(nonatomic, strong) DoricWSClient *wsClient;
|
||||
+ (instancetype)instance;
|
||||
|
||||
- (void)openDevMode;
|
||||
@ -33,8 +35,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)connectDevKit:(NSString *)url;
|
||||
|
||||
- (void)sendDevCommand:(NSString *)command;
|
||||
- (void)startDebugging:(NSString *)source;
|
||||
|
||||
- (void)stopDebugging:(BOOL)resume;
|
||||
|
||||
- (void)reload:(NSString *)source script:(NSString *)script;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -20,20 +20,50 @@
|
||||
// Created by jingpeng.wang on 2020/2/25.
|
||||
//
|
||||
#import <DoricCore/Doric.h>
|
||||
#import <DoricCore/DoricContextManager.h>
|
||||
#import <DoricCore/DoricNativeDriver.h>
|
||||
#import <DoricCore/DoricConstant.h>
|
||||
#import <DoricCore/DoricContextManager.h>
|
||||
|
||||
#import "DoricDev.h"
|
||||
#import "DoricWSClient.h"
|
||||
#import "DoricDebugDriver.h"
|
||||
#import "DoricDevViewController.h"
|
||||
#import "DoricDevMonitor.h"
|
||||
|
||||
@interface DoricContextDebuggable : NSObject
|
||||
@property(nonatomic, weak) DoricContext *doricContext;
|
||||
@property(nonatomic, weak) id <DoricDriverProtocol> nativeDriver;
|
||||
@property(nonatomic, weak) DoricWSClient *wsClient;
|
||||
@end
|
||||
|
||||
@implementation DoricContextDebuggable
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)client context:(DoricContext *)context {
|
||||
if (self = [super init]) {
|
||||
_wsClient = client;
|
||||
_doricContext = context;
|
||||
_nativeDriver = context.driver;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)startDebug {
|
||||
[self.doricContext setDriver:[[DoricDebugDriver alloc] initWithWSClient:self.wsClient]];
|
||||
[self.doricContext reload:self.doricContext.script];
|
||||
}
|
||||
|
||||
- (void)stopDebug:(BOOL)resume {
|
||||
id <DoricDriverProtocol> driver = self.doricContext.driver;
|
||||
if ([driver isKindOfClass:DoricDebugDriver.class]) {
|
||||
|
||||
}
|
||||
if (resume) {
|
||||
self.doricContext.driver = self.nativeDriver;
|
||||
[self.doricContext reload:self.doricContext.script];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
@interface DoricDev ()
|
||||
@property(nonatomic, strong) DoricWSClient *wsclient;
|
||||
@property(nonatomic, strong) DoricContext *context;
|
||||
@property(nonatomic, strong) DoricDebugDriver *driver;
|
||||
@property(nonatomic, strong) DoricContextDebuggable *debuggable;
|
||||
@end
|
||||
|
||||
@implementation DoricDev
|
||||
@ -43,10 +73,6 @@ - (instancetype)init {
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onOpenEvent) name:@"OpenEvent" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onEOFEvent) name:@"EOFEvent" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onConnectExceptionEvent) name:@"ConnectExceptionEvent" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onStartDebugEvent:) name:@"StartDebugEvent" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onEnterDebugEvent) name:@"EnterDebugEvent" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onStopDebugEvent) name:@"StopDebugEvent" object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onDebuggerReadyEvent) name:@"DebuggerReadyEvent" object:nil];
|
||||
[DoricNativeDriver.instance.registry registerMonitor:[DoricDevMonitor new]];
|
||||
}
|
||||
return self;
|
||||
@ -75,25 +101,21 @@ - (void)openDevMode {
|
||||
}
|
||||
|
||||
- (void)closeDevMode {
|
||||
if (self.wsclient) {
|
||||
[self.wsclient close];
|
||||
self.wsclient = nil;
|
||||
if (self.wsClient) {
|
||||
[self.wsClient close];
|
||||
self.wsClient = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isInDevMode {
|
||||
return self.wsclient != nil;
|
||||
return self.wsClient != nil;
|
||||
}
|
||||
|
||||
- (void)connectDevKit:(NSString *)url {
|
||||
if (self.wsclient) {
|
||||
[self.wsclient close];
|
||||
if (self.wsClient) {
|
||||
[self.wsClient close];
|
||||
}
|
||||
self.wsclient = [[DoricWSClient alloc] initWithUrl:url];
|
||||
}
|
||||
|
||||
- (void)sendDevCommand:(NSString *)command {
|
||||
[self.wsclient send:command];
|
||||
self.wsClient = [[DoricWSClient alloc] initWithUrl:url];
|
||||
}
|
||||
|
||||
- (void)onOpenEvent {
|
||||
@ -108,34 +130,51 @@ - (void)onConnectExceptionEvent {
|
||||
ShowToast(@"dev kit connection exception", DoricGravityBottom);
|
||||
}
|
||||
|
||||
- (void)onStartDebugEvent:(NSNotification *)notification {
|
||||
NSString *contextId = notification.object;
|
||||
ShowToast(contextId, DoricGravityBottom);
|
||||
for (DoricContext *context in [[DoricContextManager instance] aliveContexts]) {
|
||||
BOOL result = [context.contextId compare:contextId] == NSOrderedSame;
|
||||
if (result) {
|
||||
_context = context;
|
||||
- (DoricContext *)matchContext:(NSString *)source {
|
||||
for (DoricContext *context in [DoricContextManager.instance aliveContexts]) {
|
||||
if ([source containsString:context.source] || [context.source isEqualToString:@"__dev__"]) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)reload:(NSString *)source script:(NSString *)script {
|
||||
DoricContext *context = [self matchContext:source];
|
||||
if (context) {
|
||||
if ([context.driver isKindOfClass:DoricDebugDriver.class]) {
|
||||
DoricLog(@"Context source %@ in debugging,skip reload", source);
|
||||
} else {
|
||||
DoricLog(@"Context reload :id %@,source %@", context.contextId, source);
|
||||
[context reload:script];
|
||||
}
|
||||
} else {
|
||||
DoricLog(@"Cannot find context source %@ for reload", source);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onEnterDebugEvent {
|
||||
_driver = [DoricDebugDriver new];
|
||||
}
|
||||
- (void)startDebugging:(NSString *)source {
|
||||
[self.debuggable stopDebug:YES];
|
||||
DoricContext *context = [self matchContext:source];
|
||||
if (context) {
|
||||
[self.wsClient sendToDebugger:@"DEBUG_RES" payload:@{
|
||||
@"contextId": context.contextId
|
||||
}];
|
||||
self.debuggable = [[DoricContextDebuggable alloc] initWithWSClient:self.wsClient context:context];
|
||||
[self.debuggable startDebug];
|
||||
} else {
|
||||
DoricLog(@"Cannot find context source %@ for debugging", source);
|
||||
[self.wsClient sendToDebugger:@"DEBUG_STOP" payload:@{
|
||||
@"msg": @"Cannot find suitable alive context for debugging"
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
- (void)onStopDebugEvent {
|
||||
_context.driver = [DoricNativeDriver instance];
|
||||
_context.rootNode.viewId = nil;
|
||||
[_context callEntity:DORIC_ENTITY_INIT, _context.extra, nil];
|
||||
[_context callEntity:DORIC_ENTITY_CREATE, nil];
|
||||
[_context callEntity:DORIC_ENTITY_BUILD withArgumentsArray:@[_context.initialParams]];
|
||||
}
|
||||
|
||||
- (void)onDebuggerReadyEvent {
|
||||
_context.driver = _driver;
|
||||
_context.rootNode.viewId = nil;
|
||||
[_context callEntity:DORIC_ENTITY_INIT, _context.extra, nil];
|
||||
[_context callEntity:DORIC_ENTITY_CREATE, nil];
|
||||
[_context callEntity:DORIC_ENTITY_BUILD withArgumentsArray:@[_context.initialParams]];
|
||||
- (void)stopDebugging:(BOOL)resume {
|
||||
[self.wsClient sendToDebugger:@"DEBUG_STOP" payload:@{
|
||||
@"msg": @"Stop debugging"
|
||||
}];
|
||||
[self.debuggable stopDebug:resume];
|
||||
self.debuggable = nil;
|
||||
}
|
||||
@end
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricDevMonitor.h
|
||||
// DoricDevkit
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricDevMonitor.m
|
||||
// DoricDevkit
|
||||
@ -8,7 +23,6 @@
|
||||
#import "DoricDevMonitor.h"
|
||||
|
||||
#import "DoricDev.h"
|
||||
#import "NSString+JsonString.h"
|
||||
#import "Doric.h"
|
||||
|
||||
@implementation DoricDevMonitor
|
||||
@ -16,16 +30,11 @@ - (void)onException:(NSException *)exception inContext:(DoricContext *)context {
|
||||
if (!DoricDev.instance.isInDevMode) {
|
||||
return;
|
||||
}
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"EXCEPTION",
|
||||
@"data": @{
|
||||
@"source": [context.source stringByReplacingOccurrencesOfString:@".js" withString:@".ts"],
|
||||
@"exception": exception.reason
|
||||
}
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
[[DoricDev instance] sendDevCommand:jsonStr];
|
||||
[DoricDev.instance.wsClient sendToServer:@"EXCEPTION"
|
||||
payload:@{
|
||||
@"source": [context.source stringByReplacingOccurrencesOfString:@".js" withString:@".ts"],
|
||||
@"exception": exception.reason
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)onLog:(DoricLogType)type message:(NSString *)message {
|
||||
@ -33,23 +42,16 @@ - (void)onLog:(DoricLogType)type message:(NSString *)message {
|
||||
return;
|
||||
}
|
||||
NSString *typeString = @"DEFAULT";
|
||||
if (type == DoricLogTypeDebug) {
|
||||
typeString = @"DEFAULT";
|
||||
} else if (type == DoricLogTypeWarning) {
|
||||
if (type == DoricLogTypeWarning) {
|
||||
typeString = @"WARN";
|
||||
} else if (type == DoricLogTypeError) {
|
||||
typeString = @"ERROR";
|
||||
}
|
||||
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"LOG",
|
||||
@"data": @{
|
||||
@"type": typeString,
|
||||
@"message": message
|
||||
}
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
[[DoricDev instance] sendDevCommand:jsonStr];
|
||||
[DoricDev.instance.wsClient sendToServer:@"EXCEPTION"
|
||||
payload:@{
|
||||
@"type": typeString,
|
||||
@"message": message
|
||||
}];
|
||||
}
|
||||
@end
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#import "DoricDev.h"
|
||||
#import "DoricDevViewController.h"
|
||||
#import "DoricJSRemoteExecutor.h"
|
||||
#import "QRScanViewController.h"
|
||||
|
||||
@interface DoricDevViewController () <UITableViewDelegate, UITableViewDataSource>
|
||||
@ -51,7 +50,6 @@ - (void)viewDidLoad {
|
||||
}
|
||||
if (self.isSimulator) {
|
||||
NSString *result = @"127.0.0.1";
|
||||
[DoricJSRemoteExecutor configIp:result];
|
||||
[[DoricDev instance] connectDevKit:[NSString stringWithFormat:@"ws://%@:7777", result]];
|
||||
ShowToast([NSString stringWithFormat:@"Connected to %@", result], DoricGravityBottom);
|
||||
} else {
|
||||
@ -94,9 +92,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
|
||||
@"source": [context.source stringByReplacingOccurrencesOfString:@".js" withString:@".ts"]
|
||||
}
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
[[DoricDev instance] sendDevCommand:jsonStr];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSRemoteExecutor.m
|
||||
// Doric
|
||||
//
|
||||
// Created by 王劲鹏 on 2019/10/31.
|
||||
//
|
||||
#import "DoricJSRemoteExecutor.h"
|
||||
#import "SRWebSocket.h"
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricJSRemoteArgType.h"
|
||||
#import "NSString+JsonString.h"
|
||||
|
||||
static NSString *debuggerAddress = @"";
|
||||
|
||||
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 () <SRWebSocketDelegate>
|
||||
@property(nonatomic, strong) SRWebSocket *srWebSocket;
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSString *, id> *blockMDic;
|
||||
@property(nonatomic, strong) JSValue *temp;
|
||||
@end
|
||||
|
||||
@implementation DoricJSRemoteExecutor
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
[self srWebSocket];
|
||||
_semaphore = dispatch_semaphore_create(0);
|
||||
DC_LOCK(self.semaphore);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - SRWebSocketDelegate
|
||||
- (void)webSocketDidOpen:(SRWebSocket *)webSocket {
|
||||
DoricLog(@"debugger webSocketDidOpen");
|
||||
DC_UNLOCK(self.semaphore);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"DebuggerReadyEvent" object:nil];
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload {
|
||||
DoricLog(@"debugger webSocketdidReceivePong");
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
|
||||
NSData *jsonData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
||||
NSError *err;
|
||||
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:NSJSONReadingMutableContainers
|
||||
error:&err];
|
||||
if (err) {
|
||||
DoricLog(@"debugger webSocketdidReceiveMessage parse error:%@", err);
|
||||
return;
|
||||
}
|
||||
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 {
|
||||
DoricLog(@"error:args to more than 5. args:%@",argsArr);
|
||||
}
|
||||
|
||||
} 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");
|
||||
DC_UNLOCK(self.semaphore);
|
||||
}
|
||||
|
||||
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean {
|
||||
DoricLog(@"debugger webSocketdidCloseWithCode");
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"StopDebugEvent" object:nil];
|
||||
}
|
||||
|
||||
#pragma mark - DoricJSExecutorProtocol
|
||||
- (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 {
|
||||
|
||||
NSMutableArray *argsMArr = [NSMutableArray new];
|
||||
for (id arg in args) {
|
||||
NSDictionary *dic = [self dicForArg:arg];
|
||||
[argsMArr addObject:dic];
|
||||
}
|
||||
|
||||
NSArray *argsArr = [argsMArr copy];
|
||||
|
||||
NSDictionary *jsonDic = @{
|
||||
@"cmd": @"invokeMethod",
|
||||
@"objectName": objName,
|
||||
@"functionName": funcName,
|
||||
@"values": argsArr
|
||||
};
|
||||
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:jsonDic];
|
||||
if (!jsonStr) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self.srWebSocket send:jsonStr];
|
||||
DC_LOCK(self.semaphore);
|
||||
|
||||
return self.temp;
|
||||
}
|
||||
|
||||
- (NSDictionary *)dicForArg:(id)arg {
|
||||
DoricJSRemoteArgType type = DoricargTypeWithArg(arg);
|
||||
if (type == DoricJSRemoteArgTypeObject || type == DoricJSRemoteArgTypeArray) {
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:(NSDictionary *)arg];
|
||||
arg = jsonStr;
|
||||
}
|
||||
NSDictionary *dic = @{
|
||||
@"type": @(type),
|
||||
@"value": arg
|
||||
};
|
||||
return dic;
|
||||
}
|
||||
|
||||
+ (void)configIp:(NSString *)ip {
|
||||
debuggerAddress = [[@"ws://" stringByAppendingString:ip] stringByAppendingString:@":2080"];
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
[self.srWebSocket close];
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
- (SRWebSocket *)srWebSocket {
|
||||
if (!_srWebSocket) {
|
||||
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:debuggerAddress] 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
|
@ -14,24 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricJSRemoteExecutor.h
|
||||
// Pods
|
||||
// DoricRemoteJSExecutor.h
|
||||
// DoricDevkit
|
||||
//
|
||||
// Created by 王劲鹏 on 2019/10/31.
|
||||
// Created by pengfei.zhou on 2021/2/22.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <DoricCore/DoricJSExecutorProtocol.h>
|
||||
#import "DoricWSClient.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface DoricJSRemoteExecutor : NSObject <DoricJSExecutorProtocol>
|
||||
|
||||
@property(nonatomic, strong) dispatch_semaphore_t semaphore;
|
||||
|
||||
+ (void)configIp:(NSString *)ip;
|
||||
|
||||
- (void)close;
|
||||
@interface DoricRemoteJSExecutor : NSObject <DoricJSExecutorProtocol>
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
194
doric-iOS/Devkit/Classes/DoricRemoteJSExecutor.m
Normal file
194
doric-iOS/Devkit/Classes/DoricRemoteJSExecutor.m
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// DoricRemoteJSExecutor.m
|
||||
// DoricDevkit
|
||||
//
|
||||
// Created by pengfei.zhou on 2021/2/22.
|
||||
//
|
||||
|
||||
#import "DoricRemoteJSExecutor.h"
|
||||
#import "NSString+JsonString.h"
|
||||
#import <DoricCore/Doric.h>
|
||||
|
||||
typedef NS_ENUM(NSUInteger, DoricJSRemoteArgType) {
|
||||
DoricJSRemoteArgTypeNil = 0,
|
||||
DoricJSRemoteArgTypeNumber,
|
||||
DoricJSRemoteArgTypeBool,
|
||||
DoricJSRemoteArgTypeString,
|
||||
DoricJSRemoteArgTypeObject,
|
||||
DoricJSRemoteArgTypeArray,
|
||||
};
|
||||
|
||||
|
||||
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 DoricRemoteJSExecutor () <DoricWSClientInterceptor>
|
||||
@property(nonatomic, weak) DoricWSClient *wsClient;
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSString *, id> *blockMDic;
|
||||
@property(nonatomic, strong) JSValue *temp;
|
||||
@property(nonatomic, strong) dispatch_semaphore_t semaphore;
|
||||
@end
|
||||
|
||||
@implementation DoricRemoteJSExecutor
|
||||
- (instancetype)initWithWSClient:(DoricWSClient *)wsClient {
|
||||
if (self = [super init]) {
|
||||
_wsClient = wsClient;
|
||||
[_wsClient addInterceptor:self];
|
||||
_blockMDic = [NSMutableDictionary new];
|
||||
_semaphore = dispatch_semaphore_create(0);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (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;
|
||||
[self.wsClient sendToDebugger:@"injectGlobalJSFunction" payload:@{
|
||||
@"name": name,
|
||||
}];
|
||||
} else if ([obj isKindOfClass:NSNumber.class]) {
|
||||
[self.wsClient sendToDebugger:@"injectGlobalJSObject" payload:@{
|
||||
@"name": name,
|
||||
@"type": @(DoricJSRemoteArgTypeNumber),
|
||||
@"value": obj,
|
||||
}];
|
||||
} else if ([obj isKindOfClass:NSString.class]) {
|
||||
[self.wsClient sendToDebugger:@"injectGlobalJSObject" payload:@{
|
||||
@"name": name,
|
||||
@"type": @(DoricJSRemoteArgTypeString),
|
||||
@"value": obj,
|
||||
}];
|
||||
} else if ([obj isKindOfClass:NSObject.class]) {
|
||||
[self.wsClient sendToDebugger:@"injectGlobalJSObject" payload:@{
|
||||
@"name": name,
|
||||
@"type": @(DoricJSRemoteArgTypeObject),
|
||||
@"value": obj,
|
||||
}];
|
||||
} else if ([obj isKindOfClass:NSArray.class]) {
|
||||
[self.wsClient sendToDebugger:@"injectGlobalJSObject" payload:@{
|
||||
@"name": name,
|
||||
@"type": @(DoricJSRemoteArgTypeArray),
|
||||
@"value": obj,
|
||||
}];
|
||||
} else if (obj == nil) {
|
||||
[self.wsClient sendToDebugger:@"injectGlobalJSObject" payload:@{
|
||||
@"name": name,
|
||||
@"type": @(DoricJSRemoteArgTypeNil),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (JSValue *)invokeObject:(NSString *)objName method:(NSString *)funcName args:(NSArray *)args {
|
||||
|
||||
NSMutableArray *argsMArr = [NSMutableArray new];
|
||||
|
||||
for (id arg in args) {
|
||||
NSDictionary *dic = [self dicForArg:arg];
|
||||
[argsMArr addObject:dic];
|
||||
}
|
||||
|
||||
[self.wsClient sendToDebugger:@"invokeMethod" payload:@{
|
||||
@"cmd": @"invokeMethod",
|
||||
@"objectName": objName,
|
||||
@"functionName": funcName,
|
||||
@"values": [argsMArr copy]
|
||||
}];
|
||||
|
||||
DC_LOCK(self.semaphore);
|
||||
|
||||
return self.temp;
|
||||
}
|
||||
|
||||
- (NSDictionary *)dicForArg:(id)arg {
|
||||
DoricJSRemoteArgType type = [self argType:arg];
|
||||
if (type == DoricJSRemoteArgTypeObject || type == DoricJSRemoteArgTypeArray) {
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:arg];
|
||||
arg = jsonStr;
|
||||
}
|
||||
NSDictionary *dic = @{
|
||||
@"type": @(type),
|
||||
@"value": arg
|
||||
};
|
||||
return dic;
|
||||
}
|
||||
|
||||
- (DoricJSRemoteArgType)argType:(id)arg {
|
||||
DoricJSRemoteArgType type = DoricJSRemoteArgTypeNil;
|
||||
if ([arg isKindOfClass:[NSNumber class]]) {
|
||||
type = DoricJSRemoteArgTypeNumber;
|
||||
} else if ([arg isKindOfClass:[NSString class]]) {
|
||||
type = DoricJSRemoteArgTypeString;
|
||||
} else if ([arg isKindOfClass:[NSDictionary class]]) {
|
||||
type = DoricJSRemoteArgTypeObject;
|
||||
} else if ([arg isKindOfClass:[NSMutableArray class]]) {
|
||||
type = DoricJSRemoteArgTypeArray;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
- (BOOL)interceptType:(NSString *)type command:(NSString *)cmd payload:(NSDictionary *)payload {
|
||||
if ([type isEqualToString:@"D2C"]) {
|
||||
if ([cmd isEqualToString:@"injectGlobalJSFunction"]) {
|
||||
NSString *name = payload[@"name"];
|
||||
NSArray *argsArr = payload[@"arguments"];
|
||||
id tmpBlk = self.blockMDic[name];
|
||||
id result;
|
||||
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 {
|
||||
DoricLog(@"error:args to more than 5. args:%@", argsArr);
|
||||
result = nil;
|
||||
}
|
||||
} else if ([cmd isEqualToString:@"invokeMethod"]) {
|
||||
@try {
|
||||
self.temp = [JSValue valueWithObject:payload[@"result"] inContext:nil];
|
||||
} @catch (NSException *exception) {
|
||||
DoricLog(@"debugger ", NSStringFromSelector(_cmd), exception.reason);
|
||||
} @finally {
|
||||
DC_UNLOCK(self.semaphore);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
@end
|
@ -24,12 +24,22 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol DoricWSClientInterceptor <NSObject>
|
||||
- (BOOL)interceptType:(NSString *)type command:(NSString *)cmd payload:(NSDictionary *)payload;
|
||||
@end
|
||||
|
||||
@interface DoricWSClient : NSObject
|
||||
- (instancetype)initWithUrl:(NSString *)url;
|
||||
|
||||
- (void)send:(NSString *)command;
|
||||
|
||||
- (void)close;
|
||||
|
||||
- (void)addInterceptor:(id <DoricWSClientInterceptor>)interceptor;
|
||||
|
||||
- (void)removeInterceptor:(id <DoricWSClientInterceptor>)interceptor;
|
||||
|
||||
- (void)sendToDebugger:(NSString *)cmd payload:(NSDictionary *)payload;
|
||||
|
||||
- (void)sendToServer:(NSString *)cmd payload:(NSDictionary *)payload;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -22,16 +22,20 @@
|
||||
|
||||
#import "DoricWSClient.h"
|
||||
#import "SRWebSocket.h"
|
||||
#import "DoricUtil.h"
|
||||
#import "DoricContextManager.h"
|
||||
#import <DoricCore/Doric.h>
|
||||
#import <DoricCore/DoricContextManager.h>
|
||||
#import <DoricCore/NSString+JsonString.h>
|
||||
#import "DoricDev.h"
|
||||
|
||||
@interface DoricWSClient () <SRWebSocketDelegate>
|
||||
@property(nonatomic, strong) SRWebSocket *websocket;
|
||||
@property(nonatomic, strong) NSHashTable <id <DoricWSClientInterceptor>> *interceptors;
|
||||
@end
|
||||
|
||||
@implementation DoricWSClient
|
||||
- (instancetype)initWithUrl:(NSString *)url {
|
||||
if (self = [super init]) {
|
||||
_interceptors = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
|
||||
_websocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:url]];
|
||||
_websocket.delegate = self;
|
||||
[_websocket open];
|
||||
@ -58,7 +62,27 @@ - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message {
|
||||
DoricLog(@"webSocketdidReceiveMessage parse error:%@", err);
|
||||
return;
|
||||
}
|
||||
NSString *cmd = [[dic valueForKey:@"cmd"] mutableCopy];
|
||||
|
||||
NSString *type = dic[@"type"];
|
||||
NSString *cmd = dic[@"cmd"];
|
||||
NSDictionary *payload = dic[@"payload"];
|
||||
for (id <DoricWSClientInterceptor> interceptor in self.interceptors) {
|
||||
if ([interceptor interceptType:type command:cmd payload:payload]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ([cmd isEqualToString:@"DEBUG_REQ"]) {
|
||||
NSString *source = payload[@"source"];
|
||||
[DoricDev.instance startDebugging:source];
|
||||
} else if ([cmd isEqualToString:@"DEBUG_STOP"]) {
|
||||
[DoricDev.instance stopDebugging:YES];
|
||||
} else if ([cmd isEqualToString:@"RELOAD"]) {
|
||||
NSString *source = payload[@"source"];
|
||||
NSString *script = payload[@"script"];
|
||||
[DoricDev.instance reload:source script:script];
|
||||
}
|
||||
|
||||
if ([cmd compare:@"SWITCH_TO_DEBUG"] == NSOrderedSame) {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"EnterDebugEvent" object:nil];
|
||||
} else if ([cmd compare:@"RELOAD"] == NSOrderedSame) {
|
||||
@ -82,8 +106,33 @@ - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reas
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"EOFEvent" object:nil];
|
||||
}
|
||||
|
||||
- (void)send:(NSString *)command {
|
||||
[_websocket send:command];
|
||||
- (void)send:(NSDictionary *)command {
|
||||
NSString *jsonStr = [NSString dc_convertToJsonWithDic:command];
|
||||
[_websocket send:jsonStr];
|
||||
}
|
||||
|
||||
- (void)addInterceptor:(id <DoricWSClientInterceptor>)interceptor {
|
||||
[self.interceptors addObject:interceptor];
|
||||
}
|
||||
|
||||
- (void)removeInterceptor:(id <DoricWSClientInterceptor>)interceptor {
|
||||
[self.interceptors removeObject:interceptor];
|
||||
}
|
||||
|
||||
- (void)sendToDebugger:(NSString *)cmd payload:(NSDictionary *)payload {
|
||||
[self send:@{
|
||||
@"type": @"C2D",
|
||||
@"cmd": cmd,
|
||||
@"payload": payload,
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)sendToServer:(NSString *)cmd payload:(NSDictionary *)payload {
|
||||
[self send:@{
|
||||
@"type": @"C2S",
|
||||
@"cmd": cmd,
|
||||
@"payload": payload,
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
|
@ -24,7 +24,6 @@
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <DoricCore/Doric.h>
|
||||
#import <DoricDevkit/DoricDev.h>
|
||||
#import "DoricJSRemoteExecutor.h"
|
||||
|
||||
@interface QRScanViewController () <AVCaptureMetadataOutputObjectsDelegate>
|
||||
@property(strong, nonatomic) AVCaptureDevice *device;
|
||||
@ -105,7 +104,6 @@ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:
|
||||
NSString *result = qrObject.stringValue;
|
||||
NSLog(@"Scan result is %@", result);
|
||||
[[DoricDev instance] connectDevKit:[NSString stringWithFormat:@"ws://%@:7777", result]];
|
||||
[DoricJSRemoteExecutor configIp:result];
|
||||
ShowToast([NSString stringWithFormat:@"Connected to %@", result], DoricGravityBottom);
|
||||
[self.navigationController popViewControllerAnimated:NO];
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (JSValue *)invokeDoricMethod:(NSString *)method argumentsArray:(NSArray *)args;
|
||||
|
||||
- (void)ensureRunOnJSThread:(dispatch_block_t)block;
|
||||
|
||||
- (void)initJSEngine;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -96,6 +96,7 @@ - (instancetype)init {
|
||||
[self initJSExecutor];
|
||||
[self initDoricEnvironment];
|
||||
}];
|
||||
[self.registry registerMonitor:[DoricDefaultMonitor new]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -126,7 +127,6 @@ - (void)threadRun {
|
||||
}
|
||||
|
||||
- (void)initJSEngine {
|
||||
[self.registry registerMonitor:[DoricDefaultMonitor new]];
|
||||
self.jsExecutor = [DoricJSCoreExecutor new];
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSString (JsonString)
|
||||
+ (NSString *)dc_convertToJsonWithDic:(NSDictionary *)dic;
|
||||
+ (NSString *)dc_convertToJsonWithDic:(id)obj;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -9,11 +9,11 @@
|
||||
#import "DoricUtil.h"
|
||||
|
||||
@implementation NSString (JsonString)
|
||||
+ (NSString *)dc_convertToJsonWithDic:(NSDictionary *)dic {
|
||||
+ (NSString *)dc_convertToJsonWithDic:(id)obj {
|
||||
NSError *err;
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&err];
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj 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;
|
||||
|
@ -1,24 +0,0 @@
|
||||
//
|
||||
// DoricJSRemoteArgType.h
|
||||
// Doric
|
||||
//
|
||||
// Created by Insomnia on 2019/11/7.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, DoricJSRemoteArgType) {
|
||||
DoricJSRemoteArgTypeNil = 0,
|
||||
DoricJSRemoteArgTypeNumber,
|
||||
DoricJSRemoteArgTypeBool,
|
||||
DoricJSRemoteArgTypeString,
|
||||
DoricJSRemoteArgTypeObject,
|
||||
DoricJSRemoteArgTypeArray,
|
||||
};
|
||||
|
||||
DoricJSRemoteArgType DoricargTypeWithArg(id arg);
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -1,21 +0,0 @@
|
||||
//
|
||||
// DoricJSRemoteArgType.m
|
||||
// Doric
|
||||
//
|
||||
// Created by Insomnia on 2019/11/7.
|
||||
//
|
||||
|
||||
#import "DoricJSRemoteArgType.h"
|
||||
DoricJSRemoteArgType DoricargTypeWithArg(id arg) {
|
||||
DoricJSRemoteArgType type = DoricJSRemoteArgTypeNil;
|
||||
if ([arg isKindOfClass:[NSNumber class]]) {
|
||||
type = DoricJSRemoteArgTypeNumber;
|
||||
}else if ([arg isKindOfClass:[NSString class]]) {
|
||||
type = DoricJSRemoteArgTypeString;
|
||||
}else if ([arg isKindOfClass:[NSDictionary class]]) {
|
||||
type = DoricJSRemoteArgTypeObject;
|
||||
}else if ([arg isKindOfClass:[NSMutableArray class]]) {
|
||||
type = DoricJSRemoteArgTypeArray;
|
||||
}
|
||||
return type;
|
||||
}
|
Reference in New Issue
Block a user