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

Add WebSocket debugger, use it for Javascript.

Fabio Alessandrelli 5 жил өмнө
parent
commit
3097c2da96

+ 2 - 1
misc/dist/html/fixed-size.html

@@ -232,6 +232,7 @@ $GODOT_HEAD_INCLUDE
 
 			const EXECUTABLE_NAME = '$GODOT_BASENAME';
 			const MAIN_PACK = '$GODOT_BASENAME.pck';
+			const EXTRA_ARGS = JSON.parse('$GODOT_ARGS');
 			const DEBUG_ENABLED = $GODOT_DEBUG_ENABLED;
 			const INDETERMINATE_STATUS_STEP_MS = 100;
 
@@ -382,7 +383,7 @@ $GODOT_HEAD_INCLUDE
 			} else {
 				setStatusMode('indeterminate');
 				engine.setCanvas(canvas);
-				engine.startGame(EXECUTABLE_NAME, MAIN_PACK).then(() => {
+				engine.startGame(EXECUTABLE_NAME, MAIN_PACK, EXTRA_ARGS).then(() => {
 					setStatusMode('hidden');
 					initializing = false;
 				}, displayFailureNotice);

+ 2 - 1
misc/dist/html/full-size.html

@@ -145,6 +145,7 @@ $GODOT_HEAD_INCLUDE
 
 			const EXECUTABLE_NAME = '$GODOT_BASENAME';
 			const MAIN_PACK = '$GODOT_BASENAME.pck';
+			const EXTRA_ARGS = JSON.parse('$GODOT_ARGS');
 			const INDETERMINATE_STATUS_STEP_MS = 100;
 
 			var canvas = document.getElementById('canvas');
@@ -254,7 +255,7 @@ $GODOT_HEAD_INCLUDE
 			} else {
 				setStatusMode('indeterminate');
 				engine.setCanvas(canvas);
-				engine.startGame(EXECUTABLE_NAME, MAIN_PACK).then(() => {
+				engine.startGame(EXECUTABLE_NAME, MAIN_PACK, EXTRA_ARGS).then(() => {
 					setStatusMode('hidden');
 					initializing = false;
 				}, displayFailureNotice);

+ 92 - 0
modules/websocket/editor_debugger_server_websocket.cpp

@@ -0,0 +1,92 @@
+/*************************************************************************/
+/*  script_editor_debugger_websocket.cpp                                 */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "editor_debugger_server_websocket.h"
+
+#include "core/project_settings.h"
+#include "editor/editor_settings.h"
+#include "modules/websocket/remote_debugger_peer_websocket.h"
+
+void EditorDebuggerServerWebSocket::_peer_connected(int p_id, String _protocol) {
+	pending_peers.push_back(p_id);
+}
+
+void EditorDebuggerServerWebSocket::_peer_disconnected(int p_id, bool p_was_clean) {
+	if (pending_peers.find(p_id))
+		pending_peers.erase(p_id);
+}
+
+void EditorDebuggerServerWebSocket::poll() {
+	server->poll();
+}
+
+Error EditorDebuggerServerWebSocket::start() {
+	int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
+	Vector<String> protocols;
+	protocols.push_back("binary"); // compatibility with EMSCRIPTEN TCP-to-WebSocket layer.
+	return server->listen(remote_port, protocols);
+}
+
+void EditorDebuggerServerWebSocket::stop() {
+	server->stop();
+	pending_peers.clear();
+}
+
+bool EditorDebuggerServerWebSocket::is_active() const {
+	return server->is_listening();
+}
+
+bool EditorDebuggerServerWebSocket::is_connection_available() const {
+	return pending_peers.size() > 0;
+}
+
+Ref<RemoteDebuggerPeer> EditorDebuggerServerWebSocket::take_connection() {
+	ERR_FAIL_COND_V(!is_connection_available(), Ref<RemoteDebuggerPeer>());
+	RemoteDebuggerPeer *peer = memnew(RemoteDebuggerPeerWebSocket(server->get_peer(pending_peers[0])));
+	pending_peers.pop_front();
+	return peer;
+}
+
+EditorDebuggerServerWebSocket::EditorDebuggerServerWebSocket() {
+	server = Ref<WebSocketServer>(WebSocketServer::create());
+	int max_pkts = (int)GLOBAL_GET("network/limits/debugger/max_queued_messages");
+	server->set_buffers(8192, max_pkts, 8192, max_pkts);
+	server->connect("client_connected", callable_mp(this, &EditorDebuggerServerWebSocket::_peer_connected));
+	server->connect("client_disconnected", callable_mp(this, &EditorDebuggerServerWebSocket::_peer_disconnected));
+}
+
+EditorDebuggerServerWebSocket::~EditorDebuggerServerWebSocket() {
+	stop();
+}
+
+EditorDebuggerServer *EditorDebuggerServerWebSocket::create(const String &p_protocol) {
+	ERR_FAIL_COND_V(p_protocol != "ws://", NULL);
+	return memnew(EditorDebuggerServerWebSocket);
+}

+ 63 - 0
modules/websocket/editor_debugger_server_websocket.h

@@ -0,0 +1,63 @@
+/*************************************************************************/
+/*  script_editor_debugger_websocket.h                                   */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H
+#define SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H
+
+#include "modules/websocket/websocket_server.h"
+
+#include "editor/debugger/editor_debugger_server.h"
+
+class EditorDebuggerServerWebSocket : public EditorDebuggerServer {
+
+	GDCLASS(EditorDebuggerServerWebSocket, EditorDebuggerServer);
+
+private:
+	Ref<WebSocketServer> server;
+	List<int> pending_peers;
+
+public:
+	static EditorDebuggerServer *create(const String &p_protocol);
+
+	void _peer_connected(int p_peer, String p_protocol);
+	void _peer_disconnected(int p_peer, bool p_was_clean);
+
+	void poll();
+	Error start();
+	void stop();
+	bool is_active() const;
+	bool is_connection_available() const;
+	Ref<RemoteDebuggerPeer> take_connection();
+
+	EditorDebuggerServerWebSocket();
+	~EditorDebuggerServerWebSocket();
+};
+
+#endif // SCRIPT_EDITOR_DEBUGGER_WEBSOCKET_H

+ 8 - 0
modules/websocket/register_types.cpp

@@ -40,6 +40,10 @@
 #include "wsl_client.h"
 #include "wsl_server.h"
 #endif
+#ifdef TOOLS_ENABLED
+#include "editor/debugger/editor_debugger_server.h"
+#include "editor_debugger_server_websocket.h"
+#endif
 
 void register_websocket_types() {
 #ifdef JAVASCRIPT_ENABLED
@@ -56,6 +60,10 @@ void register_websocket_types() {
 	ClassDB::register_custom_instance_class<WebSocketServer>();
 	ClassDB::register_custom_instance_class<WebSocketClient>();
 	ClassDB::register_custom_instance_class<WebSocketPeer>();
+
+#ifdef TOOLS_ENABLED
+	EditorDebuggerServer::register_protocol_handler("ws://", EditorDebuggerServerWebSocket::create);
+#endif
 }
 
 void unregister_websocket_types() {}

+ 134 - 0
modules/websocket/remote_debugger_peer_websocket.cpp

@@ -0,0 +1,134 @@
+/*************************************************************************/
+/*  script_debugger_websocket.cpp                                        */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "remote_debugger_peer_websocket.h"
+
+#include "core/project_settings.h"
+
+Error RemoteDebuggerPeerWebSocket::connect_to_host(const String &p_uri) {
+
+	Vector<String> protocols;
+	protocols.push_back("binary"); // Compatibility for emscripten TCP-to-WebSocket.
+
+	ws_client->connect_to_url(p_uri, protocols);
+	ws_client->poll();
+
+	if (ws_client->get_connection_status() == WebSocketClient::CONNECTION_DISCONNECTED) {
+
+		ERR_PRINT("Remote Debugger: Unable to connect. Status: " + String::num(ws_client->get_connection_status()) + ".");
+		return FAILED;
+	}
+
+	ws_peer = ws_client->get_peer(1);
+
+	return OK;
+}
+
+bool RemoteDebuggerPeerWebSocket::is_peer_connected() {
+	return ws_peer.is_valid() && ws_peer->is_connected_to_host();
+}
+
+void RemoteDebuggerPeerWebSocket::poll() {
+	ws_client->poll();
+
+	while (ws_peer->is_connected_to_host() && ws_peer->get_available_packet_count() > 0 && in_queue.size() < max_queued_messages) {
+		Variant var;
+		Error err = ws_peer->get_var(var);
+		ERR_CONTINUE(err != OK);
+		ERR_CONTINUE(var.get_type() != Variant::ARRAY);
+		in_queue.push_back(var);
+	}
+
+	while (ws_peer->is_connected_to_host() && out_queue.size() > 0) {
+		Array var = out_queue[0];
+		Error err = ws_peer->put_var(var);
+		ERR_BREAK(err != OK); // Peer buffer full?
+		out_queue.pop_front();
+	}
+}
+
+int RemoteDebuggerPeerWebSocket::get_max_message_size() const {
+	return 8 << 20; // 8 Mib
+}
+
+bool RemoteDebuggerPeerWebSocket::has_message() {
+	return in_queue.size() > 0;
+}
+
+Array RemoteDebuggerPeerWebSocket::get_message() {
+	ERR_FAIL_COND_V(in_queue.size() < 1, Array());
+	Array msg = in_queue[0];
+	in_queue.pop_front();
+	return msg;
+}
+
+Error RemoteDebuggerPeerWebSocket::put_message(const Array &p_arr) {
+	if (out_queue.size() >= max_queued_messages)
+		return ERR_OUT_OF_MEMORY;
+	out_queue.push_back(p_arr);
+	return OK;
+}
+
+void RemoteDebuggerPeerWebSocket::close() {
+	if (ws_peer.is_valid()) {
+		ws_peer.unref();
+	}
+	ws_client->disconnect_from_host();
+}
+
+bool RemoteDebuggerPeerWebSocket::can_block() const {
+#ifdef JAVASCRIPT_ENABLED
+	return false;
+#else
+	return true;
+#endif
+}
+
+RemoteDebuggerPeerWebSocket::RemoteDebuggerPeerWebSocket(Ref<WebSocketPeer> p_peer) {
+#ifdef JAVASCRIPT_ENABLED
+	ws_client = Ref<WebSocketClient>(memnew(EMWSClient));
+#else
+	ws_client = Ref<WebSocketClient>(memnew(WSLClient));
+#endif
+	max_queued_messages = (int)GLOBAL_GET("network/limits/debugger/max_queued_messages");
+	ws_client->set_buffers(8192, max_queued_messages, 8192, max_queued_messages);
+	ws_peer = p_peer;
+}
+
+RemoteDebuggerPeer *RemoteDebuggerPeerWebSocket::create(const String &p_uri) {
+	ERR_FAIL_COND_V(!p_uri.begins_with("ws://") && !p_uri.begins_with("wss://"), NULL);
+	RemoteDebuggerPeerWebSocket *peer = memnew(RemoteDebuggerPeerWebSocket);
+	Error err = peer->connect_to_host(p_uri);
+	if (err != OK) {
+		memdelete(peer);
+		return NULL;
+	}
+	return peer;
+}

+ 66 - 0
modules/websocket/remote_debugger_peer_websocket.h

@@ -0,0 +1,66 @@
+/*************************************************************************/
+/*  script_debugger_websocket.h                                          */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md)    */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef SCRIPT_DEBUGGER_WEBSOCKET_H
+#define SCRIPT_DEBUGGER_WEBSOCKET_H
+
+#ifdef JAVASCRIPT_ENABLED
+#include "modules/websocket/emws_client.h"
+#else
+#include "modules/websocket/wsl_client.h"
+#endif
+#include "core/debugger/remote_debugger_peer.h"
+
+class RemoteDebuggerPeerWebSocket : public RemoteDebuggerPeer {
+
+	Ref<WebSocketClient> ws_client;
+	Ref<WebSocketPeer> ws_peer;
+	List<Array> in_queue;
+	List<Array> out_queue;
+
+	int max_queued_messages;
+
+public:
+	static RemoteDebuggerPeer *create(const String &p_uri);
+
+	Error connect_to_host(const String &p_uri);
+	bool is_peer_connected();
+	int get_max_message_size() const;
+	bool has_message();
+	Error put_message(const Array &p_arr);
+	Array get_message();
+	void close();
+	void poll();
+	bool can_block() const;
+
+	RemoteDebuggerPeerWebSocket(Ref<WebSocketPeer> p_peer = Ref<WebSocketPeer>());
+};
+
+#endif // SCRIPT_DEBUGGER_WEBSOCKET_H

+ 12 - 4
platform/javascript/export/export.cpp

@@ -28,6 +28,7 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
+#include "core/io/json.h"
 #include "core/io/tcp_server.h"
 #include "core/io/zip_io.h"
 #include "editor/editor_export.h"
@@ -198,7 +199,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
 	Ref<ImageTexture> stop_icon;
 	int menu_options;
 
-	void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug);
+	void _fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags);
 
 private:
 	Ref<EditorHTTPServer> server;
@@ -238,15 +239,21 @@ public:
 	virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
 	}
 
+	String get_debug_protocol() const { return "ws://"; }
+
 	EditorExportPlatformJavaScript();
 	~EditorExportPlatformJavaScript();
 };
 
-void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug) {
+void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Ref<EditorExportPreset> &p_preset, const String &p_name, bool p_debug, int p_flags) {
 
 	String str_template = String::utf8(reinterpret_cast<const char *>(p_html.ptr()), p_html.size());
 	String str_export;
 	Vector<String> lines = str_template.split("\n");
+	Vector<String> flags;
+	String flags_json;
+	gen_export_flags(flags, p_flags);
+	flags_json = JSON::print(flags);
 
 	for (int i = 0; i < lines.size(); i++) {
 
@@ -255,6 +262,7 @@ void EditorExportPlatformJavaScript::_fix_html(Vector<uint8_t> &p_html, const Re
 		current_line = current_line.replace("$GODOT_PROJECT_NAME", ProjectSettings::get_singleton()->get_setting("application/config/name"));
 		current_line = current_line.replace("$GODOT_HEAD_INCLUDE", p_preset->get("html/head_include"));
 		current_line = current_line.replace("$GODOT_DEBUG_ENABLED", p_debug ? "true" : "false");
+		current_line = current_line.replace("$GODOT_ARGS", flags_json);
 		str_export += current_line + "\n";
 	}
 
@@ -430,7 +438,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
 			if (!custom_html.empty()) {
 				continue;
 			}
-			_fix_html(data, p_preset, p_path.get_file().get_basename(), p_debug);
+			_fix_html(data, p_preset, p_path.get_file().get_basename(), p_debug, p_flags);
 			file = p_path.get_file();
 
 		} else if (file == "godot.js") {
@@ -469,7 +477,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese
 		buf.resize(f->get_len());
 		f->get_buffer(buf.ptrw(), buf.size());
 		memdelete(f);
-		_fix_html(buf, p_preset, p_path.get_file().get_basename(), p_debug);
+		_fix_html(buf, p_preset, p_path.get_file().get_basename(), p_debug, p_flags);
 
 		f = FileAccess::open(p_path, FileAccess::WRITE);
 		if (!f) {

+ 11 - 0
platform/javascript/os_javascript.cpp

@@ -30,13 +30,19 @@
 
 #include "os_javascript.h"
 
+#include "core/debugger/engine_debugger.h"
 #include "core/io/file_access_buffered_fa.h"
 #include "core/io/json.h"
 #include "drivers/unix/dir_access_unix.h"
 #include "drivers/unix/file_access_unix.h"
 #include "main/main.h"
+#include "modules/modules_enabled.gen.h"
 #include "platform/javascript/display_server_javascript.h"
 
+#ifdef MODULE_WEBSOCKET_ENABLED
+#include "modules/websocket/remote_debugger_peer_websocket.h"
+#endif
+
 #include <emscripten.h>
 #include <stdlib.h>
 
@@ -68,6 +74,11 @@ void OS_JavaScript::initialize() {
 	FileAccess::make_default<FileAccessBufferedFA<FileAccessUnix>>(FileAccess::ACCESS_RESOURCES);
 	DisplayServerJavaScript::register_javascript_driver();
 
+#ifdef MODULE_WEBSOCKET_ENABLED
+	EngineDebugger::register_uri_handler("ws://", RemoteDebuggerPeerWebSocket::create);
+	EngineDebugger::register_uri_handler("wss://", RemoteDebuggerPeerWebSocket::create);
+#endif
+
 	char locale_ptr[16];
 	/* clang-format off */
 	EM_ASM({