diff --git a/Userland/Services/WebContent/CMakeLists.txt b/Userland/Services/WebContent/CMakeLists.txt index a1886c6b63..235829e0ca 100644 --- a/Userland/Services/WebContent/CMakeLists.txt +++ b/Userland/Services/WebContent/CMakeLists.txt @@ -8,6 +8,7 @@ compile_ipc(WebContentClient.ipc WebContentClientEndpoint.h) set(SOURCES ClientConnection.cpp + ConsoleGlobalObject.cpp main.cpp PageHost.cpp WebContentConsoleClient.cpp diff --git a/Userland/Services/WebContent/ClientConnection.cpp b/Userland/Services/WebContent/ClientConnection.cpp index 64fbf46b82..031ae6307b 100644 --- a/Userland/Services/WebContent/ClientConnection.cpp +++ b/Userland/Services/WebContent/ClientConnection.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/Userland/Services/WebContent/ClientConnection.h b/Userland/Services/WebContent/ClientConnection.h index 8dba21858c..f4b6494048 100644 --- a/Userland/Services/WebContent/ClientConnection.h +++ b/Userland/Services/WebContent/ClientConnection.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,7 @@ private: WeakPtr m_interpreter; OwnPtr m_console_client; + JS::Handle m_console_global_object; }; } diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.cpp b/Userland/Services/WebContent/ConsoleGlobalObject.cpp new file mode 100644 index 0000000000..2e16ea6aa9 --- /dev/null +++ b/Userland/Services/WebContent/ConsoleGlobalObject.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ConsoleGlobalObject.h" +#include +#include +#include + +namespace WebContent { + +ConsoleGlobalObject::ConsoleGlobalObject(Web::Bindings::WindowObject& parent_object) + : m_window_object(&parent_object) +{ +} + +ConsoleGlobalObject::~ConsoleGlobalObject() +{ +} + +void ConsoleGlobalObject::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_window_object); +} + +JS::Object* ConsoleGlobalObject::internal_get_prototype_of() const +{ + return m_window_object->internal_get_prototype_of(); +} + +bool ConsoleGlobalObject::internal_set_prototype_of(JS::Object* prototype) +{ + return m_window_object->internal_set_prototype_of(prototype); +} + +bool ConsoleGlobalObject::internal_is_extensible() const +{ + return m_window_object->internal_is_extensible(); +} + +bool ConsoleGlobalObject::internal_prevent_extensions() +{ + return m_window_object->internal_prevent_extensions(); +} + +Optional ConsoleGlobalObject::internal_get_own_property(JS::PropertyName const& property_name) const +{ + if (auto result = m_window_object->internal_get_own_property(property_name); result.has_value()) + return result; + + return Base::internal_get_own_property(property_name); +} + +bool ConsoleGlobalObject::internal_define_own_property(JS::PropertyName const& property_name, JS::PropertyDescriptor const& descriptor) +{ + return m_window_object->internal_define_own_property(property_name, descriptor); +} + +bool ConsoleGlobalObject::internal_has_property(JS::PropertyName const& property_name) const +{ + return Object::internal_has_property(property_name) || m_window_object->internal_has_property(property_name); +} + +JS::Value ConsoleGlobalObject::internal_get(JS::PropertyName const& property_name, JS::Value receiver) const +{ + if (m_window_object->has_own_property(property_name)) + return m_window_object->internal_get(property_name, (receiver == this) ? m_window_object : receiver); + + return Base::internal_get(property_name, receiver); +} + +bool ConsoleGlobalObject::internal_set(JS::PropertyName const& property_name, JS::Value value, JS::Value receiver) +{ + return m_window_object->internal_set(property_name, value, (receiver == this) ? m_window_object : receiver); +} + +bool ConsoleGlobalObject::internal_delete(JS::PropertyName const& property_name) +{ + return m_window_object->internal_delete(property_name); +} + +JS::MarkedValueList ConsoleGlobalObject::internal_own_property_keys() const +{ + return m_window_object->internal_own_property_keys(); +} + +} diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.h b/Userland/Services/WebContent/ConsoleGlobalObject.h new file mode 100644 index 0000000000..03ec211f84 --- /dev/null +++ b/Userland/Services/WebContent/ConsoleGlobalObject.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::Bindings { +class WindowObject; +} + +namespace WebContent { + +class ConsoleGlobalObject final : public JS::GlobalObject { + JS_OBJECT(ConsoleGlobalObject, JS::GlobalObject); + +public: + ConsoleGlobalObject(Web::Bindings::WindowObject&); + virtual ~ConsoleGlobalObject() override; + + virtual Object* internal_get_prototype_of() const override; + virtual bool internal_set_prototype_of(Object* prototype) override; + virtual bool internal_is_extensible() const override; + virtual bool internal_prevent_extensions() override; + virtual Optional internal_get_own_property(JS::PropertyName const& name) const override; + virtual bool internal_define_own_property(JS::PropertyName const& name, JS::PropertyDescriptor const& descriptor) override; + virtual bool internal_has_property(JS::PropertyName const& name) const override; + virtual JS::Value internal_get(JS::PropertyName const&, JS::Value) const override; + virtual bool internal_set(JS::PropertyName const&, JS::Value value, JS::Value receiver) override; + virtual bool internal_delete(JS::PropertyName const& name) override; + virtual JS::MarkedValueList internal_own_property_keys() const override; + +private: + virtual void visit_edges(Visitor&) override; + + Web::Bindings::WindowObject* m_window_object; +}; + +} diff --git a/Userland/Services/WebContent/Forward.h b/Userland/Services/WebContent/Forward.h index 43a28f89cc..ed9cc8aab1 100644 --- a/Userland/Services/WebContent/Forward.h +++ b/Userland/Services/WebContent/Forward.h @@ -9,6 +9,7 @@ namespace WebContent { class ClientConnection; +class ConsoleGlobalObject; class PageHost; class WebContentConsoleClient; diff --git a/Userland/Services/WebContent/WebContentConsoleClient.cpp b/Userland/Services/WebContent/WebContentConsoleClient.cpp index 7a3fbe6bb2..b3a9c0ef9d 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.cpp +++ b/Userland/Services/WebContent/WebContentConsoleClient.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2021, Brandon Scott * Copyright (c) 2020, Hunter Salyer + * Copyright (c) 2021, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -9,10 +10,22 @@ #include #include #include -#include +#include +#include namespace WebContent { +WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, WeakPtr interpreter, ClientConnection& client) + : ConsoleClient(console) + , m_client(client) + , m_interpreter(interpreter) +{ + JS::DeferGC defer_gc(m_interpreter->heap()); + auto console_global_object = m_interpreter->heap().allocate_without_global_object(static_cast(m_interpreter->global_object())); + console_global_object->initialize_global_object(); + m_console_global_object = JS::make_handle(console_global_object); +} + void WebContentConsoleClient::handle_input(const String& js_source) { auto parser = JS::Parser(JS::Lexer(js_source)); @@ -24,9 +37,9 @@ void WebContentConsoleClient::handle_input(const String& js_source) auto hint = error.source_location_hint(js_source); if (!hint.is_empty()) output_html.append(String::formatted("
{}
", escape_html_entities(hint))); - m_interpreter->vm().throw_exception(m_interpreter->global_object(), error.to_string()); + m_interpreter->vm().throw_exception(*m_console_global_object.cell(), error.to_string()); } else { - m_interpreter->run(m_interpreter->global_object(), *program); + m_interpreter->run(*m_console_global_object.cell(), *program); } if (m_interpreter->exception()) { diff --git a/Userland/Services/WebContent/WebContentConsoleClient.h b/Userland/Services/WebContent/WebContentConsoleClient.h index ef43a7beab..3fbeb18062 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.h +++ b/Userland/Services/WebContent/WebContentConsoleClient.h @@ -17,12 +17,7 @@ namespace WebContent { class WebContentConsoleClient final : public JS::ConsoleClient { public: - WebContentConsoleClient(JS::Console& console, WeakPtr interpreter, ClientConnection& client) - : ConsoleClient(console) - , m_client(client) - , m_interpreter(interpreter) - { - } + WebContentConsoleClient(JS::Console&, WeakPtr, ClientConnection&); void handle_input(const String& js_source); @@ -40,6 +35,8 @@ private: ClientConnection& m_client; WeakPtr m_interpreter; + JS::Handle m_console_global_object; + void clear_output(); void print_html(const String& line); };