LibWeb: Implement KeyframeEffect::{get,set}_keyframes

This commit is contained in:
Matthew Olsson 2024-02-12 13:51:36 +00:00 committed by Andreas Kling
parent 38c67ba17c
commit 3c9c134d71
3 changed files with 54 additions and 7 deletions

View file

@ -110,6 +110,8 @@ namespace JS {
P(compactDisplay) \
P(compareExchange) \
P(compile) \
P(composite) \
P(computedOffset) \
P(concat) \
P(configurable) \
P(console) \
@ -157,6 +159,7 @@ namespace JS {
P(done) \
P(dotAll) \
P(drop) \
P(easing) \
P(encodeURI) \
P(encodeURIComponent) \
P(endsWith) \

View file

@ -281,7 +281,7 @@ static bool is_loosely_sorted_by_offset(Vector<BaseKeyframe> const& keyframes)
}
// https://www.w3.org/TR/web-animations-1/#process-a-keyframes-argument
[[maybe_unused]] static WebIDL::ExceptionOr<Vector<BaseKeyframe>> process_a_keyframes_argument(JS::Realm& realm, JS::GCPtr<JS::Object> object)
static WebIDL::ExceptionOr<Vector<BaseKeyframe>> process_a_keyframes_argument(JS::Realm& realm, JS::GCPtr<JS::Object> object)
{
auto& vm = realm.vm();
@ -688,16 +688,55 @@ void KeyframeEffect::set_pseudo_element(Optional<String> pseudo_element)
}
// https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-getkeyframes
WebIDL::ExceptionOr<Vector<JS::Object*>> KeyframeEffect::get_keyframes() const
WebIDL::ExceptionOr<Vector<JS::Object*>> KeyframeEffect::get_keyframes()
{
// FIXME: Implement this
return Vector<JS::Object*> {};
if (m_keyframe_objects.size() != m_keyframes.size()) {
auto& vm = this->vm();
auto& realm = this->realm();
// Recalculate the keyframe objects
VERIFY(m_keyframe_objects.size() == 0);
for (auto& keyframe : m_keyframes) {
auto object = JS::Object::create(realm, realm.intrinsics().object_prototype());
TRY(object->set(vm.names.offset, keyframe.offset.has_value() ? JS::Value(keyframe.offset.value()) : JS::js_null(), ShouldThrowExceptions::Yes));
TRY(object->set(vm.names.computedOffset, JS::Value(keyframe.computed_offset.value()), ShouldThrowExceptions::Yes));
auto easing_value = keyframe.easing.get<NonnullRefPtr<CSS::StyleValue const>>();
TRY(object->set(vm.names.easing, JS::PrimitiveString::create(vm, easing_value->to_string()), ShouldThrowExceptions::Yes));
if (keyframe.composite == Bindings::CompositeOperationOrAuto::Replace) {
TRY(object->set(vm.names.composite, JS::PrimitiveString::create(vm, "replace"sv), ShouldThrowExceptions::Yes));
} else if (keyframe.composite == Bindings::CompositeOperationOrAuto::Add) {
TRY(object->set(vm.names.composite, JS::PrimitiveString::create(vm, "add"sv), ShouldThrowExceptions::Yes));
} else if (keyframe.composite == Bindings::CompositeOperationOrAuto::Accumulate) {
TRY(object->set(vm.names.composite, JS::PrimitiveString::create(vm, "accumulate"sv), ShouldThrowExceptions::Yes));
} else {
TRY(object->set(vm.names.composite, JS::PrimitiveString::create(vm, "auto"sv), ShouldThrowExceptions::Yes));
}
for (auto const& [id, value] : keyframe.parsed_properties()) {
auto value_string = JS::PrimitiveString::create(vm, value->to_string());
TRY(object->set(JS::PropertyKey(DeprecatedFlyString(CSS::string_from_property_id(id))), value_string, ShouldThrowExceptions::Yes));
}
m_keyframe_objects.append(object);
}
}
return m_keyframe_objects;
}
// https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-setkeyframes
WebIDL::ExceptionOr<void> KeyframeEffect::set_keyframes(Optional<JS::Handle<JS::Object>> const&)
WebIDL::ExceptionOr<void> KeyframeEffect::set_keyframes(Optional<JS::Handle<JS::Object>> const& keyframe_object)
{
// FIXME: Implement this
m_keyframe_objects.clear();
m_keyframes = TRY(process_a_keyframes_argument(realm(), keyframe_object.has_value() ? JS::GCPtr { keyframe_object->ptr() } : JS::GCPtr<Object> {}));
// FIXME: After processing the keyframe argument, we need to turn the set of keyframes into a set of computed
// keyframes using the procedure outlined in the second half of
// https://www.w3.org/TR/web-animations-1/#calculating-computed-keyframes. For now, just compute the
// missing keyframe offsets
compute_missing_keyframe_offsets(m_keyframes);
return {};
}
@ -716,6 +755,8 @@ void KeyframeEffect::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_target_element);
for (auto const& keyframe : m_keyframe_objects)
visitor.visit(keyframe);
}
}

View file

@ -77,7 +77,7 @@ public:
Bindings::CompositeOperation composite() const { return m_composite; }
void set_composite(Bindings::CompositeOperation value) { m_composite = value; }
WebIDL::ExceptionOr<Vector<JS::Object*>> get_keyframes() const;
WebIDL::ExceptionOr<Vector<JS::Object*>> get_keyframes();
WebIDL::ExceptionOr<void> set_keyframes(Optional<JS::Handle<JS::Object>> const&);
private:
@ -97,6 +97,9 @@ private:
// https://www.w3.org/TR/web-animations-1/#keyframe
Vector<BaseKeyframe> m_keyframes {};
// A cached version of m_keyframes suitable for returning from get_keyframes()
Vector<JS::Object*> m_keyframe_objects {};
};
}