diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp index 8c50bd30c6..6daab94929 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp @@ -132,7 +132,7 @@ void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_r } } -RefPtr ImageStyleValue::image_data() const +JS::GCPtr ImageStyleValue::image_data() const { if (!m_image_request) return nullptr; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h index 65a43bc088..97398eaa93 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h @@ -48,7 +48,7 @@ public: Function on_animate; - RefPtr image_data() const; + JS::GCPtr image_data() const; private: ImageStyleValue(AK::URL const&); diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 299513cff6..4a9c0a3df2 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -347,7 +347,7 @@ void Document::initialize(JS::Realm& realm) m_selection = heap().allocate(realm, realm, *this); - m_list_of_available_images = make(); + m_list_of_available_images = heap().allocate(realm); } void Document::visit_edges(Cell::Visitor& visitor) @@ -413,6 +413,8 @@ void Document::visit_edges(Cell::Visitor& visitor) for (auto& timeline : m_associated_animation_timelines) visitor.visit(timeline); + + visitor.visit(m_list_of_available_images); } // https://w3c.github.io/selection-api/#dom-document-getselection diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index effb249092..39ed09179f 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -728,7 +728,7 @@ private: JS::GCPtr m_first_base_element_with_href_in_tree_order; // https://html.spec.whatwg.org/multipage/images.html#list-of-available-images - OwnPtr m_list_of_available_images; + JS::GCPtr m_list_of_available_images; JS::GCPtr m_visual_viewport; diff --git a/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.cpp b/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.cpp index edd677baa2..a3f6e519d0 100644 --- a/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.cpp +++ b/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.cpp @@ -5,13 +5,17 @@ */ #include +#include +#include #include namespace Web::HTML { -ErrorOr> AnimatedBitmapDecodedImageData::create(Vector&& frames, size_t loop_count, bool animated) +JS_DEFINE_ALLOCATOR(AnimatedBitmapDecodedImageData); + +ErrorOr> AnimatedBitmapDecodedImageData::create(JS::Realm& realm, Vector&& frames, size_t loop_count, bool animated) { - return adopt_nonnull_ref_or_enomem(new (nothrow) AnimatedBitmapDecodedImageData(move(frames), loop_count, animated)); + return realm.heap().allocate(realm, move(frames), loop_count, animated); } AnimatedBitmapDecodedImageData::AnimatedBitmapDecodedImageData(Vector&& frames, size_t loop_count, bool animated) diff --git a/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.h b/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.h index ac8c65dc5b..0d6ae8a6d6 100644 --- a/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.h +++ b/Userland/Libraries/LibWeb/HTML/AnimatedBitmapDecodedImageData.h @@ -12,13 +12,16 @@ namespace Web::HTML { class AnimatedBitmapDecodedImageData final : public DecodedImageData { + JS_CELL(AnimatedBitmapDecodedImageData, Cell); + JS_DECLARE_ALLOCATOR(AnimatedBitmapDecodedImageData); + public: struct Frame { RefPtr bitmap; int duration { 0 }; }; - static ErrorOr> create(Vector&&, size_t loop_count, bool animated); + static ErrorOr> create(JS::Realm&, Vector&&, size_t loop_count, bool animated); virtual ~AnimatedBitmapDecodedImageData() override; virtual RefPtr bitmap(size_t frame_index, Gfx::IntSize = {}) const override; diff --git a/Userland/Libraries/LibWeb/HTML/DecodedImageData.h b/Userland/Libraries/LibWeb/HTML/DecodedImageData.h index 35e701f0f5..9b38254068 100644 --- a/Userland/Libraries/LibWeb/HTML/DecodedImageData.h +++ b/Userland/Libraries/LibWeb/HTML/DecodedImageData.h @@ -14,7 +14,7 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/images.html#img-req-data -class DecodedImageData : public RefCounted { +class DecodedImageData : public JS::Cell { public: virtual ~DecodedImageData(); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index afaebd0d77..89b8d081ab 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -715,7 +715,7 @@ void HTMLImageElement::react_to_changes_in_the_environment() // FIXME: 13. End the synchronous section, continuing the remaining steps in parallel. - auto step_15 = [this](String const& selected_source, JS::NonnullGCPtr image_request, ListOfAvailableImages::Key const& key, NonnullRefPtr const& image_data) { + auto step_15 = [this](String const& selected_source, JS::NonnullGCPtr image_request, ListOfAvailableImages::Key const& key, JS::NonnullGCPtr image_data) { // 15. Queue an element task on the DOM manipulation task source given the img element and the following steps: queue_an_element_task(HTML::Task::Source::DOMManipulation, [this, selected_source, image_request, key, image_data] { // 1. FIXME: If the img element has experienced relevant mutations since this algorithm started, then let pending request be null and abort these steps. @@ -789,7 +789,7 @@ void HTMLImageElement::react_to_changes_in_the_environment() VERIFY(image_request->shared_image_request()); auto image_data = image_request->shared_image_request()->image_data(); image_request->set_image_data(image_data); - step_15(selected_source, image_request, key, NonnullRefPtr(*image_data)); + step_15(selected_source, image_request, key, *image_data); }); }, [this]() { diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp index e65111036b..c5724a6585 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.cpp @@ -354,7 +354,7 @@ i32 HTMLObjectElement::default_tab_index_value() const return 0; } -RefPtr HTMLObjectElement::image_data() const +JS::GCPtr HTMLObjectElement::image_data() const { if (!m_image_request) return nullptr; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h index 9e909c4a36..580d3d6372 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h +++ b/Userland/Libraries/LibWeb/HTML/HTMLObjectElement.h @@ -81,7 +81,7 @@ private: Representation m_representation { Representation::Unknown }; - RefPtr image_data() const; + JS::GCPtr image_data() const; JS::GCPtr m_image_request; }; diff --git a/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp b/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp index 7a62cb6be5..b30b54cc5f 100644 --- a/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp +++ b/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp @@ -41,6 +41,7 @@ void ImageRequest::visit_edges(JS::Cell::Visitor& visitor) Base::visit_edges(visitor); visitor.visit(m_shared_image_request); visitor.visit(m_page); + visitor.visit(m_image_data); } // https://html.spec.whatwg.org/multipage/images.html#img-available @@ -92,14 +93,14 @@ void abort_the_image_request(JS::Realm&, ImageRequest* image_request) // AD-HOC: We simply don't do this, since our SharedImageRequest may be used by someone else. } -RefPtr ImageRequest::image_data() const +JS::GCPtr ImageRequest::image_data() const { return m_image_data; } -void ImageRequest::set_image_data(RefPtr data) +void ImageRequest::set_image_data(JS::GCPtr data) { - m_image_data = move(data); + m_image_data = data; } // https://html.spec.whatwg.org/multipage/images.html#prepare-an-image-for-presentation diff --git a/Userland/Libraries/LibWeb/HTML/ImageRequest.h b/Userland/Libraries/LibWeb/HTML/ImageRequest.h index 7cb3705e5a..45fa9c4c7d 100644 --- a/Userland/Libraries/LibWeb/HTML/ImageRequest.h +++ b/Userland/Libraries/LibWeb/HTML/ImageRequest.h @@ -43,8 +43,8 @@ public: AK::URL const& current_url() const; void set_current_url(JS::Realm&, AK::URL); - [[nodiscard]] RefPtr image_data() const; - void set_image_data(RefPtr); + [[nodiscard]] JS::GCPtr image_data() const; + void set_image_data(JS::GCPtr); [[nodiscard]] float current_pixel_density() const { return m_current_pixel_density; } void set_current_pixel_density(float density) { m_current_pixel_density = density; } @@ -76,7 +76,7 @@ private: AK::URL m_current_url; // https://html.spec.whatwg.org/multipage/images.html#img-req-data - RefPtr m_image_data; + JS::GCPtr m_image_data; // https://html.spec.whatwg.org/multipage/images.html#current-pixel-density // Each image request has a current pixel density, which must initially be 1. diff --git a/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.cpp b/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.cpp index 0fd0cec290..c97c453aa3 100644 --- a/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.cpp +++ b/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.cpp @@ -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> ListOfAvailableImages::Entry::create(NonnullRefPtr image_data, bool ignore_higher_layer_caching) +JS::NonnullGCPtr ListOfAvailableImages::Entry::create(JS::VM& vm, JS::NonnullGCPtr 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(image_data, ignore_higher_layer_caching); } -ListOfAvailableImages::Entry::Entry(NonnullRefPtr 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 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 ListOfAvailableImages::add(Key const& key, NonnullRefPtr image_data, bool ignore_higher_layer_caching) +ErrorOr ListOfAvailableImages::add(Key const& key, JS::NonnullGCPtr 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::get(Key const& key) const +JS::GCPtr ListOfAvailableImages::get(Key const& key) const { auto it = m_images.find(key); if (it == m_images.end()) diff --git a/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.h b/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.h index 2d555ae95c..b54a26b8f1 100644 --- a/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.h +++ b/Userland/Libraries/LibWeb/HTML/ListOfAvailableImages.h @@ -16,7 +16,10 @@ namespace Web::HTML { // https://html.spec.whatwg.org/multipage/images.html#list-of-available-images -class ListOfAvailableImages { +class ListOfAvailableImages : public JS::Cell { + JS_CELL(ListOfAvailableImages, Cell); + JS_DECLARE_ALLOCATOR(ListOfAvailableImages); + public: struct Key { AK::URL url; @@ -30,26 +33,32 @@ public: mutable Optional cached_hash; }; - struct Entry final : public RefCounted { - static ErrorOr> create(NonnullRefPtr, bool ignore_higher_layer_caching); + struct Entry final : public JS::Cell { + JS_CELL(Entry, Cell); + JS_DECLARE_ALLOCATOR(Entry); + + public: + static JS::NonnullGCPtr create(JS::VM&, JS::NonnullGCPtr, bool ignore_higher_layer_caching); ~Entry(); bool ignore_higher_layer_caching { false }; - NonnullRefPtr image_data; + JS::NonnullGCPtr image_data; private: - Entry(NonnullRefPtr, bool ignore_higher_layer_caching); + Entry(JS::NonnullGCPtr, bool ignore_higher_layer_caching); }; ListOfAvailableImages(); ~ListOfAvailableImages(); - ErrorOr add(Key const&, NonnullRefPtr, bool ignore_higher_layer_caching); + ErrorOr add(Key const&, JS::NonnullGCPtr, bool ignore_higher_layer_caching); void remove(Key const&); - [[nodiscard]] RefPtr get(Key const&) const; + [[nodiscard]] JS::GCPtr get(Key const&) const; + + void visit_edges(JS::Cell::Visitor& visitor) override; private: - HashMap> m_images; + HashMap> m_images; }; } diff --git a/Userland/Libraries/LibWeb/HTML/SharedImageRequest.cpp b/Userland/Libraries/LibWeb/HTML/SharedImageRequest.cpp index 2df3a29d98..1f5b8f7b2f 100644 --- a/Userland/Libraries/LibWeb/HTML/SharedImageRequest.cpp +++ b/Userland/Libraries/LibWeb/HTML/SharedImageRequest.cpp @@ -56,9 +56,10 @@ void SharedImageRequest::visit_edges(JS::Cell::Visitor& visitor) visitor.visit(callback.on_finish); visitor.visit(callback.on_fail); } + visitor.visit(m_image_data); } -RefPtr SharedImageRequest::image_data() const +JS::GCPtr SharedImageRequest::image_data() const { return m_image_data; } @@ -137,7 +138,7 @@ void SharedImageRequest::handle_successful_fetch(AK::URL const& url_string, Stri bool const is_svg_image = mime_type == "image/svg+xml"sv || url_string.basename().ends_with(".svg"sv); - RefPtr image_data; + JS::GCPtr image_data; auto handle_failed_decode = [&] { m_state = State::Failed; @@ -148,7 +149,7 @@ void SharedImageRequest::handle_successful_fetch(AK::URL const& url_string, Stri }; if (is_svg_image) { - auto result = SVG::SVGDecodedImageData::create(m_page, url_string, data); + auto result = SVG::SVGDecodedImageData::create(m_document->realm(), m_page, url_string, data); if (result.is_error()) return handle_failed_decode(); @@ -165,10 +166,10 @@ void SharedImageRequest::handle_successful_fetch(AK::URL const& url_string, Stri .duration = static_cast(frame.duration), }); } - image_data = AnimatedBitmapDecodedImageData::create(move(frames), result.value().loop_count, result.value().is_animated).release_value_but_fixme_should_propagate_errors(); + image_data = AnimatedBitmapDecodedImageData::create(m_document->realm(), move(frames), result.value().loop_count, result.value().is_animated).release_value_but_fixme_should_propagate_errors(); } - m_image_data = move(image_data); + m_image_data = image_data; m_state = State::Finished; diff --git a/Userland/Libraries/LibWeb/HTML/SharedImageRequest.h b/Userland/Libraries/LibWeb/HTML/SharedImageRequest.h index 7fcc1e363e..79c8eac871 100644 --- a/Userland/Libraries/LibWeb/HTML/SharedImageRequest.h +++ b/Userland/Libraries/LibWeb/HTML/SharedImageRequest.h @@ -28,7 +28,7 @@ public: AK::URL const& url() const { return m_url; } - [[nodiscard]] RefPtr image_data() const; + [[nodiscard]] JS::GCPtr image_data() const; [[nodiscard]] JS::GCPtr fetch_controller(); void set_fetch_controller(JS::GCPtr); @@ -66,7 +66,7 @@ private: Vector m_callbacks; AK::URL m_url; - RefPtr m_image_data; + JS::GCPtr m_image_data; JS::GCPtr m_fetch_controller; JS::GCPtr m_document; diff --git a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp index 45b8d8b448..45f88ba1d6 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.cpp @@ -23,6 +23,8 @@ namespace Web::SVG { +JS_DEFINE_ALLOCATOR(SVGDecodedImageData); + class SVGDecodedImageData::SVGPageClient final : public PageClient { JS_CELL(SVGDecodedImageData::SVGPageClient, PageClient); @@ -54,7 +56,7 @@ private: } }; -ErrorOr> SVGDecodedImageData::create(Page& host_page, AK::URL const& url, ByteBuffer data) +ErrorOr> SVGDecodedImageData::create(JS::Realm& realm, JS::NonnullGCPtr host_page, AK::URL const& url, ByteBuffer data) { auto page_client = SVGPageClient::create(Bindings::main_thread_vm(), host_page); auto page = Page::create(Bindings::main_thread_vm(), *page_client); @@ -98,19 +100,28 @@ ErrorOr> SVGDecodedImageData::create(Page& ho MUST(document->append_child(*svg_root)); - return adopt_nonnull_ref_or_enomem(new (nothrow) SVGDecodedImageData(page, move(page_client), move(document), move(svg_root))); + return realm.heap().allocate(realm, page, page_client, document, *svg_root); } -SVGDecodedImageData::SVGDecodedImageData(JS::NonnullGCPtr page, JS::Handle page_client, JS::Handle document, JS::Handle root_element) - : m_page(move(page)) - , m_page_client(move(page_client)) - , m_document(move(document)) - , m_root_element(move(root_element)) +SVGDecodedImageData::SVGDecodedImageData(JS::NonnullGCPtr page, JS::NonnullGCPtr page_client, JS::NonnullGCPtr document, JS::NonnullGCPtr root_element) + : m_page(page) + , m_page_client(page_client) + , m_document(document) + , m_root_element(root_element) { } SVGDecodedImageData::~SVGDecodedImageData() = default; +void SVGDecodedImageData::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_page); + visitor.visit(m_document); + visitor.visit(m_page_client); + visitor.visit(m_root_element); +} + RefPtr SVGDecodedImageData::render(Gfx::IntSize size) const { auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, size).release_value_but_fixme_should_propagate_errors(); diff --git a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h index 88475a3c50..0e71598e65 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h +++ b/Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h @@ -12,8 +12,11 @@ namespace Web::SVG { class SVGDecodedImageData final : public HTML::DecodedImageData { + JS_CELL(SVGDecodedImageData, Cell); + JS_DECLARE_ALLOCATOR(SVGDecodedImageData); + public: - static ErrorOr> create(Page&, AK::URL const&, ByteBuffer encoded_svg); + static ErrorOr> create(JS::Realm&, JS::NonnullGCPtr, AK::URL const&, ByteBuffer encoded_svg); virtual ~SVGDecodedImageData() override; virtual RefPtr bitmap(size_t frame_index, Gfx::IntSize) const override; @@ -30,18 +33,20 @@ public: DOM::Document const& svg_document() const { return *m_document; } + virtual void visit_edges(Cell::Visitor& visitor) override; + private: class SVGPageClient; - SVGDecodedImageData(JS::NonnullGCPtr, JS::Handle, JS::Handle, JS::Handle); + SVGDecodedImageData(JS::NonnullGCPtr, JS::NonnullGCPtr, JS::NonnullGCPtr, JS::NonnullGCPtr); RefPtr render(Gfx::IntSize) const; mutable RefPtr m_immutable_bitmap; - JS::Handle m_page; - JS::Handle m_page_client; + JS::NonnullGCPtr m_page; + JS::NonnullGCPtr m_page_client; - JS::Handle m_document; - JS::Handle m_root_element; + JS::NonnullGCPtr m_document; + JS::NonnullGCPtr m_root_element; }; }