diff --git a/doric-android/devkit/src/main/java/pub/doric/devkit/DoricDev.java b/doric-android/devkit/src/main/java/pub/doric/devkit/DoricDev.java index e4a4a33b..3415603a 100644 --- a/doric-android/devkit/src/main/java/pub/doric/devkit/DoricDev.java +++ b/doric-android/devkit/src/main/java/pub/doric/devkit/DoricDev.java @@ -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) { wsClient.sendToDebugger("DEBUG_STOP", new JSONBuilder() .put("msg", "Stop debugging") diff --git a/doric-android/devkit/src/main/java/pub/doric/devkit/ui/DoricDevActivity.java b/doric-android/devkit/src/main/java/pub/doric/devkit/ui/DoricDevActivity.java index e5d6ac6d..112ec9b0 100644 --- a/doric-android/devkit/src/main/java/pub/doric/devkit/ui/DoricDevActivity.java +++ b/doric-android/devkit/src/main/java/pub/doric/devkit/ui/DoricDevActivity.java @@ -301,8 +301,12 @@ public class DoricDevActivity extends AppCompatActivity implements DoricDev.Stat public void onClick(View v) { ArrayList list = new ArrayList<>(); list.add("View source"); - if (context.getDriver() instanceof DoricDebugDriver) { - list.add("Stop debugging"); + if (DoricDev.getInstance().isInDevMode()) { + if (context.getDriver() instanceof DoricDebugDriver) { + list.add("Stop debugging"); + } else { + list.add("Start debugging"); + } } final String[] items = list.toArray(new String[0]); 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(); } else if ("Stop debugging".equals(items[which])) { DoricDev.getInstance().stopDebugging(true); + } else if ("Start debugging".equals(items[which])) { + DoricDev.getInstance().requestDebugging(context); } dialog.dismiss(); } diff --git a/doric-cli/src/server.ts b/doric-cli/src/server.ts index 2670f06d..eb10ca65 100644 --- a/doric-cli/src/server.ts +++ b/doric-cli/src/server.ts @@ -3,6 +3,7 @@ import "colors"; import path from "path"; import { glob } from "./util"; import { Shell } from "./shell"; +import { ChildProcess, } from "child_process"; export type MSG = { type: "D2C" | "C2D" | "C2S" | "D2S" | "S2C" | "S2D", @@ -14,6 +15,7 @@ export async function createServer() { let client: WebSocket | undefined = undefined; let debug: WebSocket | undefined = undefined; let deviceId = 0 + let debugProcess: ChildProcess | undefined = undefined; const wss = new WebSocket.Server({ port: 7777 }) .on("connection", (ws, request) => { let thisDeviceId: string @@ -50,6 +52,7 @@ export async function createServer() { } else if (resultObject.type === "C2D") { if (resultObject.cmd === "DEBUG_STOP") { client = undefined; + debugProcess?.kill(0); } if (client === undefined) { client = ws; @@ -61,23 +64,33 @@ export async function createServer() { 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" + if (source.endsWith(".ts")) { + source = source.replace(".ts", ".js"); + } else if (!source.endsWith(".js")) { + source = source + ".js" } - const tsFiles = await glob(`**/${source}`, { - cwd: path.resolve(process.cwd(), "src") + const jsFile = await glob(`**/${source}`, { + cwd: path.resolve(process.cwd(), "bundle") }) - if (!!!tsFiles || tsFiles.length === 0) { - console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "src")}`); + if (!!!jsFile || jsFile.length === 0) { + console.error(`Cannot find ${source} in ${path.resolve(process.cwd(), "bundle")}`); } - const sourceFile = tsFiles[0]; - Shell.exec("node", [ - "--inspect-brk", - path.resolve(process.cwd(), "src", sourceFile) - ]) - console.log(`Debugger on ${sourceFile}`); + const debuggingFile = path.resolve(process.cwd(), "bundle", jsFile[0]); + debugProcess = await Shell.execProcess( + "node", + [ + "--inspect-brk", + debuggingFile, + ], + { + env: process.env, + consoleHandler: (log) => { + console.log(`Debugger>>>`.gray, log); + } + } + ) + console.log(`Debugger on ${debuggingFile}`.green); + console.log(`Please open Chrome`); break; case 'EXCEPTION': console.log(resultObject.payload.source.red); diff --git a/doric-cli/src/shell.ts b/doric-cli/src/shell.ts index 76442d3e..7ba4fd9e 100644 --- a/doric-cli/src/shell.ts +++ b/doric-cli/src/shell.ts @@ -1,4 +1,4 @@ -import { spawn, SpawnOptionsWithoutStdio } from "child_process"; +import { ChildProcess, spawn, SpawnOptionsWithoutStdio } from "child_process"; import "colors"; const debug = false export namespace Shell { @@ -59,6 +59,61 @@ export namespace Shell { }); }); } + + export async function execProcess( + command: string, + args?: ReadonlyArray, + options?: SpawnOptionsWithoutStdio & { + silence?: boolean; //不打印耗时,默认为false + verbose?: boolean; //打印输出内容,默认为true + consoleHandler?: (info: string) => void; //命令行输出内容处理 + } + ): Promise { + 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( command: string, args?: ReadonlyArray, diff --git a/doric-iOS/Devkit/Classes/DoricDev.h b/doric-iOS/Devkit/Classes/DoricDev.h index bf792219..ff13a1c1 100644 --- a/doric-iOS/Devkit/Classes/DoricDev.h +++ b/doric-iOS/Devkit/Classes/DoricDev.h @@ -61,6 +61,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)stopDebugging:(BOOL)resume; +- (void)requestDebugging:(DoricContext *)context; + - (BOOL)isReloadingContext:(DoricContext *)context; - (void)reload:(NSString *)source script:(NSString *)script; diff --git a/doric-iOS/Devkit/Classes/DoricDev.m b/doric-iOS/Devkit/Classes/DoricDev.m index fcf85765..8e1b2609 100644 --- a/doric-iOS/Devkit/Classes/DoricDev.m +++ b/doric-iOS/Devkit/Classes/DoricDev.m @@ -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 { [self.wsClient sendToServer:command payload:payload]; } diff --git a/doric-iOS/Devkit/Classes/DoricDevViewController.m b/doric-iOS/Devkit/Classes/DoricDevViewController.m index 4dfd270c..f7bcfeba 100644 --- a/doric-iOS/Devkit/Classes/DoricDevViewController.m +++ b/doric-iOS/Devkit/Classes/DoricDevViewController.m @@ -105,11 +105,18 @@ - (void)onClick { }]; [alertController addAction:cancel]; [alertController addAction:viewSource]; - if ([self.doricContext.driver isKindOfClass:DoricDebugDriver.class]) { - UIAlertAction *stopDebugging = [UIAlertAction actionWithTitle:@"Stop debugging" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) { - [DoricDev.instance stopDebugging:YES]; - }]; - [alertController addAction:stopDebugging]; + if (DoricDev.instance.isInDevMode) { + if ([self.doricContext.driver isKindOfClass:DoricDebugDriver.class]) { + UIAlertAction *stopDebugging = [UIAlertAction actionWithTitle:@"Stop debugging" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) { + [DoricDev.instance stopDebugging:YES]; + }]; + [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];