2
0
Эх сурвалжийг харах

DevTools: embedded DevTools for hlprofile view

Yuxiao Mao 2 сар өмнө
parent
commit
46d1f2051b

+ 1 - 0
bin/app.html

@@ -110,6 +110,7 @@
 		<separator></separator>
 		<menu label="Memory profiler" class="memprof"></menu>
 		<menu label="Remote console" class="remoteconsole"></menu>
+		<menu label="DevTools" class="devtools"></menu>
 		<menu label="Gpu mem dump" class="gpudump"></menu>
 	</menu>
 	<menu label="Settings" class="settings">

+ 8 - 0
bin/blank.html

@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<!-- Blank source used by DevTools.hx, do not remove -->
+</body>
+</html>

+ 10 - 0
bin/package.json

@@ -12,5 +12,15 @@
 	"js-flags": "--expose-gc",
 	"dependencies": {
 		"mongodb": "^3.2.2"
+	},
+	"webview": {
+		"partitions": [
+			{
+				"name": "trusted",
+				"accessible_resources": [
+					"<all_urls>"
+				]
+			}
+		]
 	}
 }

+ 13 - 0
bin/style.css

@@ -3522,6 +3522,19 @@ div.gradient-box {
   cursor: pointer;
   text-align: center;
 }
+.devtools {
+  width: 100%;
+  height: 100%;
+}
+.devtools webview {
+  display: block;
+}
+.devtools #webview-blank {
+  height: 0px;
+}
+.devtools #webview-devtools {
+  height: 100%;
+}
 .hover-parent .hover-reveal {
   visibility: hidden;
 }

+ 14 - 0
bin/style.less

@@ -4141,6 +4141,20 @@ div.gradient-box {
 	}
 }
 
