1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 06:57:44 +00:00

LibWeb: Make HTML::DecodedImageData to be GC-allocated

This change fixes GC-leak caused by following mutual dependency:
- SVGDecodedImageData owns JS::Handle for Page.
- SVGDecodedImageData is owned by visited objects.
by making everything inherited from HTML::DecodedImageData and
ListOfAvailableImages to be GC-allocated.

Generally, if visited object has a handle, very likely we leak
everything visited from object in a handle.
This commit is contained in:
Aliaksandr Kalenik 2023-12-12 20:07:19 +01:00 committed by Andreas Kling
parent 57a04c536c
commit 41a3c19cfe
18 changed files with 100 additions and 54 deletions

View file

@ -9,6 +9,9 @@
namespace Web::HTML {
JS_DEFINE_ALLOCATOR(ListOfAvailableImages);
JS_DEFINE_ALLOCATOR(ListOfAvailableImages::Entry);
ListOfAvailableImages::ListOfAvailableImages() = default;
ListOfAvailableImages::~ListOfAvailableImages() = default;
@ -30,23 +33,30 @@ u32 ListOfAvailableImages::Key::hash() const
return cached_hash.value();
}
ErrorOr<NonnullRefPtr<ListOfAvailableImages::Entry>> ListOfAvailableImages::Entry::create(NonnullRefPtr<DecodedImageData> image_data, bool ignore_higher_layer_caching)
JS::NonnullGCPtr<ListOfAvailableImages::Entry> ListOfAvailableImages::Entry::create(JS::VM& vm, JS::NonnullGCPtr<DecodedImageData> image_data, bool ignore_higher_layer_caching)
{
return adopt_nonnull_ref_or_enomem(new (nothrow) Entry(move(image_data), ignore_higher_layer_caching));
return vm.heap().allocate_without_realm<Entry>(image_data, ignore_higher_layer_caching);
}
ListOfAvailableImages::Entry::Entry(NonnullRefPtr<DecodedImageData> data, bool ignore_higher_layer_caching)
void ListOfAvailableImages::visit_edges(JS::Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
for (auto& it : m_images)
visitor.visit(it.value);
}
ListOfAvailableImages::Entry::Entry(JS::NonnullGCPtr<DecodedImageData> data, bool ignore_higher_layer_caching)
: ignore_higher_layer_caching(ignore_higher_layer_caching)
, image_data(move(data))
, image_data(data)
{
}
ListOfAvailableImages::Entry::~Entry() = default;
ErrorOr<void> ListOfAvailableImages::add(Key const& key, NonnullRefPtr<DecodedImageData> image_data, bool ignore_higher_layer_caching)
ErrorOr<void> ListOfAvailableImages::add(Key const& key, JS::NonnullGCPtr<DecodedImageData> image_data, bool ignore_higher_layer_caching)
{
auto entry = TRY(Entry::create(move(image_data), ignore_higher_layer_caching));
TRY(m_images.try_set(key, move(entry)));
auto entry = Entry::create(vm(), image_data, ignore_higher_layer_caching);
TRY(m_images.try_set(key, entry));
return {};
}
@ -55,7 +65,7 @@ void ListOfAvailableImages::remove(Key const& key)
m_images.remove(key);
}
RefPtr<ListOfAvailableImages::Entry> ListOfAvailableImages::get(Key const& key) const
JS::GCPtr<ListOfAvailableImages::Entry> ListOfAvailableImages::get(Key const& key) const
{
auto it = m_images.find(key);
if (it == m_images.end())