feat:add debug option:start debugging

This commit is contained in:
pengfei.zhou 2021-03-02 15:11:16 +08:00 committed by osborn
parent de4188b74e
commit cf888e3655
7 changed files with 117 additions and 22 deletions

View File

@ -142,6 +142,12 @@ public class DoricDev {
} }
} }
public void requestDebugging(DoricContext context) {
wsClient.sendToServer("DEBUG", new JSONBuilder()
.put("source", context.getSource())
.toJSONObject());
}
public void stopDebugging(boolean resume) { public void stopDebugging(boolean resume) {
wsClient.sendToDebugger("DEBUG_STOP", new JSONBuilder() wsClient.sendToDebugger("DEBUG_STOP", new JSONBuilder()
.put("msg", "Stop debugging") .put("msg", "Stop debugging")

View File

@ -301,8 +301,12 @@ public class DoricDevActivity extends AppCompatActivity implements DoricDev.Stat
public void onClick(View v) { public void onClick(View v) {
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
list.add("View source"); list.add("View source");
if (context.getDriver() instanceof DoricDebugDriver) { if (DoricDev.getInstance().isInDevMode()) {
list.add("Stop debugging"); if (context.getDriver() instanceof DoricDebugDriver) {
list.add("Stop debugging");
} else {
list.add("Start debugging");
}
} }
final String[] items = list.toArray(new String[0]); final String[] items = list.toArray(new String[0]);
AlertDialog.Builder builder = new AlertDialog.Builder(holder.itemView.getContext(), R.style.Theme_Doric_Modal); AlertDialog.Builder builder = new AlertDialog.Builder(holder.itemView.getContext(), R.style.Theme_Doric_Modal);
@ -333,6 +337,8 @@ public class DoricDevActivity extends AppCompatActivity implements DoricDev.Stat
builder.show(); builder.show();
} else if ("Stop debugging".equals(items[which])) { } else if ("Stop debugging".equals(items[which])) {
DoricDev.getInstance().stopDebugging(true); DoricDev.getInstance().stopDebugging(true);
} else if ("Start debugging".equals(items[which])) {
DoricDev.getInstance().requestDebugging(context);
} }
dialog.dismiss(); dialog.dismiss();
} }

View File

@ -3,6 +3,7 @@ import "colors";
import path from "path"; import path from "path";
import { glob } from "./util"; import { glob } from "./util";
import { Shell } from "./shell"; import { Shell } from "./shell";
import { ChildProcess, } from "child_process";
export type MSG = { export type MSG = {
type: "D2C" | "C2D" | "C2S" | "D2S" | "S2C" | "S2D", type: "D2C" | "C2D" | "C2S" | "D2S" | "S2C" | "S2D",
@ -14,6 +15,7 @@ export async function createServer() {
let client: WebSocket | undefined = undefined; let client: WebSocket | undefined = undefined;
let debug: WebSocket | undefined = undefined; let debug: WebSocket | undefined = undefined;
let deviceId = 0 let deviceId = 0
let debugProcess: ChildProcess | undefined = undefined;
const wss = new WebSocket.Server({ port: 7777 }) const wss = new WebSocket.Server({ port: 7777 })
.on("connection", (ws, request) => { .on("connection", (ws, request) => {
let thisDeviceId: string let thisDeviceId: string
@ -50,6 +52,7 @@ export async function createServer() {
} else if (resultObject.type === "C2D") { } else if (resultObject.type === "C2D") {
if (resultObject.cmd === "DEBUG_STOP") { if (resultObject.cmd === "DEBUG_STOP") {
client = undefined; client = undefined;
debugProcess?.kill(0);
} }
if (client === undefined) { if (client === undefined) {
client = ws; client = ws;
@ -61,23 +64,33 @@ export async function createServer() {
switch (resultObject.cmd) { switch (resultObject.cmd) {
case 'DEBUG': case 'DEBUG':
let source = resultObject.payload.source as string; let source = resultObject.payload.source as string;
if (source.endsWith(".js")) { if (source.endsWith(".ts")) {
source = source.replace(".js", ".ts"); source = source.replace(".ts", ".js");
} else if (!source.endsWith(".ts")) { } else if (!source.endsWith(".js")) {
source = source + ".ts" source = source + ".js"
} }
const tsFiles = await glob(`**/${source}`, { const jsFile = await glob(`**/${source}`, {
cwd: path.resolve(process.cwd(), "src") cwd: path.resolve(process.cwd(), "bundle")
}) })
if (!!!tsFiles || tsFiles.length === 0) { if (!!!jsFile || jsFile.length === 0) {
console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "src")}`); console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "bundle")}`);
} }
const sourceFile = tsFiles[0]; const debuggingFile = path.resolve(process.cwd(), "bundle", jsFile[0]);
Shell.exec("node", [ debugProcess = await Shell.execProcess(
"--inspect-brk", "node",
path.resolve(process.cwd(), "src", sourceFile) [
]) "--inspect-brk",
console.log(`Debugger on ${sourceFile}`); debuggingFile,
],
{
env: process.env,
consoleHandler: (log) => {
console.log(`Debugger>>>`.gray, log);
}
}
)
console.log(`Debugger on ${debuggingFile}`.green);
console.log(`Please open Chrome`);
break; break;
case 'EXCEPTION': case 'EXCEPTION':
console.log(resultObject.payload.source.red); console.log(resultObject.payload.source.red);

View File

@ -1,4 +1,4 @@
import { spawn, SpawnOptionsWithoutStdio } from "child_process"; import { ChildProcess, spawn, SpawnOptionsWithoutStdio } from "child_process";
import "colors"; import "colors";
const debug = false const debug = false
export namespace Shell { export namespace Shell {
@ -59,6 +59,61 @@ export namespace Shell {
}); });
}); });
} }
export async function execProcess(
command: string,
args?: ReadonlyArray<string>,
options?: SpawnOptionsWithoutStdio & {
silence?: boolean; //不打印耗时,默认为false
verbose?: boolean; //打印输出内容,默认为true
consoleHandler?: (info: string) => void; //命令行输出内容处理
}
): Promise<ChildProcess> {
if (!options?.silence) {
debug && console.log(`>>>>>>>>${command} ${args ? args.join(" ") : ""}`);
}
const now = new Date().getTime();
return new Promise((resolve) => {
const cmd = spawn(command, args, options);
cmd.stdout.on("data", (data) => {
if (options?.verbose !== false) {
debug && console.log(data.toString());
}
if (options?.consoleHandler) {
options.consoleHandler(data.toString());
}
});
cmd.stderr.on("data", (data) => {
if (options?.verbose !== false) {
debug && console.error(data.toString());
}
if (options?.consoleHandler) {
options.consoleHandler(data.toString());
}
});
cmd.on("close", (code) => {
if (!options?.silence) {
const cost = new Date().getTime() - now;
if (code !== 0) {
debug && console.log(`exitCode:${code} 耗时 ${cost}ms <<<<<<<<`.red);
} else {
debug && console.log(`exitCode:${code} 耗时 ${cost}ms <<<<<<<<`);
}
}
});
cmd.on("error", (err) => {
if (!options?.silence) {
const cost = new Date().getTime() - now;
debug && console.log(`error:${err} 耗时 ${cost}ms <<<<<<<<`);
}
});
resolve(cmd);
});
}
export async function exec( export async function exec(
command: string, command: string,
args?: ReadonlyArray<string>, args?: ReadonlyArray<string>,

View File

@ -61,6 +61,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)stopDebugging:(BOOL)resume; - (void)stopDebugging:(BOOL)resume;
- (void)requestDebugging:(DoricContext *)context;
- (BOOL)isReloadingContext:(DoricContext *)context; - (BOOL)isReloadingContext:(DoricContext *)context;
- (void)reload:(NSString *)source script:(NSString *)script; - (void)reload:(NSString *)source script:(NSString *)script;

View File

@ -227,6 +227,12 @@ - (void)stopDebugging:(BOOL)resume {
}); });
} }
- (void)requestDebugging:(DoricContext *)context {
[self.wsClient sendToServer:@"DEBUG" payload:@{
@"source": context.source
}];
}
- (void)sendDevCommand:(NSString *)command payload:(NSDictionary *)payload { - (void)sendDevCommand:(NSString *)command payload:(NSDictionary *)payload {
[self.wsClient sendToServer:command payload:payload]; [self.wsClient sendToServer:command payload:payload];
} }

View File

@ -105,11 +105,18 @@ - (void)onClick {
}]; }];
[alertController addAction:cancel]; [alertController addAction:cancel];
[alertController addAction:viewSource]; [alertController addAction:viewSource];
if ([self.doricContext.driver isKindOfClass:DoricDebugDriver.class]) { if (DoricDev.instance.isInDevMode) {
UIAlertAction *stopDebugging = [UIAlertAction actionWithTitle:@"Stop debugging" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) { if ([self.doricContext.driver isKindOfClass:DoricDebugDriver.class]) {
[DoricDev.instance stopDebugging:YES]; UIAlertAction *stopDebugging = [UIAlertAction actionWithTitle:@"Stop debugging" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) {
}]; [DoricDev.instance stopDebugging:YES];
[alertController addAction:stopDebugging]; }];
[alertController addAction:stopDebugging];
} else {
UIAlertAction *startDebugging = [UIAlertAction actionWithTitle:@"Start debugging" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) {
[DoricDev.instance requestDebugging:self.doricContext];
}];
[alertController addAction:startDebugging];
}
} }
[self.vc presentViewController:alertController animated:true completion:nil]; [self.vc presentViewController:alertController animated:true completion:nil];