+.devtools {
+	width: 100%;
+	height: 100%;
+	webview {
+		display: block;
+	}
+	#webview-blank {
+		height: 0px;
+	}
+	#webview-devtools {
+		height: 100%;
+	}
+}
+
 .hover-parent {
 	.hover-reveal {
 		visibility: hidden;

+ 3 - 0
hide/Ide.hx

@@ -1435,6 +1435,9 @@ class Ide extends hide.tools.IdeData {
 		analysis.find(".remoteconsole").click(function(_) {
 			open("hide.view.RemoteConsoleView",{});
 		});
+		analysis.find(".devtools").click(function(_) {
+			open("hide.view.DevTools",{});
+		});
 		analysis.find(".gpudump").click(function(_) {
 			var path = hide.tools.MemDump.gpudump();
 			quickMessage('Gpu mem dumped at ${path}.');

+ 92 - 0
hide/view/DevTools.hx

@@ -0,0 +1,92 @@
+package hide.view;
+
+class DevTools extends hide.ui.View<{ profileFilePath : String }> {
+	var devtools : Element.HTMLElement;
+
+	public function new( ?state ) {
+		super(state);
+	}
+
+	override function onDisplay() {
+		new Element('
+		<div class="devtools">
+			<webview id="webview-blank" src="blank.html" partition="persist:trusted"></webview>
+			<webview id="webview-devtools" src="about:blank" partition="persist:trusted"></webview>
+		</div>').appendTo(element);
+		var blank = element.find("#webview-blank").get(0);
+		devtools = element.find("#webview-devtools").get(0);
+		var openCalled = false;
+		var blankLoaded = false;
+		var devtoolsLoaded = false;
+		function tryOpen() {
+			if( openCalled || !blankLoaded || !devtoolsLoaded )
+				return;
+			openCalled = true;
+			showDevTools(blank, true, devtools);
+			// wait for devTools ready
+			haxe.Timer.delay(() -> openProfile(), 500);
+		}
+		blank.addEventListener("contentload", function() {
+			blankLoaded = true;
+			tryOpen();
+		});
+		devtools.addEventListener("contentload", function() {
+			devtoolsLoaded = true;
+			tryOpen();
+		});
+	}
+
+	override function buildTabMenu():Array<hide.comp.ContextMenu.MenuItem> {
+		var menu = super.buildTabMenu();
+		menu.push({isSeparator: true});
+		menu.push({label: "Debug", click: () -> {
+			showDevTools(devtools, true);
+		}});
+		return menu;
+	}
+
+	public function openProfile() {
+		if( this.state.profileFilePath == null )
+			return;
+		try {
+			var unsafeContent = sys.io.File.getContent(this.state.profileFilePath);
+			// ensure that it's really a json
+			var fileContent = haxe.Json.stringify(haxe.Json.parse(unsafeContent));
+			unsafeExecuteScript('
+var tmp = {};
+tmp.fileContent = `${fileContent}`;
+tmp.dataT = new DataTransfer();
+tmp.dataT.items.add(new File([tmp.fileContent], "profile.json", {type: "application/json"}))
+document.elementFromPoint(0, 0).shadowRoot.getElementById("tab-timeline").dispatchEvent(new MouseEvent("mousedown", {isTrusted: true, button: 0}));
+setTimeout(function() {
+	document.getElementsByClassName("timeline")[0].dispatchEvent(new DragEvent("dragover", {dataTransfer: tmp.dataT}));
+	document.getElementsByClassName("timeline")[0].lastChild.dispatchEvent(new DragEvent("drop", {dataTransfer: tmp.dataT}));
+}, 100);
+			');
+		} catch( e ) {
+			ide.error("Unable to open profile: " + e.message);
+			this.state.profileFilePath = null;
+			saveState();
+			syncTitle();
+		}
+
+	}
+
+	inline function showDevTools( webview : Element.HTMLElement, show : Bool, ?container : Element.HTMLElement ) {
+		js.Syntax.code("{0}.showDevTools({1}, {2});", webview, show, container);
+	}
+
+	inline function unsafeExecuteScript( script : String ) {
+		js.Syntax.code("{0}.executeScript({ code: {1}, mainWorld: false });", devtools, script);
+	}
+
+	override function getTitle() {
+		if( this.state.profileFilePath != null ) {
+			var file = haxe.io.Path.withoutDirectory(this.state.profileFilePath);
+			return "DevTools:" + file;
+		}
+		return "DevTools";
+	}
+
+	static var _ = hide.ui.View.register(DevTools);
+}

+ 17 - 1
hide/view/RemoteConsoleView.hx

@@ -441,6 +441,9 @@ class RemoteConsoleCommandHL extends RemoteConsoleCommand {
 				panel.log("CPU profiling started");
 			});
 		});
+		#if (hashlink >= "1.15.0")
+		var openBtn = new Element('<div class="ico ico-share-square-o disable" title="Open in DevTools"/>');
+		#end
 		var dump = new RemoteConsoleSubCommandDump(panel, function(onResult) {
 			panel.sendCommand("profCpu", { action : "dump" }, function(r) {
 				var dir = (panel.peerCwd ?? hide.Ide.inst.projectDir) + "/";
@@ -450,6 +453,7 @@ class RemoteConsoleCommandHL extends RemoteConsoleCommand {
 					var outfile = "hlprofile.json";
 					hlprof.ProfileGen.run([dir + file, "-o", dir + outfile]);
 					file = outfile;
+					openBtn.removeClass("disable");
 				} catch (e) {
 					panel.log(e.message, true);
 				}
@@ -458,7 +462,19 @@ class RemoteConsoleCommandHL extends RemoteConsoleCommand {
 				#end
 				onResult(file, "Profile dump");
 			});
-		}).element.appendTo(subcmd);
+		});
+		dump.element.appendTo(subcmd);
+		#if (hashlink >= "1.15.0")
+		openBtn.on('click', function(e) {
+			var file = dump.dumpFile.val();
+			if( file.length > 0 && sys.FileSystem.exists(file) ) {
+				ide.open("hide.view.DevTools", {profileFilePath : file}, null);
+			} else {
+				panel.log('File $file does not exist', true);
+			}
+		});
+		openBtn.appendTo(dump.element);
+		#end
 		var subcmd = new Element('<div class="sub-command">
 			<h5>Prof Alloc</h5>
 		</div>').appendTo(element);