From e076f9997f8e8c14ce1c9d5eb6c8f0786a36a032 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 6 Apr 2022 14:53:33 +0200 Subject: [PATCH] HackStudio: Remove "evaluate expression" dialog This was built on Web::InProcessWebView which is going to be removed. Since this feature wasn't really used or maintained, let's just remove it for now, and it can be resurrected on top of OutOfProcessWebView if someone finds it useful enough to do that work. --- Userland/DevTools/HackStudio/CMakeLists.txt | 3 - .../Debugger/DebuggerGlobalJSObject.cpp | 115 -------------- .../Debugger/DebuggerGlobalJSObject.h | 34 ---- .../Debugger/DebuggerVariableJSObject.cpp | 58 ------- .../Debugger/DebuggerVariableJSObject.h | 38 ----- .../Debugger/EvaluateExpressionDialog.cpp | 147 ------------------ .../Debugger/EvaluateExpressionDialog.h | 32 ---- Userland/DevTools/HackStudio/Editor.cpp | 8 - Userland/DevTools/HackStudio/Editor.h | 1 - 9 files changed, 436 deletions(-) delete mode 100644 Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.cpp delete mode 100644 Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.h delete mode 100644 Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.cpp delete mode 100644 Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.h delete mode 100644 Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.cpp delete mode 100644 Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.h diff --git a/Userland/DevTools/HackStudio/CMakeLists.txt b/Userland/DevTools/HackStudio/CMakeLists.txt index ee4a8ddd2d..610b25ef35 100644 --- a/Userland/DevTools/HackStudio/CMakeLists.txt +++ b/Userland/DevTools/HackStudio/CMakeLists.txt @@ -18,11 +18,8 @@ set(SOURCES Debugger/BacktraceModel.cpp Debugger/DebugInfoWidget.cpp Debugger/Debugger.cpp - Debugger/DebuggerGlobalJSObject.cpp - Debugger/DebuggerVariableJSObject.cpp Debugger/DisassemblyModel.cpp Debugger/DisassemblyWidget.cpp - Debugger/EvaluateExpressionDialog.cpp Debugger/RegistersModel.cpp Debugger/VariablesModel.cpp Dialogs/Git/GitCommitDialog.cpp diff --git a/Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.cpp b/Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.cpp deleted file mode 100644 index 70822d9299..0000000000 --- a/Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2021, Hunter Salyer - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "DebuggerGlobalJSObject.h" -#include "Debugger.h" -#include "DebuggerVariableJSObject.h" -#include -#include -#include - -namespace HackStudio { - -DebuggerGlobalJSObject::DebuggerGlobalJSObject() -{ - auto regs = Debugger::the().session()->get_registers(); - auto lib = Debugger::the().session()->library_at(regs.ip()); - if (!lib) - return; - m_variables = lib->debug_info->get_variables_in_current_scope(regs); -} - -JS::ThrowCompletionOr DebuggerGlobalJSObject::internal_get(JS::PropertyKey const& property_key, JS::Value receiver) const -{ - if (m_variables.is_empty() || !property_key.is_string()) - return Base::internal_get(property_key, receiver); - - auto it = m_variables.find_if([&](auto& variable) { - return variable->name == property_key.as_string(); - }); - if (it.is_end()) - return Base::internal_get(property_key, receiver); - auto& target_variable = **it; - auto js_value = debugger_to_js(target_variable); - if (js_value.has_value()) - return js_value.value(); - auto error_string = String::formatted("Variable {} of type {} is not convertible to a JS Value", property_key.as_string(), target_variable.type_name); - return vm().throw_completion(const_cast(*this), move(error_string)); -} - -JS::ThrowCompletionOr DebuggerGlobalJSObject::internal_set(JS::PropertyKey const& property_key, JS::Value value, JS::Value receiver) -{ - if (m_variables.is_empty() || !property_key.is_string()) - return Base::internal_set(property_key, value, receiver); - - auto it = m_variables.find_if([&](auto& variable) { - return variable->name == property_key.as_string(); - }); - if (it.is_end()) - return Base::internal_set(property_key, value, receiver); - auto& target_variable = **it; - auto debugger_value = js_to_debugger(value, target_variable); - if (debugger_value.has_value()) - return Debugger::the().session()->poke(target_variable.location_data.address, debugger_value.value()); - auto error_string = String::formatted("Cannot convert JS value {} to variable {} of type {}", value.to_string_without_side_effects(), property_key.as_string(), target_variable.type_name); - return vm().throw_completion(const_cast(*this), move(error_string)); -} - -Optional DebuggerGlobalJSObject::debugger_to_js(Debug::DebugInfo::VariableInfo const& variable) const -{ - if (variable.location_type != Debug::DebugInfo::VariableInfo::LocationType::Address) - return {}; - - auto variable_address = variable.location_data.address; - - if (variable.is_enum_type() || variable.type_name == "int") { - auto value = Debugger::the().session()->peek(variable_address); - VERIFY(value.has_value()); - return JS::Value((i32)value.value()); - } - - if (variable.type_name == "char") { - auto value = Debugger::the().session()->peek(variable_address); - VERIFY(value.has_value()); - return JS::Value((char)value.value()); - } - - if (variable.type_name == "bool") { - auto value = Debugger::the().session()->peek(variable_address); - VERIFY(value.has_value()); - return JS::Value(value.value() != 0); - } - - auto* object = DebuggerVariableJSObject::create(const_cast(*this), variable); - for (auto& member : variable.members) { - auto member_value = debugger_to_js(member); - if (!member_value.has_value()) - continue; - object->define_direct_property(member.name, member_value.value(), JS::default_attributes); - } - - return JS::Value(object); -} - -Optional DebuggerGlobalJSObject::js_to_debugger(JS::Value value, Debug::DebugInfo::VariableInfo const& variable) const -{ - if (value.is_string() && variable.type_name == "char") { - auto string = value.as_string().string(); - if (string.length() != 1) - return {}; - return string[0]; - } - - if (value.is_number() && (variable.is_enum_type() || variable.type_name == "int")) - return value.as_u32(); - - if (value.is_boolean() && variable.type_name == "bool") - return value.as_bool(); - - return {}; -} - -} diff --git a/Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.h b/Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.h deleted file mode 100644 index a1f3b09e01..0000000000 --- a/Userland/DevTools/HackStudio/Debugger/DebuggerGlobalJSObject.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2021, Hunter Salyer - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace HackStudio { - -class DebuggerGlobalJSObject final - : public JS::GlobalObject - , public Weakable { - JS_OBJECT(DebuggerGlobalJSObject, JS::GlobalObject); - -public: - DebuggerGlobalJSObject(); - - virtual JS::ThrowCompletionOr internal_get(JS::PropertyKey const&, JS::Value receiver) const override; - virtual JS::ThrowCompletionOr internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver) override; - - Optional debugger_to_js(Debug::DebugInfo::VariableInfo const&) const; - Optional js_to_debugger(JS::Value value, Debug::DebugInfo::VariableInfo const&) const; - -private: - NonnullOwnPtrVector m_variables; -}; - -} diff --git a/Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.cpp b/Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.cpp deleted file mode 100644 index 97db4eeffe..0000000000 --- a/Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2021, Matthew Olsson - * Copyright (c) 2021, Hunter Salyer - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "DebuggerVariableJSObject.h" -#include "Debugger.h" -#include -#include -#include -#include - -namespace HackStudio { - -DebuggerVariableJSObject* DebuggerVariableJSObject::create(DebuggerGlobalJSObject& global_object, Debug::DebugInfo::VariableInfo const& variable_info) -{ - return global_object.heap().allocate(global_object, variable_info, *global_object.object_prototype()); -} - -DebuggerVariableJSObject::DebuggerVariableJSObject(Debug::DebugInfo::VariableInfo const& variable_info, JS::Object& prototype) - : JS::Object(prototype) - , m_variable_info(variable_info) -{ -} - -JS::ThrowCompletionOr DebuggerVariableJSObject::internal_set(const JS::PropertyKey& property_key, JS::Value value, JS::Value) -{ - auto& vm = this->vm(); - - if (!property_key.is_string()) - return vm.throw_completion(global_object(), String::formatted("Invalid variable name {}", property_key.to_string())); - - auto name = property_key.as_string(); - auto it = m_variable_info.members.find_if([&](auto& variable) { - return variable->name == name; - }); - - if (it.is_end()) - return vm.throw_completion(global_object(), String::formatted("Variable of type {} has no property {}", m_variable_info.type_name, property_key)); - - auto& member = **it; - auto new_value = debugger_object().js_to_debugger(value, member); - if (!new_value.has_value()) - return vm.throw_completion(global_object(), String::formatted("Cannot convert JS value {} to variable {} of type {}", value.to_string_without_side_effects(), name, member.type_name)); - - Debugger::the().session()->poke(member.location_data.address, new_value.value()); - return true; -} - -DebuggerGlobalJSObject& DebuggerVariableJSObject::debugger_object() const -{ - return static_cast(global_object()); -} - -} diff --git a/Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.h b/Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.h deleted file mode 100644 index 195e978225..0000000000 --- a/Userland/DevTools/HackStudio/Debugger/DebuggerVariableJSObject.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2021, Matthew Olsson - * Copyright (c) 2021, Hunter Salyer - * Copyright (c) 2022, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include "DebuggerGlobalJSObject.h" -#include -#include -#include -#include - -namespace HackStudio { - -class DebuggerVariableJSObject final : public JS::Object { - using Base = JS::Object; - -public: - static DebuggerVariableJSObject* create(DebuggerGlobalJSObject&, Debug::DebugInfo::VariableInfo const& variable_info); - - DebuggerVariableJSObject(Debug::DebugInfo::VariableInfo const& variable_info, JS::Object& prototype); - virtual ~DebuggerVariableJSObject() override = default; - - virtual StringView class_name() const override { return m_variable_info.type_name; } - - JS::ThrowCompletionOr internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver) override; - -private: - DebuggerGlobalJSObject& debugger_object() const; - - Debug::DebugInfo::VariableInfo const& m_variable_info; -}; - -} diff --git a/Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.cpp b/Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.cpp deleted file mode 100644 index c1fc9a7058..0000000000 --- a/Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2021, Hunter Salyer - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "EvaluateExpressionDialog.h" -#include "DebuggerGlobalJSObject.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace HackStudio { - -static JS::VM& global_vm() -{ - static RefPtr vm; - if (!vm) - vm = JS::VM::create(); - return *vm; -} - -EvaluateExpressionDialog::EvaluateExpressionDialog(Window* parent_window) - : Dialog(parent_window) - , m_interpreter(JS::Interpreter::create(global_vm())) -{ - set_title("Evaluate Expression"); - set_icon(parent_window->icon()); - build(parent_window); -} - -void EvaluateExpressionDialog::build(Window* parent_window) -{ - auto& widget = set_main_widget(); - - int width = max(parent_window->width() / 2, 150); - int height = max(parent_window->height() * (2 / 3), 350); - - set_rect(x(), y(), width, height); - - widget.set_layout(); - widget.set_fill_with_background_color(true); - - widget.layout()->set_margins(6); - widget.layout()->set_spacing(6); - - m_text_editor = widget.add(); - m_text_editor->set_fixed_height(19); - m_text_editor->set_syntax_highlighter(make()); - m_text_editor->set_font(Gfx::FontDatabase::default_fixed_width_font()); - m_text_editor->set_history_enabled(true); - - auto base_document = Web::DOM::Document::create(); - base_document->append_child(adopt_ref(*new Web::DOM::DocumentType(base_document))); - auto html_element = base_document->create_element("html").release_value(); - base_document->append_child(html_element); - auto head_element = base_document->create_element("head").release_value(); - html_element->append_child(head_element); - auto body_element = base_document->create_element("body").release_value(); - html_element->append_child(body_element); - m_output_container = body_element; - - m_output_view = widget.add(); - m_output_view->set_document(base_document); - - auto& button_container_outer = widget.add(); - button_container_outer.set_fixed_height(20); - button_container_outer.set_layout(); - - auto& button_container_inner = button_container_outer.add(); - button_container_inner.set_layout(); - button_container_inner.layout()->set_spacing(6); - button_container_inner.layout()->set_margins({ 4, 0, 4 }); - button_container_inner.layout()->add_spacer(); - - m_evaluate_button = button_container_inner.add(); - m_evaluate_button->set_fixed_height(20); - m_evaluate_button->set_text("Evaluate"); - m_evaluate_button->on_click = [this](auto) { - handle_evaluation(m_text_editor->text()); - }; - - m_close_button = button_container_inner.add(); - m_close_button->set_fixed_height(20); - m_close_button->set_text("Close"); - m_close_button->on_click = [this](auto) { - done(ExecOK); - }; - - m_text_editor->on_return_pressed = [this] { - m_evaluate_button->click(); - }; - m_text_editor->on_escape_pressed = [this] { - m_close_button->click(); - }; - m_text_editor->set_focus(true); -} - -void EvaluateExpressionDialog::handle_evaluation(String const& expression) -{ - m_output_container->remove_all_children(); - m_output_view->update(); - - auto script_or_error = JS::Script::parse(expression, m_interpreter->realm()); - - StringBuilder output_html; - auto result = JS::ThrowCompletionOr { JS::js_undefined() }; - if (script_or_error.is_error()) { - auto error = script_or_error.error()[0]; - auto hint = error.source_location_hint(expression); - if (!hint.is_empty()) - output_html.append(String::formatted("
{}
", escape_html_entities(hint))); - result = m_interpreter->vm().throw_completion(m_interpreter->global_object(), error.to_string()); - } else { - result = m_interpreter->run(script_or_error.value()); - } - - if (result.is_error()) { - output_html.append("Uncaught exception: "); - auto error = *result.throw_completion().value(); - if (error.is_object()) - output_html.append(JS::MarkupGenerator::html_from_error(error.as_object())); - else - output_html.append(JS::MarkupGenerator::html_from_value(error)); - set_output(output_html.string_view()); - return; - } - - set_output(JS::MarkupGenerator::html_from_value(result.value())); -} - -void EvaluateExpressionDialog::set_output(StringView html) -{ - auto paragraph = m_output_container->document().create_element("p").release_value(); - paragraph->set_inner_html(html); - - m_output_container->append_child(paragraph); -} - -} diff --git a/Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.h b/Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.h deleted file mode 100644 index 201c3c8190..0000000000 --- a/Userland/DevTools/HackStudio/Debugger/EvaluateExpressionDialog.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021, Hunter Salyer - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include - -namespace HackStudio { - -class EvaluateExpressionDialog : public GUI::Dialog { - C_OBJECT(EvaluateExpressionDialog); - -private: - explicit EvaluateExpressionDialog(Window* parent_window); - - void build(Window* parent_window); - void handle_evaluation(String const& expression); - void set_output(StringView html); - - NonnullOwnPtr m_interpreter; - RefPtr m_text_editor; - RefPtr m_output_view; - RefPtr m_output_container; - RefPtr m_evaluate_button; - RefPtr m_close_button; -}; - -} diff --git a/Userland/DevTools/HackStudio/Editor.cpp b/Userland/DevTools/HackStudio/Editor.cpp index d50d92247b..181cc2b2b3 100644 --- a/Userland/DevTools/HackStudio/Editor.cpp +++ b/Userland/DevTools/HackStudio/Editor.cpp @@ -7,7 +7,6 @@ #include "Editor.h" #include "Debugger/Debugger.h" -#include "Debugger/EvaluateExpressionDialog.h" #include "EditorWrapper.h" #include "HackStudio.h" #include "Language.h" @@ -56,11 +55,6 @@ Editor::Editor() create_tokens_info_timer(); set_document(CodeDocument::create()); - m_evaluate_expression_action = GUI::Action::create("Evaluate expression", { Mod_Ctrl, Key_E }, [this](auto&) { - VERIFY(is_program_running()); - auto dialog = EvaluateExpressionDialog::construct(window()); - dialog->exec(); - }); m_move_execution_to_line_action = GUI::Action::create("Set execution point to line", [this](auto&) { VERIFY(is_program_running()); auto success = Debugger::the().set_execution_position(currently_open_file(), cursor().line()); @@ -73,7 +67,6 @@ Editor::Editor() set_debug_mode(false); - add_custom_context_menu_action(*m_evaluate_expression_action); add_custom_context_menu_action(*m_move_execution_to_line_action); set_gutter_visible(true); @@ -722,7 +715,6 @@ void Editor::handle_function_parameters_hint_request() void Editor::set_debug_mode(bool enabled) { - m_evaluate_expression_action->set_enabled(enabled); m_move_execution_to_line_action->set_enabled(enabled); } diff --git a/Userland/DevTools/HackStudio/Editor.h b/Userland/DevTools/HackStudio/Editor.h index e1bc6206d5..d2031b202b 100644 --- a/Userland/DevTools/HackStudio/Editor.h +++ b/Userland/DevTools/HackStudio/Editor.h @@ -120,7 +120,6 @@ private: bool m_hovering_editor { false }; bool m_hovering_clickable { false }; bool m_autocomplete_in_focus { false }; - RefPtr m_evaluate_expression_action; RefPtr m_move_execution_to_line_action; RefPtr m_tokens_info_timer; // Used for querying language server for syntax highlighting info OwnPtr m_language_client;