From ec24d7555a21531d001b871887bf8f53ba541a31 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 21 Jul 2023 11:59:49 +0200 Subject: [PATCH] LibWeb: Add a simple `internals` objects only available during testing This object is available as `window.internals` (or just `internals`) and is only accessible while running in "test mode". This first version only has one API: gc(), which triggers a garbage collection immediately. In the future, we can add more APIs here to help us test parts of the engine that are hard or impossible to reach via public web APIs. --- Ladybird/WebContent/main.cpp | 3 ++ .../BindingsGenerator/IDLGenerators.cpp | 5 +++ .../LibWeb/BindingsGenerator/Namespaces.h | 1 + .../GenerateWindowOrWorkerInterfaces.cpp | 8 ++--- Tests/LibWeb/Text/expected/internals.txt | 3 ++ Tests/LibWeb/Text/input/internals.html | 9 +++++ Userland/Libraries/LibWeb/CMakeLists.txt | 1 + Userland/Libraries/LibWeb/Forward.h | 4 +++ Userland/Libraries/LibWeb/HTML/Window.cpp | 13 +++++++- Userland/Libraries/LibWeb/HTML/Window.h | 2 ++ .../Libraries/LibWeb/Internals/Internals.cpp | 33 +++++++++++++++++++ .../Libraries/LibWeb/Internals/Internals.h | 26 +++++++++++++++ .../Libraries/LibWeb/Internals/Internals.idl | 5 +++ Userland/Libraries/LibWeb/idl_files.cmake | 1 + 14 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/internals.txt create mode 100644 Tests/LibWeb/Text/input/internals.html create mode 100644 Userland/Libraries/LibWeb/Internals/Internals.cpp create mode 100644 Userland/Libraries/LibWeb/Internals/Internals.h create mode 100644 Userland/Libraries/LibWeb/Internals/Internals.idl diff --git a/Ladybird/WebContent/main.cpp b/Ladybird/WebContent/main.cpp index 6968890c3b..7c88639ecf 100644 --- a/Ladybird/WebContent/main.cpp +++ b/Ladybird/WebContent/main.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +90,8 @@ ErrorOr serenity_main(Main::Arguments arguments) Web::WebSockets::WebSocketClientManager::initialize(Ladybird::WebSocketClientManagerQt::create()); } + Web::HTML::Window::set_internals_object_exposed(is_layout_test_mode); + JS::Bytecode::Interpreter::set_enabled(use_javascript_bytecode); VERIFY(webcontent_fd_passing_socket >= 0); diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index aa34dd939e..830f86d3d3 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -3126,6 +3126,7 @@ using namespace Web::FileAPI; using namespace Web::Geometry; using namespace Web::HighResolutionTime; using namespace Web::HTML; +using namespace Web::Internals; using namespace Web::IntersectionObserver; using namespace Web::RequestIdleCallback; using namespace Web::ResizeObserver; @@ -3342,6 +3343,7 @@ using namespace Web::FileAPI; using namespace Web::Geometry; using namespace Web::HighResolutionTime; using namespace Web::HTML; +using namespace Web::Internals; using namespace Web::IntersectionObserver; using namespace Web::PerformanceTimeline; using namespace Web::RequestIdleCallback; @@ -3723,6 +3725,7 @@ using namespace Web::FileAPI; using namespace Web::Geometry; using namespace Web::HighResolutionTime; using namespace Web::HTML; +using namespace Web::Internals; using namespace Web::IntersectionObserver; using namespace Web::NavigationTiming; using namespace Web::PerformanceTimeline; @@ -3858,6 +3861,7 @@ using namespace Web::FileAPI; using namespace Web::Geometry; using namespace Web::HighResolutionTime; using namespace Web::HTML; +using namespace Web::Internals; using namespace Web::IntersectionObserver; using namespace Web::NavigationTiming; using namespace Web::PerformanceTimeline; @@ -3990,6 +3994,7 @@ using namespace Web::FileAPI; using namespace Web::Geometry; using namespace Web::HighResolutionTime; using namespace Web::HTML; +using namespace Web::Internals; using namespace Web::IntersectionObserver; using namespace Web::NavigationTiming; using namespace Web::PerformanceTimeline; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h index 6fd5580dfd..8c95cba9e8 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h @@ -23,6 +23,7 @@ static constexpr Array libweb_interface_namespaces = { "Geometry"sv, "HTML"sv, "HighResolutionTime"sv, + "Internals"sv, "IntersectionObserver"sv, "NavigationTiming"sv, "RequestIdleCallback"sv, diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 79e8f1e637..ddd3dd1570 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -178,7 +178,7 @@ void Intrinsics::create_web_namespace<@namespace_class@>(JS::Realm& realm) )~~~"); }; - auto add_interface = [&](SourceGenerator& gen, StringView name, StringView prototype_class, StringView constructor_class, Optional const& legacy_constructor) { + auto add_interface = [](SourceGenerator& gen, StringView name, StringView prototype_class, StringView constructor_class, Optional const& legacy_constructor) { gen.set("interface_name", name); gen.set("prototype_class", prototype_class); gen.set("constructor_class", constructor_class); @@ -434,6 +434,8 @@ static ErrorOr parse_exposure_set(IDL::Interface& interface) auto exposed = maybe_exposed.value().trim_whitespace(); if (exposed == "*"sv) return ExposedTo::All; + if (exposed == "Nobody"sv) + return ExposedTo::Nobody; if (exposed == "Window"sv) return ExposedTo::Window; if (exposed == "Worker"sv) @@ -477,10 +479,8 @@ ErrorOr add_to_interface_sets(IDL::Interface& interface, Vector + diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index af43003b01..538683710f 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -397,6 +397,7 @@ set(SOURCES Infra/ByteSequences.cpp Infra/JSON.cpp Infra/Strings.cpp + Internals/Internals.cpp IntersectionObserver/IntersectionObserver.cpp IntersectionObserver/IntersectionObserverEntry.cpp Layout/AudioBox.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 926c6efd61..41c974b8dc 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -454,6 +454,10 @@ namespace Web::HighResolutionTime { class Performance; } +namespace Web::Internals { +class Internals; +} + namespace Web::IntersectionObserver { class IntersectionObserver; class IntersectionObserverEntry; diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index d9ffdcba02..9a28a1f57b 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022, Andreas Kling + * Copyright (c) 2020-2023, Andreas Kling * Copyright (c) 2021-2022, Sam Atkins * Copyright (c) 2021-2023, Linus Groh * @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -805,6 +806,13 @@ WebIDL::ExceptionOr> Window::byte_length_ return JS::NonnullGCPtr { *m_byte_length_queuing_strategy_size_function }; } +static bool s_internals_object_exposed = false; + +void Window::set_internals_object_exposed(bool exposed) +{ + s_internals_object_exposed = exposed; +} + WebIDL::ExceptionOr Window::initialize_web_interfaces(Badge) { auto& realm = this->realm(); @@ -815,6 +823,9 @@ WebIDL::ExceptionOr Window::initialize_web_interfaces(Badge(realm, realm)), JS::default_attributes); + return {}; } diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index b4a6aeb47c..b0b2ec3806 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -190,6 +190,8 @@ public: HighResolutionTime::DOMHighResTimeStamp get_last_activation_timestamp() const { return m_last_activation_timestamp; } void set_last_activation_timestamp(HighResolutionTime::DOMHighResTimeStamp timestamp) { m_last_activation_timestamp = timestamp; } + static void set_internals_object_exposed(bool); + private: explicit Window(JS::Realm&); diff --git a/Userland/Libraries/LibWeb/Internals/Internals.cpp b/Userland/Libraries/LibWeb/Internals/Internals.cpp new file mode 100644 index 0000000000..fb8955bb53 --- /dev/null +++ b/Userland/Libraries/LibWeb/Internals/Internals.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +namespace Web::Internals { + +Internals::Internals(JS::Realm& realm) + : Bindings::PlatformObject(realm) +{ +} + +Internals::~Internals() = default; + +JS::ThrowCompletionOr Internals::initialize(JS::Realm& realm) +{ + TRY(Base::initialize(realm)); + Object::set_prototype(&Bindings::ensure_web_prototype(realm, "Internals")); + return {}; +} + +void Internals::gc() +{ + vm().heap().collect_garbage(); +} + +} diff --git a/Userland/Libraries/LibWeb/Internals/Internals.h b/Userland/Libraries/LibWeb/Internals/Internals.h new file mode 100644 index 0000000000..cf421d5771 --- /dev/null +++ b/Userland/Libraries/LibWeb/Internals/Internals.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::Internals { + +class Internals final : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(Internals, Bindings::PlatformObject); + +public: + virtual ~Internals() override; + + void gc(); + +private: + explicit Internals(JS::Realm&); + virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; +}; + +} diff --git a/Userland/Libraries/LibWeb/Internals/Internals.idl b/Userland/Libraries/LibWeb/Internals/Internals.idl new file mode 100644 index 0000000000..423e8e7643 --- /dev/null +++ b/Userland/Libraries/LibWeb/Internals/Internals.idl @@ -0,0 +1,5 @@ +[Exposed=Nobody] interface Internals { + + undefined gc(); + +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 0c37ffbe40..132235152c 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -183,6 +183,7 @@ libweb_js_bindings(HTML/WorkerGlobalScope) libweb_js_bindings(HTML/WorkerLocation) libweb_js_bindings(HTML/WorkerNavigator) libweb_js_bindings(HighResolutionTime/Performance) +libweb_js_bindings(Internals/Internals) libweb_js_bindings(IntersectionObserver/IntersectionObserver) libweb_js_bindings(IntersectionObserver/IntersectionObserverEntry) libweb_js_bindings(NavigationTiming/PerformanceTiming)