#include <AK/String.h>
#include <AK/Variant.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/VM.h>
#include <LibJS/Runtime/Value.h>
#include <LibJS/Runtime/ValueInlines.h>
#include <LibWeb/Animations/AnimationEffect.h>
#include <LibWeb/Bindings/AnimationEffect.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/CSS/CSSNumericValue.h>
#include <LibWeb/WebIDL/AbstractOperations.h>
#include <LibWeb/WebIDL/Tracing.h>

namespace Web::Bindings {

void AnimationEffectConstructor::initialize(JS::Realm& realm, JS::NativeFunction& object)
{
    auto& vm = realm.vm();
    [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable;

    
    object.define_direct_property(vm.names.length, JS::Value(0), JS::Attribute::Configurable);
    object.define_direct_property(vm.names.name, JS::PrimitiveString::create(vm, "AnimationEffect"_utf16), JS::Attribute::Configurable);
    object.define_direct_property(vm.names.prototype, &ensure_web_prototype<AnimationEffectPrototype>(realm, "AnimationEffect"_fly_string), 0);
}

JS::ThrowCompletionOr<GC::Ref<JS::Object>> AnimationEffectConstructor::construct([[maybe_unused]] InterfaceConstructor& constructor, [[maybe_unused]] JS::FunctionObject& new_target)
{
    WebIDL::log_trace(constructor.vm(), "AnimationEffectConstructor::construct");
    return constructor.vm().throw_completion<JS::TypeError>(JS::ErrorType::NotAConstructor, "AnimationEffect");
}

void AnimationEffectPrototype::initialize(JS::Realm& realm, JS::Object& object)
{
    [[maybe_unused]] auto& vm = realm.vm();
    [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable | JS::Attribute::Configurable | JS::Attribute::Writable;

    object.set_prototype(realm.intrinsics().object_prototype());
    object.define_native_function(realm, "getTiming"_utf16_fly_string, get_timing, 0, default_attributes);

    object.define_native_function(realm, "getComputedTiming"_utf16_fly_string, get_computed_timing, 0, default_attributes);

    object.define_native_function(realm, "updateTiming"_utf16_fly_string, update_timing, 0, default_attributes);

    object.define_direct_property(vm.well_known_symbol_to_string_tag(), JS::PrimitiveString::create(vm, "AnimationEffect"_utf16), JS::Attribute::Configurable);
}

void AnimationEffectPrototype::define_unforgeable_attributes(JS::Realm& realm, [[maybe_unused]] JS::Object& object)
{
    [[maybe_unused]] auto& vm = realm.vm();
    [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable;
}

[[maybe_unused]] static JS::ThrowCompletionOr<Animations::AnimationEffect*> impl_from(JS::VM& vm, JS::Value js_value)
{

    if (auto impl = js_value.as_if<Animations::AnimationEffect>())
        return impl.ptr();
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "AnimationEffect");
}

[[maybe_unused]] static JS::ThrowCompletionOr<Animations::AnimationEffect*> impl_from(JS::VM& vm)
{
    auto this_value = vm.this_value();
    if (this_value.is_nullish())
        this_value = &vm.current_realm()->global_object();
    return impl_from(vm, this_value);
}

JS_DEFINE_NATIVE_FUNCTION(AnimationEffectPrototype::get_timing)
{
    WebIDL::log_trace(vm, "AnimationEffectPrototype::get_timing");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] Animations::AnimationEffect* idl_object = TRY(impl_from(vm));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->get_timing(); }));
    return [&]() -> JS::Value {
        // 1. Let O be OrdinaryObjectCreate(%Object.prototype%).
        auto dictionary_object = JS::Object::create(realm, realm.intrinsics().object_prototype());

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("delay"_utf16_fly_string, JS::Value(R.delay)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("direction"_utf16_fly_string, JS::PrimitiveString::create(vm, idl_enum_to_string(R.direction))));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("duration"_utf16_fly_string, R.duration.visit(
        [&](double const& visited_union_value0) -> JS::Value
        {
            return JS::Value(visited_union_value0);
        },
        [&](GC::Ref<CSS::CSSNumericValue> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        },
        [&](String const& visited_union_value2) -> JS::Value
        {
            return WebIDL::primitive_string_from_string(vm, visited_union_value2);
        }
    )));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("easing"_utf16_fly_string, WebIDL::primitive_string_from_string(vm, R.easing)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("endDelay"_utf16_fly_string, JS::Value(R.end_delay)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("fill"_utf16_fly_string, JS::PrimitiveString::create(vm, idl_enum_to_string(R.fill))));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("iterationStart"_utf16_fly_string, JS::Value(R.iteration_start)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("iterations"_utf16_fly_string, JS::Value(R.iterations)));

        // 4. Return O.
        return dictionary_object;
    }();
}

