mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-06-21 08:35:24 +00:00
ImageStyleValue stored GC-managed request, stylesheet, and animation timer references as strong GC::Ptr fields even though image style values are refcounted objects. When such a style value outlives the GC object that normally visits it, those fields can keep stale pointers after GC collects the referents. On Steam this allowed a stale image resource request to be read as unrelated image data, making carousel SVG arrows render at the wrong size. Store these back references as GC::Weak instead. Reachable style values still use live requests, stylesheets, and timers normally, but detached values observe null after the GC collects the referent and can reload or skip the now-dead association instead of dereferencing reused GC memory. Keep a local timer handle while installing the timeout callback so setup does not rely on the weak member. With the image style values no longer hiding strong GC edges, remove the obsolete IGNORE_GC annotation from CSSStyleSheet's pending image list.
62 lines
2.1 KiB
C++
62 lines
2.1 KiB
C++
/*
|
|
* Copyright (c) 2026-present, the Ladybird developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Optional.h>
|
|
#include <AK/String.h>
|
|
#include <AK/Vector.h>
|
|
#include <LibGC/Weak.h>
|
|
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
|
|
|
|
namespace Web::CSS {
|
|
|
|
class ImageSetStyleValue final : public AbstractImageStyleValue {
|
|
using Base = AbstractImageStyleValue;
|
|
|
|
public:
|
|
struct Option {
|
|
NonnullRefPtr<AbstractImageStyleValue const> image;
|
|
NonnullRefPtr<StyleValue const> resolution;
|
|
Optional<String> type;
|
|
};
|
|
|
|
static ValueComparingNonnullRefPtr<ImageSetStyleValue const> create(Vector<Option>);
|
|
virtual ~ImageSetStyleValue() override = default;
|
|
|
|
virtual void visit_edges(JS::Cell::Visitor&) const override;
|
|
|
|
virtual void serialize(StringBuilder&, SerializationMode) const override;
|
|
virtual bool equals(StyleValue const& other) const override;
|
|
virtual bool is_computationally_independent() const override;
|
|
|
|
virtual void load_any_resources(DOM::Document&) override;
|
|
|
|
virtual Optional<CSSPixels> natural_width() const override;
|
|
virtual Optional<CSSPixels> natural_height() const override;
|
|
virtual Optional<CSSPixelFraction> natural_aspect_ratio() const override;
|
|
|
|
virtual void resolve_for_size(Layout::NodeWithStyle const&, CSSPixelSize) const override;
|
|
virtual bool is_paintable() const override;
|
|
virtual void paint(DisplayListRecordingContext&, DevicePixelRect const&, ImageRendering) const override;
|
|
virtual Optional<Gfx::Color> color_if_single_pixel_bitmap() const override;
|
|
|
|
AbstractImageStyleValue const* selected_image() const { return m_selected_image; }
|
|
|
|
private:
|
|
explicit ImageSetStyleValue(Vector<Option>);
|
|
|
|
virtual void set_style_sheet(GC::Ptr<CSSStyleSheet>) override;
|
|
virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(ComputationContext const&) const override;
|
|
|
|
AbstractImageStyleValue const* select_image(double device_pixels_per_css_pixel) const;
|
|
|
|
Vector<Option> m_options;
|
|
GC::Weak<CSSStyleSheet> m_style_sheet;
|
|
mutable AbstractImageStyleValue const* m_selected_image { nullptr };
|
|
};
|
|
|
|
}
|