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;