JS_DEFINE_NATIVE_FUNCTION(AnimationEffectPrototype::get_computed_timing)
{
    WebIDL::log_trace(vm, "AnimationEffectPrototype::get_computed_timing");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] Animations::AnimationEffect* idl_object = TRY(impl_from(vm));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->get_computed_timing(); }));
    return [&]() -> JS::Value {
        // 1. Let O be OrdinaryObjectCreate(%Object.prototype%).
        auto dictionary_object = JS::Object::create(realm, realm.intrinsics().object_prototype());

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("delay"_utf16_fly_string, JS::Value(R.delay)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("direction"_utf16_fly_string, JS::PrimitiveString::create(vm, idl_enum_to_string(R.direction))));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("duration"_utf16_fly_string, R.duration.visit(
        [&](double const& visited_union_value0) -> JS::Value
        {
            return JS::Value(visited_union_value0);
        },
        [&](GC::Ref<CSS::CSSNumericValue> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        },
        [&](String const& visited_union_value2) -> JS::Value
        {
            return WebIDL::primitive_string_from_string(vm, visited_union_value2);
        }
    )));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("easing"_utf16_fly_string, WebIDL::primitive_string_from_string(vm, R.easing)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("endDelay"_utf16_fly_string, JS::Value(R.end_delay)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("fill"_utf16_fly_string, JS::PrimitiveString::create(vm, idl_enum_to_string(R.fill))));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("iterationStart"_utf16_fly_string, JS::Value(R.iteration_start)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("iterations"_utf16_fly_string, JS::Value(R.iterations)));

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:
        if (R.active_duration.has_value()) {

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("activeDuration"_utf16_fly_string, R.active_duration.value().visit(
        [&](double const& visited_union_value0) -> JS::Value
        {
            return JS::Value(visited_union_value0);
        },
        [&](GC::Ref<CSS::CSSNumericValue> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        }
    )));
        }

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:
        if (R.current_iteration.has_value()) {

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("currentIteration"_utf16_fly_string, [&]() -> JS::Value {
        // 1. If the IDL nullable type T? value is null, then the JavaScript value is null.
        if (!R.current_iteration.value().has_value())
            return JS::js_null();

        // 2. Otherwise, the JavaScript value is the result of converting the IDL nullable type value to the inner IDL type T.
        return JS::Value(JS::Value(R.current_iteration.value().value()));
    }()));
        }

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:
        if (R.end_time.has_value()) {

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("endTime"_utf16_fly_string, R.end_time.value().visit(
        [&](double const& visited_union_value0) -> JS::Value
        {
            return JS::Value(visited_union_value0);
        },
        [&](GC::Ref<CSS::CSSNumericValue> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        }
    )));
        }

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:
        if (R.local_time.has_value()) {

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("localTime"_utf16_fly_string, R.local_time.value().visit(
        [&](double const& visited_union_value0) -> JS::Value
        {
            return JS::Value(visited_union_value0);
        },
        [&](GC::Ref<CSS::CSSNumericValue> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        },
        [](Empty) -> JS::Value
        {
            return JS::js_null();
        }
    )));
        }

        // 1. Let key be the identifier of member.
        // 2. If V[key] exists, then:
        if (R.progress.has_value()) {

        // 1. Let idlValue be V[key].
        // 2. Let value be the result of converting idlValue to a JavaScript value.
        // 3. Perform ! CreateDataPropertyOrThrow(O, key, value).
        MUST(dictionary_object->create_data_property("progress"_utf16_fly_string, [&]() -> JS::Value {
        // 1. If the IDL nullable type T? value is null, then the JavaScript value is null.
        if (!R.progress.value().has_value())
            return JS::js_null();

        // 2. Otherwise, the JavaScript value is the result of converting the IDL nullable type value to the inner IDL type T.
        return JS::Value(JS::Value(R.progress.value().value()));
    }()));
        }

        // 4. Return O.
        return dictionary_object;
    }();
}

