Files
ladybird/Services/WebWorker/PageHost.cpp
Aliaksandr Kalenik 737691c43a LibWeb: Keep worker startup reachable until script load completes
Fixes flakiness in worker tests that create a Worker or SharedWorker
with a missing script URL and only attach an error handler to it.
Once the test callback returns, nothing keeps the worker rooted from
JavaScript. If GC ran before the WebWorker process reported the
script fetch failure, the Worker/WorkerAgentParent cycle could be
collected and the error event never delivered, leaving the test hung
until timeout.

Hold startup-pending WorkerAgentParents from the outside
EnvironmentSettingsObject and release that edge once the script load
succeeds, fails, or the worker closes. The worker now survives long
enough to deliver its first script-load result.
2026-04-27 18:02:49 +02:00

140 lines
3.3 KiB
C++

/*
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <WebWorker/ConnectionFromClient.h>
#include <WebWorker/PageHost.h>
namespace WebWorker {
GC_DEFINE_ALLOCATOR(PageHost);
GC::Ref<PageHost> PageHost::create(JS::VM& vm, ConnectionFromClient& client)
{
return vm.heap().allocate<PageHost>(client);
}
PageHost::~PageHost() = default;
Web::Page& PageHost::page()
{
return *m_page;
}
Web::Page const& PageHost::page() const
{
return *m_page;
}
Gfx::Palette PageHost::palette() const
{
return Gfx::Palette(*m_palette_impl);
}
void PageHost::setup_palette()
{
// FIXME: We don't actually need a palette :thonk:
auto buffer_or_error = Core::AnonymousBuffer::create_with_size(sizeof(Gfx::SystemTheme));
VERIFY(!buffer_or_error.is_error());
auto buffer = buffer_or_error.release_value();
auto* theme = buffer.data<Gfx::SystemTheme>();
theme->color[to_underlying(Gfx::ColorRole::Window)] = Color(Color::Magenta).value();
theme->color[to_underlying(Gfx::ColorRole::WindowText)] = Color(Color::Cyan).value();
m_palette_impl = Gfx::PaletteImpl::create_with_anonymous_buffer(buffer);
}
bool PageHost::is_connection_open() const
{
return m_client.is_open();
}
Web::DevicePixelRect PageHost::screen_rect() const
{
return {};
}
double PageHost::zoom_level() const
{
return 1.0;
}
double PageHost::device_pixel_ratio() const
{
return 1.0;
}
double PageHost::device_pixels_per_css_pixel() const
{
return 1.0;
}
Web::CSS::PreferredColorScheme PageHost::preferred_color_scheme() const
{
return Web::CSS::PreferredColorScheme::Auto;
}
Web::CSS::PreferredContrast PageHost::preferred_contrast() const
{
return Web::CSS::PreferredContrast::Auto;
}
Web::CSS::PreferredMotion PageHost::preferred_motion() const
{
return Web::CSS::PreferredMotion::Auto;
}
HTTP::Cookie::VersionedCookie PageHost::page_did_request_cookie(URL::URL const& url, HTTP::Cookie::Source source)
{
return m_client.did_request_cookie(url, source);
}
void PageHost::page_did_report_worker_exception(String const& message, String const& filename, u32 lineno, u32 colno)
{
m_client.async_did_report_worker_exception(message, filename, lineno, colno);
}
void PageHost::page_did_post_broadcast_channel_message(Web::HTML::BroadcastChannelMessage const& message)
{
m_client.async_did_post_broadcast_channel_message(message);
}
void PageHost::request_file(Web::FileRequest request)
{
m_client.request_file(move(request));
}
Web::PageClient::WorkerAgentResponse PageHost::request_worker_agent(Web::Bindings::AgentType worker_type)
{
auto response = m_client.request_worker_agent(worker_type);
return { response.take_handle(), response.take_request_server_handle(), response.take_image_decoder_handle() };
}
void PageHost::did_finish_loading_worker_script()
{
m_client.async_did_finish_loading_worker_script();
}
void PageHost::did_fail_loading_worker_script()
{
m_client.async_did_fail_loading_worker_script();
}
PageHost::PageHost(ConnectionFromClient& client)
: m_client(client)
, m_page(Web::Page::create(Web::Bindings::main_thread_vm(), *this))
{
setup_palette();
}
void PageHost::visit_edges(JS::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_page);
}
}