diff --git a/Userland/Libraries/LibJS/Console.cpp b/Userland/Libraries/LibJS/Console.cpp index 0e202b88949..9a32e29036c 100644 --- a/Userland/Libraries/LibJS/Console.cpp +++ b/Userland/Libraries/LibJS/Console.cpp @@ -18,11 +18,23 @@ namespace JS { +JS_DEFINE_ALLOCATOR(Console); +JS_DEFINE_ALLOCATOR(ConsoleClient); + Console::Console(Realm& realm) : m_realm(realm) { } +Console::~Console() = default; + +void Console::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_realm); + visitor.visit(m_client); +} + // 1.1.1. assert(condition, ...data), https://console.spec.whatwg.org/#assert ThrowCompletionOr Console::assert_() { @@ -543,10 +555,23 @@ ThrowCompletionOr Console::format_time_since(Core::ElapsedTimer timer) return MUST(builder.to_string()); } +ConsoleClient::ConsoleClient(Console& console) + : m_console(console) +{ +} + +ConsoleClient::~ConsoleClient() = default; + +void ConsoleClient::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_console); +} + // 2.1. Logger(logLevel, args), https://console.spec.whatwg.org/#logger ThrowCompletionOr ConsoleClient::logger(Console::LogLevel log_level, MarkedVector const& args) { - auto& vm = m_console.realm().vm(); + auto& vm = m_console->realm().vm(); // 1. If args is empty, return. if (args.is_empty()) @@ -578,7 +603,7 @@ ThrowCompletionOr ConsoleClient::logger(Console::LogLevel log_level, Mark // 2.2. Formatter(args), https://console.spec.whatwg.org/#formatter ThrowCompletionOr> ConsoleClient::formatter(MarkedVector const& args) { - auto& realm = m_console.realm(); + auto& realm = m_console->realm(); auto& vm = realm.vm(); // 1. If args’s size is 1, return args. @@ -691,7 +716,7 @@ ThrowCompletionOr> ConsoleClient::formatter(MarkedVector ConsoleClient::generically_format_values(MarkedVector const& values) { AllocatingMemoryStream stream; - auto& vm = m_console.realm().vm(); + auto& vm = m_console->realm().vm(); PrintContext ctx { vm, stream, true }; bool first = true; for (auto const& value : values) { diff --git a/Userland/Libraries/LibJS/Console.h b/Userland/Libraries/LibJS/Console.h index 7b291dd1c08..30136e4093d 100644 --- a/Userland/Libraries/LibJS/Console.h +++ b/Userland/Libraries/LibJS/Console.h @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include namespace JS { @@ -21,11 +23,13 @@ namespace JS { class ConsoleClient; // https://console.spec.whatwg.org -class Console { - AK_MAKE_NONCOPYABLE(Console); - AK_MAKE_NONMOVABLE(Console); +class Console : public Cell { + JS_CELL(Console, Cell); + JS_DECLARE_ALLOCATOR(Console); public: + virtual ~Console() override; + // These are not really levels, but that's the term used in the spec. enum class LogLevel { Assert, @@ -54,8 +58,6 @@ public: Vector stack; }; - explicit Console(Realm&); - void set_client(ConsoleClient& client) { m_client = &client; } Realm& realm() const { return m_realm; } @@ -87,24 +89,26 @@ public: void report_exception(JS::Error const&, bool) const; private: + explicit Console(Realm&); + + virtual void visit_edges(Visitor&) override; + ThrowCompletionOr value_vector_to_string(MarkedVector const&); ThrowCompletionOr format_time_since(Core::ElapsedTimer timer); NonnullGCPtr m_realm; - ConsoleClient* m_client { nullptr }; + GCPtr m_client; HashMap m_counters; HashMap m_timer_table; Vector m_group_stack; }; -class ConsoleClient { -public: - explicit ConsoleClient(Console& console) - : m_console(console) - { - } +class ConsoleClient : public Cell { + JS_CELL(ConsoleClient, Cell); + JS_DECLARE_ALLOCATOR(ConsoleClient); +public: using PrinterArguments = Variant>; ThrowCompletionOr logger(Console::LogLevel log_level, MarkedVector const& args); @@ -120,9 +124,11 @@ public: ThrowCompletionOr generically_format_values(MarkedVector const&); protected: - virtual ~ConsoleClient() = default; + explicit ConsoleClient(Console&); + virtual ~ConsoleClient() override; + virtual void visit_edges(Visitor& visitor) override; - Console& m_console; + NonnullGCPtr m_console; }; } diff --git a/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp b/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp index 20806c9aad7..b4843cb2c1a 100644 --- a/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ConsoleObject.cpp @@ -16,14 +16,22 @@ JS_DEFINE_ALLOCATOR(ConsoleObject); ConsoleObject::ConsoleObject(Realm& realm) : Object(ConstructWithPrototypeTag::Tag, realm.intrinsics().object_prototype()) - , m_console(make(realm)) { } +ConsoleObject::~ConsoleObject() = default; + +void ConsoleObject::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_console); +} + void ConsoleObject::initialize(Realm& realm) { auto& vm = this->vm(); Base::initialize(realm); + m_console = vm.heap().allocate(realm, realm); u8 attr = Attribute::Writable | Attribute::Enumerable | Attribute::Configurable; define_native_function(realm, vm.names.assert, assert_, 0, attr); define_native_function(realm, vm.names.clear, clear, 0, attr); diff --git a/Userland/Libraries/LibJS/Runtime/ConsoleObject.h b/Userland/Libraries/LibJS/Runtime/ConsoleObject.h index d970b7c27ea..c5f37eab28a 100644 --- a/Userland/Libraries/LibJS/Runtime/ConsoleObject.h +++ b/Userland/Libraries/LibJS/Runtime/ConsoleObject.h @@ -16,12 +16,13 @@ class ConsoleObject final : public Object { public: virtual void initialize(Realm&) override; - virtual ~ConsoleObject() override = default; + virtual ~ConsoleObject() override; Console& console() { return *m_console; } private: explicit ConsoleObject(Realm&); + virtual void visit_edges(Visitor&) override; JS_DECLARE_NATIVE_FUNCTION(assert_); JS_DECLARE_NATIVE_FUNCTION(clear); @@ -41,7 +42,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(time_log); JS_DECLARE_NATIVE_FUNCTION(time_end); - NonnullOwnPtr m_console; + GCPtr m_console; }; } diff --git a/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.cpp b/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.cpp index c478e572e2e..ec93368f386 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.cpp +++ b/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.cpp @@ -13,6 +13,8 @@ namespace Web::HTML { +JS_DEFINE_ALLOCATOR(WorkerDebugConsoleClient); + WorkerDebugConsoleClient::WorkerDebugConsoleClient(JS::Console& console) : ConsoleClient(console) { @@ -34,7 +36,7 @@ void WorkerDebugConsoleClient::end_group() // 2.3. Printer(logLevel, args[, options]), https://console.spec.whatwg.org/#printer JS::ThrowCompletionOr WorkerDebugConsoleClient::printer(JS::Console::LogLevel log_level, PrinterArguments arguments) { - auto& vm = m_console.realm().vm(); + auto& vm = m_console->realm().vm(); auto indent = TRY_OR_THROW_OOM(vm, String::repeated(' ', m_group_stack_depth * 2)); @@ -59,7 +61,7 @@ JS::ThrowCompletionOr WorkerDebugConsoleClient::printer(JS::Console:: } auto output = TRY(generically_format_values(arguments.get>())); - m_console.output_debug_message(log_level, output); + m_console->output_debug_message(log_level, output); switch (log_level) { case JS::Console::LogLevel::Debug: diff --git a/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.h b/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.h index 569ce5d4afe..0876f44f48f 100644 --- a/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.h +++ b/Userland/Libraries/LibWeb/HTML/WorkerDebugConsoleClient.h @@ -16,16 +16,18 @@ namespace Web::HTML { class WorkerDebugConsoleClient final : public JS::ConsoleClient - , public RefCounted , public Weakable { -public: - WorkerDebugConsoleClient(JS::Console& console); + JS_CELL(WorkerDebugConsoleClient, JS::ConsoleClient); + JS_DECLARE_ALLOCATOR(WorkerDebugConsoleClient); +public: virtual void clear() override; virtual void end_group() override; virtual JS::ThrowCompletionOr printer(JS::Console::LogLevel log_level, PrinterArguments arguments) override; private: + WorkerDebugConsoleClient(JS::Console& console); + int m_group_stack_depth { 0 }; }; diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index d53dd3bb1a4..470d42cf560 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -680,10 +680,10 @@ void PageClient::initialize_js_console(Web::DOM::Document& document) { auto& realm = document.realm(); auto console_object = realm.intrinsics().console_object(); - auto console_client = make(console_object->console(), document.realm(), *this); + auto console_client = heap().allocate_without_realm(console_object->console(), document.realm(), *this); console_object->console().set_client(*console_client); - m_console_clients.set(document, move(console_client)); + m_console_clients.set(document, console_client); } void PageClient::destroy_js_console(Web::DOM::Document& document) diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index 1f2fec96b68..d7c333f4fec 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -196,7 +196,7 @@ private: BackingStores m_backing_stores; // NOTE: These documents are not visited, but manually removed from the map on document finalization. - HashMap, NonnullOwnPtr> m_console_clients; + HashMap, JS::NonnullGCPtr> m_console_clients; WeakPtr m_top_level_document_console_client; JS::Handle m_console_global_object; diff --git a/Userland/Services/WebContent/WebContentConsoleClient.cpp b/Userland/Services/WebContent/WebContentConsoleClient.cpp index 7a78a2997ba..d66b29b8de7 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.cpp +++ b/Userland/Services/WebContent/WebContentConsoleClient.cpp @@ -24,6 +24,8 @@ namespace WebContent { +JS_DEFINE_ALLOCATOR(WebContentConsoleClient); + WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, JS::Realm& realm, PageClient& client) : ConsoleClient(console) , m_client(client) @@ -32,6 +34,15 @@ WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, JS::Realm m_console_global_environment_extensions = realm.heap().allocate(realm, realm, window); } +WebContentConsoleClient::~WebContentConsoleClient() = default; + +void WebContentConsoleClient::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_client); + visitor.visit(m_console_global_environment_extensions); +} + void WebContentConsoleClient::handle_input(ByteString const& js_source) { if (!m_console_global_environment_extensions) @@ -158,7 +169,7 @@ JS::ThrowCompletionOr WebContentConsoleClient::printer(JS::Console::L } auto output = TRY(generically_format_values(arguments.get>())); - m_console.output_debug_message(log_level, output); + m_console->output_debug_message(log_level, output); StringBuilder html; switch (log_level) { diff --git a/Userland/Services/WebContent/WebContentConsoleClient.h b/Userland/Services/WebContent/WebContentConsoleClient.h index 5d7d2dc6bec..5b3e8712954 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.h +++ b/Userland/Services/WebContent/WebContentConsoleClient.h @@ -20,14 +20,20 @@ namespace WebContent { class WebContentConsoleClient final : public JS::ConsoleClient , public Weakable { + JS_CELL(WebContentConsoleClient, JS::ConsoleClient); + JS_DECLARE_ALLOCATOR(WebContentConsoleClient); + public: - WebContentConsoleClient(JS::Console&, JS::Realm&, PageClient&); + virtual ~WebContentConsoleClient() override; void handle_input(ByteString const& js_source); void send_messages(i32 start_index); void report_exception(JS::Error const&, bool) override; private: + WebContentConsoleClient(JS::Console&, JS::Realm&, PageClient&); + + virtual void visit_edges(JS::Cell::Visitor&) override; virtual void clear() override; virtual JS::ThrowCompletionOr printer(JS::Console::LogLevel log_level, PrinterArguments) override; @@ -38,7 +44,7 @@ private: } JS::NonnullGCPtr m_client; - JS::Handle m_console_global_environment_extensions; + JS::GCPtr m_console_global_environment_extensions; void clear_output(); void print_html(ByteString const& line); diff --git a/Userland/Services/WebWorker/DedicatedWorkerHost.cpp b/Userland/Services/WebWorker/DedicatedWorkerHost.cpp index 5560a9fde4b..c5ce1219c9f 100644 --- a/Userland/Services/WebWorker/DedicatedWorkerHost.cpp +++ b/Userland/Services/WebWorker/DedicatedWorkerHost.cpp @@ -55,7 +55,7 @@ void DedicatedWorkerHost::run(JS::NonnullGCPtr page, Web::HTML::Trans auto inner_settings = Web::HTML::WorkerEnvironmentSettingsObject::setup(page, move(realm_execution_context)); auto& console_object = *inner_settings->realm().intrinsics().console_object(); - m_console = adopt_ref(*new Web::HTML::WorkerDebugConsoleClient(console_object.console())); + m_console = console_object.heap().allocate_without_realm(console_object.console()); VERIFY(m_console); console_object.console().set_client(*m_console); diff --git a/Userland/Services/WebWorker/DedicatedWorkerHost.h b/Userland/Services/WebWorker/DedicatedWorkerHost.h index d448dae21f0..4bfeb95a916 100644 --- a/Userland/Services/WebWorker/DedicatedWorkerHost.h +++ b/Userland/Services/WebWorker/DedicatedWorkerHost.h @@ -23,7 +23,7 @@ public: void run(JS::NonnullGCPtr, Web::HTML::TransferDataHolder message_port_data, Web::HTML::SerializedEnvironmentSettingsObject const&); private: - RefPtr m_console; + JS::Handle m_console; URL::URL m_url; String m_type; diff --git a/Userland/Utilities/js.cpp b/Userland/Utilities/js.cpp index 8f428110385..1bc582339b7 100644 --- a/Userland/Utilities/js.cpp +++ b/Userland/Utilities/js.cpp @@ -497,7 +497,7 @@ public: auto output = TRY(generically_format_values(arguments.get>())); #ifdef AK_OS_SERENITY - m_console.output_debug_message(log_level, output); + m_console->output_debug_message(log_level, output); #endif switch (log_level) {