LibWeb: Store AnimationTimeline associated document as Ref

We always had an associated document for the spec defined timelines
(i.e. `DocumentTimeline` and `ScrollTimeline`) but not for the ad-hoc
`InternalAnimationTimeline` so lets store one for that as well and use a
`Ref` instead of a `Ptr`.

This requires `convert_a_timeline_time_to_an_origin_relative_time` to be
implemented for `InternalAnimationTimeline` since it can now be called
where it previously wasn't due to the absence of a document - we just
return an empty optional since it's not used anywhere.
This commit is contained in:
Callum Law 2026-04-23 17:05:53 +12:00 committed by Alexander Kalenik
parent e3117c12c0
commit 5e3028013c
7 changed files with 15 additions and 27 deletions

View file

@ -47,15 +47,6 @@ NullableCSSNumberish AnimationTimeline::duration_for_bindings() const
return NullableCSSNumberish::from_optional_css_numberish_time(realm(), duration());
}
void AnimationTimeline::set_associated_document(GC::Ptr<DOM::Document> document)
{
if (document)
document->associate_with_timeline(*this);
if (m_associated_document)
m_associated_document->disassociate_with_timeline(*this);
m_associated_document = document;
}
// https://drafts.csswg.org/web-animations-1/#timeline
bool AnimationTimeline::is_inactive() const
{
@ -63,22 +54,23 @@ bool AnimationTimeline::is_inactive() const
return !m_current_time.has_value();
}
AnimationTimeline::AnimationTimeline(JS::Realm& realm)
AnimationTimeline::AnimationTimeline(JS::Realm& realm, GC::Ref<DOM::Document> document)
: Bindings::PlatformObject(realm)
, m_associated_document(document)
{
}
void AnimationTimeline::finalize()
{
Base::finalize();
if (m_associated_document)
m_associated_document->disassociate_with_timeline(*this);
m_associated_document->disassociate_with_timeline(*this);
}
void AnimationTimeline::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(AnimationTimeline);
Base::initialize(realm);
m_associated_document->associate_with_timeline(*this);
}
void AnimationTimeline::visit_edges(Cell::Visitor& visitor)

View file

@ -32,8 +32,7 @@ public:
NullableCSSNumberish duration_for_bindings() const;
virtual Optional<TimeValue> duration() const = 0;
GC::Ptr<DOM::Document> associated_document() const { return m_associated_document; }
void set_associated_document(GC::Ptr<DOM::Document>);
GC::Ref<DOM::Document> associated_document() const { return m_associated_document; }
virtual bool is_inactive() const;
bool is_monotonically_increasing() const { return m_is_monotonically_increasing; }
@ -48,7 +47,7 @@ public:
GC::WeakHashSet<Animation> const& associated_animations() const { return m_associated_animations; }
protected:
AnimationTimeline(JS::Realm&);
AnimationTimeline(JS::Realm&, GC::Ref<DOM::Document>);
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
@ -63,7 +62,7 @@ protected:
bool m_is_monotonically_increasing { false };
// https://www.w3.org/TR/web-animations-1/#timeline-associated-with-a-document
GC::Ptr<DOM::Document> m_associated_document {};
GC::Ref<DOM::Document> m_associated_document;
GC::WeakHashSet<Animation> m_associated_animations;
};

View file

@ -79,10 +79,9 @@ bool DocumentTimeline::is_inactive() const
}
DocumentTimeline::DocumentTimeline(JS::Realm& realm, DOM::Document& document, HighResolutionTime::DOMHighResTimeStamp origin_time)
: AnimationTimeline(realm)
: AnimationTimeline(realm, document)
, m_origin_time(origin_time)
{
set_associated_document(document);
}
void DocumentTimeline::initialize(JS::Realm& realm)

View file

@ -175,11 +175,10 @@ void ScrollTimeline::update_current_time(double)
}
ScrollTimeline::ScrollTimeline(JS::Realm& realm, DOM::Document& document, Source source, Bindings::ScrollAxis axis)
: AnimationTimeline(realm)
: AnimationTimeline(realm, document)
, m_source(source)
, m_axis(axis)
{
set_associated_document(document);
}
void ScrollTimeline::visit_edges(Cell::Visitor& visitor)

View file

@ -35,14 +35,11 @@ void InternalAnimationTimeline::set_time(Optional<double> time)
animation.update();
}
InternalAnimationTimeline::InternalAnimationTimeline(JS::Realm& realm)
: AnimationTimeline(realm)
InternalAnimationTimeline::InternalAnimationTimeline(JS::Realm& realm, GC::Ref<DOM::Document> document)
: AnimationTimeline(realm, document)
{
m_current_time = { Animations::TimeValue::Type::Milliseconds, 0.0 };
m_is_monotonically_increasing = true;
auto& document = as<HTML::Window>(HTML::relevant_global_object(*this)).associated_document();
document.associate_with_timeline(*this);
}
void InternalAnimationTimeline::initialize(JS::Realm& realm)

View file

@ -17,12 +17,14 @@ public:
virtual Optional<Animations::TimeValue> duration() const override { return {}; }
virtual Optional<double> convert_a_timeline_time_to_an_origin_relative_time(Optional<Animations::TimeValue>) override { return {}; }
virtual void update_current_time(double timestamp) override;
void set_time(Optional<double> time);
private:
explicit InternalAnimationTimeline(JS::Realm&);
explicit InternalAnimationTimeline(JS::Realm&, GC::Ref<DOM::Document>);
virtual ~InternalAnimationTimeline() override = default;
virtual void initialize(JS::Realm&) override;

View file

@ -380,7 +380,7 @@ void Internals::spoof_current_url(String const& url_string)
GC::Ref<InternalAnimationTimeline> Internals::create_internal_animation_timeline()
{
auto& realm = this->realm();
return realm.create<InternalAnimationTimeline>(realm);
return realm.create<InternalAnimationTimeline>(realm, as<HTML::Window>(realm.global_object()).associated_document());
}
void Internals::simulate_drag_start(double x, double y, String const& name, String const& contents)