JS_DEFINE_NATIVE_FUNCTION(AnimationEffectPrototype::update_timing)
{
    WebIDL::log_trace(vm, "AnimationEffectPrototype::update_timing");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] Animations::AnimationEffect* idl_object = TRY(impl_from(vm));

    auto arg0 = vm.argument(0);
    OptionalEffectTiming timing = OptionalEffectTiming {};
    if (!arg0.is_undefined())
        timing = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_optional_effect_timing(vm, arg0); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->update_timing(timing); }));
    return JS::js_undefined();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<FillMode> convert_to_idl_value_for_fill_mode(JS::VM& vm, JS::Value value)
{
    // 1. Let S be the result of calling ? ToString(V).
    auto value_as_string = TRY(value.to_utf16_string(vm));

    // 2. If S is not one of E’s enumeration values, then throw a TypeError.
    // 3. Return the enumeration value of type E that is equal to S.
    if (value_as_string == "none"sv)
        return FillMode::None;
    if (value_as_string == "forwards"sv)
        return FillMode::Forwards;
    if (value_as_string == "backwards"sv)
        return FillMode::Backwards;
    if (value_as_string == "both"sv)
        return FillMode::Both;
    if (value_as_string == "auto"sv)
        return FillMode::Auto;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "FillMode");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(FillMode value)
{
    // The result of converting an IDL enumeration type value to a JavaScript value is the String value that represents the same sequence of code units as the enumeration value.
    switch (value) {
    case FillMode::None:
        return "none"_utf16;
    case FillMode::Forwards:
        return "forwards"_utf16;
    case FillMode::Backwards:
        return "backwards"_utf16;
    case FillMode::Both:
        return "both"_utf16;
    case FillMode::Auto:
        return "auto"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<PlaybackDirection> convert_to_idl_value_for_playback_direction(JS::VM& vm, JS::Value value)
{
    // 1. Let S be the result of calling ? ToString(V).
    auto value_as_string = TRY(value.to_utf16_string(vm));

    // 2. If S is not one of E’s enumeration values, then throw a TypeError.
    // 3. Return the enumeration value of type E that is equal to S.
    if (value_as_string == "normal"sv)
        return PlaybackDirection::Normal;
    if (value_as_string == "reverse"sv)
        return PlaybackDirection::Reverse;
    if (value_as_string == "alternate"sv)
        return PlaybackDirection::Alternate;
    if (value_as_string == "alternate-reverse"sv)
        return PlaybackDirection::AlternateReverse;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "PlaybackDirection");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(PlaybackDirection value)
{
    // The result of converting an IDL enumeration type value to a JavaScript value is the String value that represents the same sequence of code units as the enumeration value.
    switch (value) {
    case PlaybackDirection::Normal:
        return "normal"_utf16;
    case PlaybackDirection::Reverse:
        return "reverse"_utf16;
    case PlaybackDirection::Alternate:
        return "alternate"_utf16;
    case PlaybackDirection::AlternateReverse:
        return "alternate-reverse"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#es-dictionary
JS::ThrowCompletionOr<EffectTiming> convert_to_idl_value_for_effect_timing(JS::VM& vm, JS::Value js_dict)
{
    // 1. If jsDict is not an Object and jsDict is neither undefined nor null, then throw a TypeError.
    if (!js_dict.is_object() && !js_dict.is_nullish())
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "EffectTiming");

    // 2. Let idlDict be an empty ordered map, representing a dictionary of type D.
    // 3. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
    // 4. For each dictionary dictionary in dictionaries, in order:
    // NB: We defer construction until the return initializer because some members may not be default-constructible. Inherited dictionaries are represented by the generated C++ struct inheritance.

    // 5. Return idlDict.
    return EffectTiming {
        .delay = TRY([&]() -> JS::ThrowCompletionOr<double> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("delay"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "delay");
        return x;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = 0;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .direction = TRY([&]() -> JS::ThrowCompletionOr<PlaybackDirection> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("direction"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_playback_direction(vm, js_member_value); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = PlaybackDirection::Normal;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .duration = TRY([&]() -> JS::ThrowCompletionOr<Variant<double, GC::Ref<CSS::CSSNumericValue>, String>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("duration"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<double, GC::Ref<CSS::CSSNumericValue>, String>> {

        if (js_member_value.is_object()) {
            [[maybe_unused]] auto& object = js_member_value.as_object();

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<CSS::CSSNumericValue>(object))
                    return Variant<double, GC::Ref<CSS::CSSNumericValue>, String> { GC::Ref { *result } };
            }
        }

        if (js_member_value.is_number()) {
            auto duration_number = TRY(js_member_value.to_double(vm));
            return Variant<double, GC::Ref<CSS::CSSNumericValue>, String> { duration_number };
        }

        auto duration_string = TRY([&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, js_member_value));
    }());
        return Variant<double, GC::Ref<CSS::CSSNumericValue>, String> { duration_string };

        auto duration_number_fallback = TRY(js_member_value.to_double(vm));
        return Variant<double, GC::Ref<CSS::CSSNumericValue>, String> { duration_number_fallback };

        return vm.throw_completion<JS::TypeError>("No union types matched"_utf16);
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = Variant<double, GC::Ref<CSS::CSSNumericValue>, String> { "auto"_string };

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .easing = TRY([&]() -> JS::ThrowCompletionOr<String> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("easing"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, js_member_value));
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = "linear"_string;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .end_delay = TRY([&]() -> JS::ThrowCompletionOr<double> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("endDelay"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "endDelay");
        return x;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = 0;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .fill = TRY([&]() -> JS::ThrowCompletionOr<FillMode> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("fill"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_fill_mode(vm, js_member_value); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = FillMode::Auto;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .iteration_start = TRY([&]() -> JS::ThrowCompletionOr<double> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("iterationStart"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "iterationStart");
        return x;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = 0.0;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
        .iterations = TRY([&]() -> JS::ThrowCompletionOr<double> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("iterations"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return js_member_value.to_double(vm); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 5. Otherwise, if jsMemberValue is undefined but member has a default value, then:
            // 1. Let idlMemberValue be the result of converting member's default value to an IDL value whose type is the type member is declared to be of.
            auto idl_member_value = 1.0;

            // 2. Set idlDict[key] to idlMemberValue.
            return idl_member_value;
        }()),
    };
}

// https://webidl.spec.whatwg.org/#es-dictionary
JS::ThrowCompletionOr<OptionalEffectTiming> convert_to_idl_value_for_optional_effect_timing(JS::VM& vm, JS::Value js_dict)
{
    // 1. If jsDict is not an Object and jsDict is neither undefined nor null, then throw a TypeError.
    if (!js_dict.is_object() && !js_dict.is_nullish())
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "OptionalEffectTiming");

    // 2. Let idlDict be an empty ordered map, representing a dictionary of type D.
    // 3. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
    // 4. For each dictionary dictionary in dictionaries, in order:
    // NB: We defer construction until the return initializer because some members may not be default-constructible. Inherited dictionaries are represented by the generated C++ struct inheritance.

    // 5. Return idlDict.
    return OptionalEffectTiming {
        .delay = TRY([&]() -> JS::ThrowCompletionOr<Optional<double>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("delay"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "delay");
        return x;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .direction = TRY([&]() -> JS::ThrowCompletionOr<Optional<PlaybackDirection>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("direction"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_playback_direction(vm, js_member_value); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .duration = TRY([&]() -> JS::ThrowCompletionOr<Optional<Variant<double, String>>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("duration"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<double, String>> {

        if (js_member_value.is_object()) {
            [[maybe_unused]] auto& object = js_member_value.as_object();
        }

        if (js_member_value.is_number()) {
            auto duration_number = TRY(js_member_value.to_double(vm));
            return Variant<double, String> { duration_number };
        }

        auto duration_string = TRY([&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, js_member_value));
    }());
        return Variant<double, String> { duration_string };

        auto duration_number_fallback = TRY(js_member_value.to_double(vm));
        return Variant<double, String> { duration_number_fallback };

        return vm.throw_completion<JS::TypeError>("No union types matched"_utf16);
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .easing = TRY([&]() -> JS::ThrowCompletionOr<Optional<String>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("easing"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, js_member_value));
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .end_delay = TRY([&]() -> JS::ThrowCompletionOr<Optional<double>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("endDelay"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "endDelay");
        return x;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .fill = TRY([&]() -> JS::ThrowCompletionOr<Optional<FillMode>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("fill"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_fill_mode(vm, js_member_value); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .iteration_start = TRY([&]() -> JS::ThrowCompletionOr<Optional<double>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("iterationStart"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "iterationStart");
        return x;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        .iterations = TRY([&]() -> JS::ThrowCompletionOr<Optional<double>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("iterations"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return js_member_value.to_double(vm); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
    };
}

// https://webidl.spec.whatwg.org/#es-dictionary
JS::ThrowCompletionOr<ComputedEffectTiming> convert_to_idl_value_for_computed_effect_timing(JS::VM& vm, JS::Value js_dict)
{
    // 1. If jsDict is not an Object and jsDict is neither undefined nor null, then throw a TypeError.
    if (!js_dict.is_object() && !js_dict.is_nullish())
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "ComputedEffectTiming");

    // 2. Let idlDict be an empty ordered map, representing a dictionary of type D.
    // 3. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
    // 4. For each dictionary dictionary in dictionaries, in order:
    // NB: We defer construction until the return initializer because some members may not be default-constructible. Inherited dictionaries are represented by the generated C++ struct inheritance.

    // 5. Return idlDict.
    return ComputedEffectTiming {
        TRY(convert_to_idl_value_for_effect_timing(vm, js_dict)),
        TRY([&]() -> JS::ThrowCompletionOr<Optional<Variant<double, GC::Ref<CSS::CSSNumericValue>>>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("activeDuration"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<double, GC::Ref<CSS::CSSNumericValue>>> {

        if (js_member_value.is_object()) {
            [[maybe_unused]] auto& object = js_member_value.as_object();

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<CSS::CSSNumericValue>(object))
                    return Variant<double, GC::Ref<CSS::CSSNumericValue>> { GC::Ref { *result } };
            }
        }

        if (js_member_value.is_number()) {
            auto activeDuration_number = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "activeDuration");
        return x;
    }());
            return Variant<double, GC::Ref<CSS::CSSNumericValue>> { activeDuration_number };
        }

        auto activeDuration_number_fallback = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "activeDuration");
        return x;
    }());
        return Variant<double, GC::Ref<CSS::CSSNumericValue>> { activeDuration_number_fallback };

        return vm.throw_completion<JS::TypeError>("No union types matched"_utf16);
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        TRY([&]() -> JS::ThrowCompletionOr<Optional<Optional<double>>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("currentIteration"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Optional<Optional<double>>> {
        Optional<double> value;

        if (!js_member_value.is_nullish()) {

            value = TRY(js_member_value.to_double(vm));
        }
        return value;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        TRY([&]() -> JS::ThrowCompletionOr<Optional<Variant<double, GC::Ref<CSS::CSSNumericValue>>>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("endTime"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<double, GC::Ref<CSS::CSSNumericValue>>> {

        if (js_member_value.is_object()) {
            [[maybe_unused]] auto& object = js_member_value.as_object();

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<CSS::CSSNumericValue>(object))
                    return Variant<double, GC::Ref<CSS::CSSNumericValue>> { GC::Ref { *result } };
            }
        }

        if (js_member_value.is_number()) {
            auto endTime_number = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "endTime");
        return x;
    }());
            return Variant<double, GC::Ref<CSS::CSSNumericValue>> { endTime_number };
        }

        auto endTime_number_fallback = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "endTime");
        return x;
    }());
        return Variant<double, GC::Ref<CSS::CSSNumericValue>> { endTime_number_fallback };

        return vm.throw_completion<JS::TypeError>("No union types matched"_utf16);
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        TRY([&]() -> JS::ThrowCompletionOr<Optional<Variant<double, GC::Ref<CSS::CSSNumericValue>, Empty>>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("localTime"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Optional<Variant<double, GC::Ref<CSS::CSSNumericValue>, Empty>>> {
        Variant<double, GC::Ref<CSS::CSSNumericValue>, Empty> value;

        if (!js_member_value.is_nullish()) {

            value = TRY([&]() -> JS::ThrowCompletionOr<Variant<double, GC::Ref<CSS::CSSNumericValue>>> {

        if (js_member_value.is_object()) {
            [[maybe_unused]] auto& object = js_member_value.as_object();

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<CSS::CSSNumericValue>(object))
                    return Variant<double, GC::Ref<CSS::CSSNumericValue>> { GC::Ref { *result } };
            }
        }

        if (js_member_value.is_number()) {
            auto localTime_number = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "localTime");
        return x;
    }());
            return Variant<double, GC::Ref<CSS::CSSNumericValue>> { localTime_number };
        }

        auto localTime_number_fallback = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "localTime");
        return x;
    }());
        return Variant<double, GC::Ref<CSS::CSSNumericValue>> { localTime_number_fallback };

        return vm.throw_completion<JS::TypeError>("No union types matched"_utf16);
    }());
        }
        return value;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
        TRY([&]() -> JS::ThrowCompletionOr<Optional<Optional<double>>> {
            // 1. Let key be the identifier of member.
            // 2. If jsDict is either undefined or null, then:
            //     1. Let jsMemberValue be undefined.
            // 3. Otherwise,
            //     1. Let jsMemberValue be ? Get(jsDict, key).
            auto js_member_value = JS::js_undefined();
            if (js_dict.is_object())
                js_member_value = TRY(js_dict.as_object().get("progress"_utf16_fly_string));

            // 4. If jsMemberValue is not undefined, then:
            if (!js_member_value.is_undefined()) {
                // 1. Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
                auto idl_member_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Optional<Optional<double>>> {
        Optional<double> value;

        if (!js_member_value.is_nullish()) {

            value = TRY([&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(js_member_value.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "progress");
        return x;
    }());
        }
        return value;
    }(); }));

                // 2. Set idlDict[key] to idlMemberValue.
                return idl_member_value;
            }
            // 7. Otherwise, jsMemberValue is undefined and the member is optional.
            return OptionalNone {};
        }()),
    };
}

} // namespace Web::Bindings
