#include <AK/Optional.h>
#include <AK/String.h>
#include <AK/Utf16String.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/Iterator.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/Bindings/CanvasRenderingContext2D.h>
#include <LibWeb/Bindings/CanvasRenderingContext2DSettings.h>
#include <LibWeb/Bindings/DOMMatrixReadOnly.h>
#include <LibWeb/Bindings/DOMPointReadOnly.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/ImageData.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/Bindings/PredefinedColorSpace.h>
#include <LibWeb/Geometry/DOMMatrix.h>
#include <LibWeb/HTML/CanvasGradient.h>
#include <LibWeb/HTML/CanvasPattern.h>
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
#include <LibWeb/HTML/HTMLCanvasElement.h>
#include <LibWeb/HTML/HTMLImageElement.h>
#include <LibWeb/HTML/HTMLVideoElement.h>
#include <LibWeb/HTML/ImageBitmap.h>
#include <LibWeb/HTML/ImageData.h>
#include <LibWeb/HTML/OffscreenCanvas.h>
#include <LibWeb/HTML/Path2D.h>
#include <LibWeb/HTML/TextMetrics.h>
#include <LibWeb/SVG/SVGImageElement.h>
#include <LibWeb/WebIDL/AbstractOperations.h>
#include <LibWeb/WebIDL/OverloadResolution.h>
#include <LibWeb/WebIDL/OverloadTypes.h>
#include <LibWeb/WebIDL/Tracing.h>
#include <LibWeb/WebIDL/Types.h>

namespace Web::Bindings {

void CanvasRenderingContext2DConstructor::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, "CanvasRenderingContext2D"_utf16), JS::Attribute::Configurable);
    object.define_direct_property(vm.names.prototype, &ensure_web_prototype<CanvasRenderingContext2DPrototype>(realm, "CanvasRenderingContext2D"_fly_string), 0);
}

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

void CanvasRenderingContext2DPrototype::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());

    auto canvas_id = "canvas"_utf16_fly_string;
    auto native_canvas_getter = JS::NativeFunction::create(realm, canvas_getter, 0, canvas_id, &realm, "get"sv);
    GC::Ptr<JS::NativeFunction> native_canvas_setter;

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto canvas_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(canvas_id, native_canvas_getter, native_canvas_setter, canvas_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto global_alpha_id = "globalAlpha"_utf16_fly_string;
    auto native_global_alpha_getter = JS::NativeFunction::create(realm, global_alpha_getter, 0, global_alpha_id, &realm, "get"sv);
    auto native_global_alpha_setter = JS::NativeFunction::create(realm, global_alpha_setter, 1, global_alpha_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto global_alpha_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(global_alpha_id, native_global_alpha_getter, native_global_alpha_setter, global_alpha_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto global_composite_operation_id = "globalCompositeOperation"_utf16_fly_string;
    auto native_global_composite_operation_getter = JS::NativeFunction::create(realm, global_composite_operation_getter, 0, global_composite_operation_id, &realm, "get"sv);
    auto native_global_composite_operation_setter = JS::NativeFunction::create(realm, global_composite_operation_setter, 1, global_composite_operation_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto global_composite_operation_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(global_composite_operation_id, native_global_composite_operation_getter, native_global_composite_operation_setter, global_composite_operation_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto image_smoothing_enabled_id = "imageSmoothingEnabled"_utf16_fly_string;
    auto native_image_smoothing_enabled_getter = JS::NativeFunction::create(realm, image_smoothing_enabled_getter, 0, image_smoothing_enabled_id, &realm, "get"sv);
    auto native_image_smoothing_enabled_setter = JS::NativeFunction::create(realm, image_smoothing_enabled_setter, 1, image_smoothing_enabled_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto image_smoothing_enabled_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(image_smoothing_enabled_id, native_image_smoothing_enabled_getter, native_image_smoothing_enabled_setter, image_smoothing_enabled_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto image_smoothing_quality_id = "imageSmoothingQuality"_utf16_fly_string;
    auto native_image_smoothing_quality_getter = JS::NativeFunction::create(realm, image_smoothing_quality_getter, 0, image_smoothing_quality_id, &realm, "get"sv);
    auto native_image_smoothing_quality_setter = JS::NativeFunction::create(realm, image_smoothing_quality_setter, 1, image_smoothing_quality_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto image_smoothing_quality_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(image_smoothing_quality_id, native_image_smoothing_quality_getter, native_image_smoothing_quality_setter, image_smoothing_quality_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto stroke_style_id = "strokeStyle"_utf16_fly_string;
    auto native_stroke_style_getter = JS::NativeFunction::create(realm, stroke_style_getter, 0, stroke_style_id, &realm, "get"sv);
    auto native_stroke_style_setter = JS::NativeFunction::create(realm, stroke_style_setter, 1, stroke_style_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto stroke_style_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(stroke_style_id, native_stroke_style_getter, native_stroke_style_setter, stroke_style_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto fill_style_id = "fillStyle"_utf16_fly_string;
    auto native_fill_style_getter = JS::NativeFunction::create(realm, fill_style_getter, 0, fill_style_id, &realm, "get"sv);
    auto native_fill_style_setter = JS::NativeFunction::create(realm, fill_style_setter, 1, fill_style_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto fill_style_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(fill_style_id, native_fill_style_getter, native_fill_style_setter, fill_style_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto shadow_offset_x_id = "shadowOffsetX"_utf16_fly_string;
    auto native_shadow_offset_x_getter = JS::NativeFunction::create(realm, shadow_offset_x_getter, 0, shadow_offset_x_id, &realm, "get"sv);
    auto native_shadow_offset_x_setter = JS::NativeFunction::create(realm, shadow_offset_x_setter, 1, shadow_offset_x_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto shadow_offset_x_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(shadow_offset_x_id, native_shadow_offset_x_getter, native_shadow_offset_x_setter, shadow_offset_x_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto shadow_offset_y_id = "shadowOffsetY"_utf16_fly_string;
    auto native_shadow_offset_y_getter = JS::NativeFunction::create(realm, shadow_offset_y_getter, 0, shadow_offset_y_id, &realm, "get"sv);
    auto native_shadow_offset_y_setter = JS::NativeFunction::create(realm, shadow_offset_y_setter, 1, shadow_offset_y_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto shadow_offset_y_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(shadow_offset_y_id, native_shadow_offset_y_getter, native_shadow_offset_y_setter, shadow_offset_y_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto shadow_blur_id = "shadowBlur"_utf16_fly_string;
    auto native_shadow_blur_getter = JS::NativeFunction::create(realm, shadow_blur_getter, 0, shadow_blur_id, &realm, "get"sv);
    auto native_shadow_blur_setter = JS::NativeFunction::create(realm, shadow_blur_setter, 1, shadow_blur_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto shadow_blur_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(shadow_blur_id, native_shadow_blur_getter, native_shadow_blur_setter, shadow_blur_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto shadow_color_id = "shadowColor"_utf16_fly_string;
    auto native_shadow_color_getter = JS::NativeFunction::create(realm, shadow_color_getter, 0, shadow_color_id, &realm, "get"sv);
    auto native_shadow_color_setter = JS::NativeFunction::create(realm, shadow_color_setter, 1, shadow_color_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto shadow_color_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(shadow_color_id, native_shadow_color_getter, native_shadow_color_setter, shadow_color_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto filter_id = "filter"_utf16_fly_string;
    auto native_filter_getter = JS::NativeFunction::create(realm, filter_getter, 0, filter_id, &realm, "get"sv);
    auto native_filter_setter = JS::NativeFunction::create(realm, filter_setter, 1, filter_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto filter_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(filter_id, native_filter_getter, native_filter_setter, filter_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto line_width_id = "lineWidth"_utf16_fly_string;
    auto native_line_width_getter = JS::NativeFunction::create(realm, line_width_getter, 0, line_width_id, &realm, "get"sv);
    auto native_line_width_setter = JS::NativeFunction::create(realm, line_width_setter, 1, line_width_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto line_width_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(line_width_id, native_line_width_getter, native_line_width_setter, line_width_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto line_cap_id = "lineCap"_utf16_fly_string;
    auto native_line_cap_getter = JS::NativeFunction::create(realm, line_cap_getter, 0, line_cap_id, &realm, "get"sv);
    auto native_line_cap_setter = JS::NativeFunction::create(realm, line_cap_setter, 1, line_cap_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto line_cap_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(line_cap_id, native_line_cap_getter, native_line_cap_setter, line_cap_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto line_join_id = "lineJoin"_utf16_fly_string;
    auto native_line_join_getter = JS::NativeFunction::create(realm, line_join_getter, 0, line_join_id, &realm, "get"sv);
    auto native_line_join_setter = JS::NativeFunction::create(realm, line_join_setter, 1, line_join_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto line_join_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(line_join_id, native_line_join_getter, native_line_join_setter, line_join_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto miter_limit_id = "miterLimit"_utf16_fly_string;
    auto native_miter_limit_getter = JS::NativeFunction::create(realm, miter_limit_getter, 0, miter_limit_id, &realm, "get"sv);
    auto native_miter_limit_setter = JS::NativeFunction::create(realm, miter_limit_setter, 1, miter_limit_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto miter_limit_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(miter_limit_id, native_miter_limit_getter, native_miter_limit_setter, miter_limit_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto line_dash_offset_id = "lineDashOffset"_utf16_fly_string;
    auto native_line_dash_offset_getter = JS::NativeFunction::create(realm, line_dash_offset_getter, 0, line_dash_offset_id, &realm, "get"sv);
    auto native_line_dash_offset_setter = JS::NativeFunction::create(realm, line_dash_offset_setter, 1, line_dash_offset_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto line_dash_offset_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(line_dash_offset_id, native_line_dash_offset_getter, native_line_dash_offset_setter, line_dash_offset_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto font_id = "font"_utf16_fly_string;
    auto native_font_getter = JS::NativeFunction::create(realm, font_getter, 0, font_id, &realm, "get"sv);
    auto native_font_setter = JS::NativeFunction::create(realm, font_setter, 1, font_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto font_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(font_id, native_font_getter, native_font_setter, font_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto text_align_id = "textAlign"_utf16_fly_string;
    auto native_text_align_getter = JS::NativeFunction::create(realm, text_align_getter, 0, text_align_id, &realm, "get"sv);
    auto native_text_align_setter = JS::NativeFunction::create(realm, text_align_setter, 1, text_align_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto text_align_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(text_align_id, native_text_align_getter, native_text_align_setter, text_align_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto text_baseline_id = "textBaseline"_utf16_fly_string;
    auto native_text_baseline_getter = JS::NativeFunction::create(realm, text_baseline_getter, 0, text_baseline_id, &realm, "get"sv);
    auto native_text_baseline_setter = JS::NativeFunction::create(realm, text_baseline_setter, 1, text_baseline_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto text_baseline_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(text_baseline_id, native_text_baseline_getter, native_text_baseline_setter, text_baseline_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto direction_id = "direction"_utf16_fly_string;
    auto native_direction_getter = JS::NativeFunction::create(realm, direction_getter, 0, direction_id, &realm, "get"sv);
    auto native_direction_setter = JS::NativeFunction::create(realm, direction_setter, 1, direction_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto direction_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(direction_id, native_direction_getter, native_direction_setter, direction_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    auto letter_spacing_id = "letterSpacing"_utf16_fly_string;
    auto native_letter_spacing_getter = JS::NativeFunction::create(realm, letter_spacing_getter, 0, letter_spacing_id, &realm, "get"sv);
    auto native_letter_spacing_setter = JS::NativeFunction::create(realm, letter_spacing_setter, 1, letter_spacing_id, &realm, "set"sv);

    // 4. Let configurable be false if attr is unforgeable and true otherwise.
    auto letter_spacing_attributes = default_attributes;

    // 5. Let desc be the PropertyDescriptor{[[Get]]: getter, [[Set]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}.

    // 7. Perform ! DefinePropertyOrThrow(target, id, desc).
    object.define_direct_accessor(letter_spacing_id, native_letter_spacing_getter, native_letter_spacing_setter, letter_spacing_attributes);

    // 8. FIXME: If attr’s type is an observable array type with type argument T, then set target’s backing observable array exotic object for attr to the result of creating an observable array exotic object in realm, given T, attr’s set an indexed value algorithm, and attr’s delete an indexed value algorithm.
    object.define_native_function(realm, "getContextAttributes"_utf16_fly_string, get_context_attributes, 0, default_attributes);

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

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

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

    object.define_native_function(realm, "isContextLost"_utf16_fly_string, is_context_lost, 0, default_attributes);

    object.define_native_function(realm, "scale"_utf16_fly_string, scale, 2, default_attributes);

    object.define_native_function(realm, "rotate"_utf16_fly_string, rotate, 1, default_attributes);

    object.define_native_function(realm, "translate"_utf16_fly_string, translate, 2, default_attributes);

    object.define_native_function(realm, "transform"_utf16_fly_string, transform, 6, default_attributes);

    object.define_native_function(realm, "getTransform"_utf16_fly_string, get_transform, 0, default_attributes);

    object.define_native_function(realm, "setTransform"_utf16_fly_string, set_transform, 0, default_attributes);

    object.define_native_function(realm, "resetTransform"_utf16_fly_string, reset_transform, 0, default_attributes);

    object.define_native_function(realm, "createLinearGradient"_utf16_fly_string, create_linear_gradient, 4, default_attributes);

    object.define_native_function(realm, "createRadialGradient"_utf16_fly_string, create_radial_gradient, 6, default_attributes);

    object.define_native_function(realm, "createConicGradient"_utf16_fly_string, create_conic_gradient, 3, default_attributes);

    object.define_native_function(realm, "createPattern"_utf16_fly_string, create_pattern, 2, default_attributes);

    object.define_native_function(realm, "clearRect"_utf16_fly_string, clear_rect, 4, default_attributes);

    object.define_native_function(realm, "fillRect"_utf16_fly_string, fill_rect, 4, default_attributes);

    object.define_native_function(realm, "strokeRect"_utf16_fly_string, stroke_rect, 4, default_attributes);

    object.define_native_function(realm, "beginPath"_utf16_fly_string, begin_path, 0, default_attributes);

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

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

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

    object.define_native_function(realm, "isPointInPath"_utf16_fly_string, is_point_in_path, 2, default_attributes);

    object.define_native_function(realm, "fillText"_utf16_fly_string, fill_text, 3, default_attributes);

    object.define_native_function(realm, "strokeText"_utf16_fly_string, stroke_text, 3, default_attributes);

    object.define_native_function(realm, "measureText"_utf16_fly_string, measure_text, 1, default_attributes);

    object.define_native_function(realm, "drawImage"_utf16_fly_string, draw_image, 3, default_attributes);

    object.define_native_function(realm, "createImageData"_utf16_fly_string, create_image_data, 1, default_attributes);

    object.define_native_function(realm, "getImageData"_utf16_fly_string, get_image_data, 4, default_attributes);

    object.define_native_function(realm, "putImageData"_utf16_fly_string, put_image_data, 3, default_attributes);

    object.define_native_function(realm, "setLineDash"_utf16_fly_string, set_line_dash, 1, default_attributes);

    object.define_native_function(realm, "getLineDash"_utf16_fly_string, get_line_dash, 0, default_attributes);

    object.define_native_function(realm, "closePath"_utf16_fly_string, close_path, 0, default_attributes);

    object.define_native_function(realm, "moveTo"_utf16_fly_string, move_to, 2, default_attributes);

    object.define_native_function(realm, "lineTo"_utf16_fly_string, line_to, 2, default_attributes);

    object.define_native_function(realm, "quadraticCurveTo"_utf16_fly_string, quadratic_curve_to, 4, default_attributes);

    object.define_native_function(realm, "bezierCurveTo"_utf16_fly_string, bezier_curve_to, 6, default_attributes);

    object.define_native_function(realm, "arcTo"_utf16_fly_string, arc_to, 5, default_attributes);

    object.define_native_function(realm, "rect"_utf16_fly_string, rect, 4, default_attributes);

    object.define_native_function(realm, "roundRect"_utf16_fly_string, round_rect, 4, default_attributes);

    object.define_native_function(realm, "arc"_utf16_fly_string, arc, 5, default_attributes);

    object.define_native_function(realm, "ellipse"_utf16_fly_string, ellipse, 7, default_attributes);

    object.define_direct_property("isPointInStroke"_utf16_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented);

    object.define_direct_property("isPointInStroke"_utf16_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented);

    object.define_direct_property("drawFocusIfNeeded"_utf16_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented);

    object.define_direct_property("drawFocusIfNeeded"_utf16_fly_string, JS::js_undefined(), default_attributes | JS::Attribute::Unimplemented);

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

void CanvasRenderingContext2DPrototype::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<HTML::CanvasRenderingContext2D*> impl_from(JS::VM& vm, JS::Value js_value)
{

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

[[maybe_unused]] static JS::ThrowCompletionOr<HTML::CanvasRenderingContext2D*> 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(CanvasRenderingContext2DPrototype::canvas_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::canvas_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->canvas_for_binding(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::global_alpha_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::global_alpha_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->global_alpha(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::global_composite_operation_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::global_composite_operation_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->global_composite_operation(); }));

    return WebIDL::primitive_string_from_string(vm, R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::image_smoothing_enabled_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::image_smoothing_enabled_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->image_smoothing_enabled(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::image_smoothing_quality_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::image_smoothing_quality_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->image_smoothing_quality(); }));

    return JS::PrimitiveString::create(vm, idl_enum_to_string(R));
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke_style_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke_style_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->stroke_style(); }));

    return R.visit(
        [&](String const& visited_union_value0) -> JS::Value
        {
            return WebIDL::primitive_string_from_string(vm, visited_union_value0);
        },
        [&](GC::Ref<HTML::CanvasGradient> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        },
        [&](GC::Ref<HTML::CanvasPattern> const& visited_union_value2) -> JS::Value
        {
            return JS::Value(visited_union_value2);
        }
    );
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill_style_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill_style_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->fill_style(); }));

    return R.visit(
        [&](String const& visited_union_value0) -> JS::Value
        {
            return WebIDL::primitive_string_from_string(vm, visited_union_value0);
        },
        [&](GC::Ref<HTML::CanvasGradient> const& visited_union_value1) -> JS::Value
        {
            return JS::Value(visited_union_value1);
        },
        [&](GC::Ref<HTML::CanvasPattern> const& visited_union_value2) -> JS::Value
        {
            return JS::Value(visited_union_value2);
        }
    );
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_offset_x_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_offset_x_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->shadow_offset_x(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_offset_y_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_offset_y_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->shadow_offset_y(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_blur_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_blur_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->shadow_blur(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_color_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_color_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->shadow_color(); }));

    return WebIDL::primitive_string_from_string(vm, R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::filter_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::filter_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->filter(); }));

    return WebIDL::primitive_string_from_string(vm, R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_width_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_width_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->line_width(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_cap_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_cap_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->line_cap(); }));

    return JS::PrimitiveString::create(vm, idl_enum_to_string(R));
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_join_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_join_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->line_join(); }));

    return JS::PrimitiveString::create(vm, idl_enum_to_string(R));
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::miter_limit_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::miter_limit_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->miter_limit(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_dash_offset_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_dash_offset_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->line_dash_offset(); }));

    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::font_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::font_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->font(); }));

    return WebIDL::primitive_string_from_string(vm, R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::text_align_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::text_align_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->text_align(); }));

    return JS::PrimitiveString::create(vm, idl_enum_to_string(R));
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::text_baseline_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::text_baseline_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->text_baseline(); }));

    return JS::PrimitiveString::create(vm, idl_enum_to_string(R));
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::direction_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::direction_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->direction(); }));

    return JS::PrimitiveString::create(vm, idl_enum_to_string(R));
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::letter_spacing_getter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::letter_spacing_getter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    auto* idl_object = TRY(impl_from(vm));


    auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->letter_spacing(); }));

    return WebIDL::primitive_string_from_string(vm, R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::global_alpha_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::global_alpha_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_global_alpha(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::global_composite_operation_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::global_composite_operation_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }(); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_global_composite_operation(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::image_smoothing_enabled_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::image_smoothing_enabled_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_boolean(); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_image_smoothing_enabled(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::image_smoothing_quality_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::image_smoothing_quality_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> attribute's type is an enumeration
        // 1. Let S be ? ToString(V).
        auto maybe_idl_value = throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_image_smoothing_quality(vm, V); });

        // 2. If S is not one of the enumeration's values, then return undefined.
        if (maybe_idl_value.is_error())
            return JS::js_undefined();

        // 3. Otherwise, idlValue is the enumeration value equal to S.
        auto idl_value = maybe_idl_value.release_value();

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_image_smoothing_quality(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke_style_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke_style_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>>> {

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

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<HTML::CanvasGradient>(object))
                    return Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::CanvasPattern>(object))
                    return Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>> { GC::Ref { *result } };
            }
        }

        auto strokeStyle_string = TRY([&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }());
        return Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>> { strokeStyle_string };

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

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_stroke_style(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill_style_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill_style_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>>> {

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

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<HTML::CanvasGradient>(object))
                    return Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::CanvasPattern>(object))
                    return Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>> { GC::Ref { *result } };
            }
        }

        auto fillStyle_string = TRY([&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }());
        return Variant<String, GC::Ref<HTML::CanvasGradient>, GC::Ref<HTML::CanvasPattern>> { fillStyle_string };

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

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_fill_style(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_offset_x_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_offset_x_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_shadow_offset_x(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_offset_y_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_offset_y_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_shadow_offset_y(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_blur_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_blur_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_shadow_blur(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::shadow_color_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::shadow_color_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }(); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_shadow_color(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::filter_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::filter_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }(); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_filter(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_width_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_width_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_line_width(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_cap_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_cap_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> attribute's type is an enumeration
        // 1. Let S be ? ToString(V).
        auto maybe_idl_value = throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_canvas_line_cap(vm, V); });

        // 2. If S is not one of the enumeration's values, then return undefined.
        if (maybe_idl_value.is_error())
            return JS::js_undefined();

        // 3. Otherwise, idlValue is the enumeration value equal to S.
        auto idl_value = maybe_idl_value.release_value();

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_line_cap(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_join_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_join_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> attribute's type is an enumeration
        // 1. Let S be ? ToString(V).
        auto maybe_idl_value = throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_canvas_line_join(vm, V); });

        // 2. If S is not one of the enumeration's values, then return undefined.
        if (maybe_idl_value.is_error())
            return JS::js_undefined();

        // 3. Otherwise, idlValue is the enumeration value equal to S.
        auto idl_value = maybe_idl_value.release_value();

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_line_join(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::miter_limit_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::miter_limit_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_miter_limit(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_dash_offset_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_dash_offset_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return V.to_double(vm); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_line_dash_offset(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::font_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::font_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }(); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_font(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::text_align_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::text_align_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> attribute's type is an enumeration
        // 1. Let S be ? ToString(V).
        auto maybe_idl_value = throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_canvas_text_align(vm, V); });

        // 2. If S is not one of the enumeration's values, then return undefined.
        if (maybe_idl_value.is_error())
            return JS::js_undefined();

        // 3. Otherwise, idlValue is the enumeration value equal to S.
        auto idl_value = maybe_idl_value.release_value();

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_text_align(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::text_baseline_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::text_baseline_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> attribute's type is an enumeration
        // 1. Let S be ? ToString(V).
        auto maybe_idl_value = throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_canvas_text_baseline(vm, V); });

        // 2. If S is not one of the enumeration's values, then return undefined.
        if (maybe_idl_value.is_error())
            return JS::js_undefined();

        // 3. Otherwise, idlValue is the enumeration value equal to S.
        auto idl_value = maybe_idl_value.release_value();

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_text_baseline(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::direction_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::direction_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> attribute's type is an enumeration
        // 1. Let S be ? ToString(V).
        auto maybe_idl_value = throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_canvas_direction(vm, V); });

        // 2. If S is not one of the enumeration's values, then return undefined.
        if (maybe_idl_value.is_error())
            return JS::js_undefined();

        // 3. Otherwise, idlValue is the enumeration value equal to S.
        auto idl_value = maybe_idl_value.release_value();

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_direction(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::letter_spacing_setter)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::letter_spacing_setter");
    [[maybe_unused]] auto& realm = *vm.current_realm();

    // 1. Let V be undefined.
    auto V = JS::js_undefined();

    // 2. If any arguments were passed, then set V to the value of the first argument passed.
    if (vm.argument_count() > 0)
        V = vm.argument(0);

    // 3. Let id be attribute’s identifier.

    // 4. Let idlObject be null.
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = nullptr;

    // 5. If attribute is a regular attribute:

    // 1. Let jsValue be the this value, if it is not null or undefined, or realm’s global object otherwise. (This will subsequently cause a TypeError in a few steps, if the global object does not implement target and [LegacyLenientThis] is not specified.)
    auto js_value = vm.this_value();
    if (js_value.is_nullish())
        js_value = &realm.global_object();

    // 2. FIXME: If jsValue is a platform object, then perform a security check, passing jsValue, attribute’s identifier, and "setter".

    // 3. Let validThis be true if jsValue implements target, or false otherwise.
    auto maybe_idl_object = impl_from(vm, js_value);

    // 4. If validThis is false and attribute was not specified with the [LegacyLenientThis] extended attribute, then throw a TypeError.
    idl_object = TRY(maybe_idl_object);

    auto original_steps = [&]() -> JS::ThrowCompletionOr<JS::Value> {
        // 6. Let idlValue be determined as follows:
        // -> Otherwise, idlValue is the result of converting V to an IDL value of attribute’s type.
        auto idl_value = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, V));
    }(); }));

        // 7. Run the setter steps of attribute with idlObject as this and idlValue as the value.
        auto setter_result = [&]() -> JS::ThrowCompletionOr<void> {
            TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_letter_spacing(idl_value); }));
    return {};
        }();

        if (setter_result.is_error())
            return setter_result.release_error();

        return JS::js_undefined();
    };

    // 8. Return undefined.
    return TRY(original_steps());
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::get_context_attributes)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::get_context_attributes");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->get_context_attributes(); }));
    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("alpha"_utf16_fly_string, JS::Value(R.alpha)));

        // 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("colorSpace"_utf16_fly_string, JS::PrimitiveString::create(vm, idl_enum_to_string(R.color_space))));

        // 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("colorType"_utf16_fly_string, JS::PrimitiveString::create(vm, idl_enum_to_string(R.color_type))));

        // 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("desynchronized"_utf16_fly_string, JS::Value(R.desynchronized)));

        // 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("willReadFrequently"_utf16_fly_string, JS::Value(R.will_read_frequently)));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::save)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::save");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::restore)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::restore");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::reset)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::reset");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::is_context_lost)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::is_context_lost");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::scale)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::scale");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "scale", "2");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::rotate)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::rotate");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "rotate");

    auto arg0 = vm.argument(0);
    auto radians = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::translate)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::translate");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "translate", "2");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::transform)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::transform");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 6)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "transform", "6");

    auto arg0 = vm.argument(0);
    auto a = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto b = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto c = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto d = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto e = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    auto arg5 = vm.argument(5);
    auto f = TRY(throw_dom_exception_if_needed(vm, [&] { return arg5.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->transform(a, b, c, d, e, f); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::get_transform)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::get_transform");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::set_transform)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::set_transform");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(6, vm.argument_count())) {
    case 0:
        chosen_overload_callable_id = 1;
        break;
    case 1:
        chosen_overload_callable_id = 1;
        break;
    case 6:
        chosen_overload_callable_id = 0;
        break;
    }

    Vector<StringView> dictionary_types {
        "DOMMatrix2DInit"sv,
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return set_transform0(vm);
    case 1:
        return set_transform1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::set_transform0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::set_transform0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 6)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "setTransform", "6");

    auto arg0 = vm.argument(0);
    auto a = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto b = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto c = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto d = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto e = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    auto arg5 = vm.argument(5);
    auto f = TRY(throw_dom_exception_if_needed(vm, [&] { return arg5.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->set_transform(a, b, c, d, e, f); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::set_transform1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::set_transform1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    auto arg0 = vm.argument(0);
    DOMMatrix2DInit transform = DOMMatrix2DInit {};
    if (!arg0.is_undefined())
        transform = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_dom_matrix2d_init(vm, arg0); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::reset_transform)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::reset_transform");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_linear_gradient)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_linear_gradient");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "createLinearGradient", "4");

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

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

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

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

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->create_linear_gradient(x0, y0, x1, y1); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_radial_gradient)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_radial_gradient");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 6)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "createRadialGradient", "6");

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

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

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

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

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

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

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->create_radial_gradient(x0, y0, r0, x1, y1, r1); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_conic_gradient)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_conic_gradient");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 3)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "createConicGradient", "3");

    auto arg0 = vm.argument(0);
    auto start_angle = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<double> {
        auto x = TRY(arg0.to_double(vm));
        if (isinf(x) || isnan(x))
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidRestrictedFloatingPointParameter, "startAngle");
        return x;
    }(); }));

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

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

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->create_conic_gradient(start_angle, x, y); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_pattern)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_pattern");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "createPattern", "2");

    auto arg0 = vm.argument(0);
    auto image = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>>> {

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

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<HTML::HTMLImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<SVG::SVGImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLVideoElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLCanvasElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::ImageBitmap>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::OffscreenCanvas>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };
            }
        }

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

    auto arg1 = vm.argument(1);
    auto repetition = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        String string;
        if (!arg1.is_null())
            string = TRY(WebIDL::to_string(vm, arg1));
        return string;
    }(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->create_pattern(image, repetition); }));
    return [&]() -> JS::Value {
        // 1. If the IDL nullable type T? value is null, then the JavaScript value is null.
        if (!R)
            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));
    }();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::clear_rect)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::clear_rect");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "clearRect", "4");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto w = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto h = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->clear_rect(x, y, w, h); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill_rect)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill_rect");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "fillRect", "4");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto w = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto h = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->fill_rect(x, y, w, h); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke_rect)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke_rect");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "strokeRect", "4");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto w = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto h = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->stroke_rect(x, y, w, h); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::begin_path)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::begin_path");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(2, vm.argument_count())) {
    case 0:
        chosen_overload_callable_id = 0;
        break;
    case 1: {
        Vector<WebIDL::EffectiveOverloadSet::Item> overloads;
        overloads.ensure_capacity(2);
        overloads.empend(0, Vector<NonnullRefPtr<WebIDL::Type const>> { make_ref_counted<WebIDL::Type>("DOMString", false) }, Vector<WebIDL::Optionality> { WebIDL::Optionality::Optional });
        overloads.empend(1, Vector<NonnullRefPtr<WebIDL::Type const>> { make_ref_counted<WebIDL::Type>("Path2D", false) }, Vector<WebIDL::Optionality> { WebIDL::Optionality::Required });
        effective_overload_set.emplace(move(overloads), 0);
        break;
    }
    case 2:
        chosen_overload_callable_id = 1;
        break;
    }

    Vector<StringView> dictionary_types {
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return fill0(vm);
    case 1:
        return fill1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    auto arg0 = vm.argument(0);
    String fill_rule = "nonzero"_string;
    if (!arg0.is_undefined())
        fill_rule = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, arg0));
    }(); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "fill");

    auto arg0 = vm.argument(0);
    auto path = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::Path2D>> {
        if (auto impl = arg0.as_if<HTML::Path2D>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Path2D");
    }(); }));

    auto arg1 = vm.argument(1);
    String fill_rule = "nonzero"_string;
    if (!arg1.is_undefined())
        fill_rule = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, arg1));
    }(); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(1, vm.argument_count())) {
    case 0:
        chosen_overload_callable_id = 0;
        break;
    case 1:
        chosen_overload_callable_id = 1;
        break;
    }

    Vector<StringView> dictionary_types {
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return stroke0(vm);
    case 1:
        return stroke1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "stroke");

    auto arg0 = vm.argument(0);
    auto path = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::Path2D>> {
        if (auto impl = arg0.as_if<HTML::Path2D>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Path2D");
    }(); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::clip)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::clip");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(2, vm.argument_count())) {
    case 0:
        chosen_overload_callable_id = 0;
        break;
    case 1: {
        Vector<WebIDL::EffectiveOverloadSet::Item> overloads;
        overloads.ensure_capacity(2);
        overloads.empend(0, Vector<NonnullRefPtr<WebIDL::Type const>> { make_ref_counted<WebIDL::Type>("DOMString", false) }, Vector<WebIDL::Optionality> { WebIDL::Optionality::Optional });
        overloads.empend(1, Vector<NonnullRefPtr<WebIDL::Type const>> { make_ref_counted<WebIDL::Type>("Path2D", false) }, Vector<WebIDL::Optionality> { WebIDL::Optionality::Required });
        effective_overload_set.emplace(move(overloads), 0);
        break;
    }
    case 2:
        chosen_overload_callable_id = 1;
        break;
    }

    Vector<StringView> dictionary_types {
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return clip0(vm);
    case 1:
        return clip1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::clip0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::clip0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    auto arg0 = vm.argument(0);
    String fill_rule = "nonzero"_string;
    if (!arg0.is_undefined())
        fill_rule = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, arg0));
    }(); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::clip1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::clip1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "clip");

    auto arg0 = vm.argument(0);
    auto path = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::Path2D>> {
        if (auto impl = arg0.as_if<HTML::Path2D>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Path2D");
    }(); }));

    auto arg1 = vm.argument(1);
    String fill_rule = "nonzero"_string;
    if (!arg1.is_undefined())
        fill_rule = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, arg1));
    }(); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::is_point_in_path)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::is_point_in_path");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(4, vm.argument_count())) {
    case 2:
        chosen_overload_callable_id = 0;
        break;
    case 3: {
        Vector<WebIDL::EffectiveOverloadSet::Item> overloads;
        overloads.ensure_capacity(2);
        overloads.empend(0, Vector<NonnullRefPtr<WebIDL::Type const>> { make_ref_counted<WebIDL::Type>("unrestricted double", false), make_ref_counted<WebIDL::Type>("unrestricted double", false), make_ref_counted<WebIDL::Type>("DOMString", false) }, Vector<WebIDL::Optionality> { WebIDL::Optionality::Required, WebIDL::Optionality::Required, WebIDL::Optionality::Optional });
        overloads.empend(1, Vector<NonnullRefPtr<WebIDL::Type const>> { make_ref_counted<WebIDL::Type>("Path2D", false), make_ref_counted<WebIDL::Type>("unrestricted double", false), make_ref_counted<WebIDL::Type>("unrestricted double", false) }, Vector<WebIDL::Optionality> { WebIDL::Optionality::Required, WebIDL::Optionality::Required, WebIDL::Optionality::Required });
        effective_overload_set.emplace(move(overloads), 0);
        break;
    }
    case 4:
        chosen_overload_callable_id = 1;
        break;
    }

    Vector<StringView> dictionary_types {
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return is_point_in_path0(vm);
    case 1:
        return is_point_in_path1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::is_point_in_path0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::is_point_in_path0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "isPointInPath", "2");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    String fill_rule = "nonzero"_string;
    if (!arg2.is_undefined())
        fill_rule = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, arg2));
    }(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->is_point_in_path(x, y, fill_rule); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::is_point_in_path1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::is_point_in_path1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 3)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "isPointInPath", "3");

    auto arg0 = vm.argument(0);
    auto path = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::Path2D>> {
        if (auto impl = arg0.as_if<HTML::Path2D>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Path2D");
    }(); }));

    auto arg1 = vm.argument(1);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    String fill_rule = "nonzero"_string;
    if (!arg3.is_undefined())
        fill_rule = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<String> {
        return TRY(WebIDL::to_string(vm, arg3));
    }(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->is_point_in_path(path, x, y, fill_rule); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::fill_text)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::fill_text");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 3)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "fillText", "3");

    auto arg0 = vm.argument(0);
    auto text = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Utf16String> {
        return TRY(WebIDL::to_utf16_string(vm, arg0));
    }(); }));

    auto arg1 = vm.argument(1);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    Optional<double> max_width {};
    if (!arg3.is_undefined())
        max_width = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->fill_text(text, x, y, max_width); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::stroke_text)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::stroke_text");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 3)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "strokeText", "3");

    auto arg0 = vm.argument(0);
    auto text = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Utf16String> {
        return TRY(WebIDL::to_utf16_string(vm, arg0));
    }(); }));

    auto arg1 = vm.argument(1);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    Optional<double> max_width {};
    if (!arg3.is_undefined())
        max_width = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->stroke_text(text, x, y, max_width); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::measure_text)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::measure_text");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "measureText");

    auto arg0 = vm.argument(0);
    auto text = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Utf16String> {
        return TRY(WebIDL::to_utf16_string(vm, arg0));
    }(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->measure_text(text); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::draw_image)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::draw_image");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(9, vm.argument_count())) {
    case 3:
        chosen_overload_callable_id = 0;
        break;
    case 5:
        chosen_overload_callable_id = 1;
        break;
    case 9:
        chosen_overload_callable_id = 2;
        break;
    }

    Vector<StringView> dictionary_types {
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return draw_image0(vm);
    case 1:
        return draw_image1(vm);
    case 2:
        return draw_image2(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::draw_image0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::draw_image0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 3)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "drawImage", "3");

    auto arg0 = vm.argument(0);
    auto image = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>>> {

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

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<HTML::HTMLImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<SVG::SVGImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLVideoElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLCanvasElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::ImageBitmap>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::OffscreenCanvas>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };
            }
        }

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

    auto arg1 = vm.argument(1);
    auto dx = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto dy = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->draw_image(image, dx, dy); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::draw_image1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::draw_image1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 5)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "drawImage", "5");

    auto arg0 = vm.argument(0);
    auto image = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>>> {

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

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<HTML::HTMLImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<SVG::SVGImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLVideoElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLCanvasElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::ImageBitmap>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::OffscreenCanvas>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };
            }
        }

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

    auto arg1 = vm.argument(1);
    auto dx = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto dy = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto dw = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto dh = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->draw_image(image, dx, dy, dw, dh); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::draw_image2)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::draw_image2");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 9)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "drawImage", "9");

    auto arg0 = vm.argument(0);
    auto image = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>>> {

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

            if (is<PlatformObject>(object)) {

                if (auto* result = as_if<HTML::HTMLImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<SVG::SVGImageElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLVideoElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::HTMLCanvasElement>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::ImageBitmap>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };

                if (auto* result = as_if<HTML::OffscreenCanvas>(object))
                    return Variant<GC::Ref<HTML::HTMLImageElement>, GC::Ref<SVG::SVGImageElement>, GC::Ref<HTML::HTMLVideoElement>, GC::Ref<HTML::HTMLCanvasElement>, GC::Ref<HTML::ImageBitmap>, GC::Ref<HTML::OffscreenCanvas>> { GC::Ref { *result } };
            }
        }

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

    auto arg1 = vm.argument(1);
    auto sx = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto sy = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto sw = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto sh = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    auto arg5 = vm.argument(5);
    auto dx = TRY(throw_dom_exception_if_needed(vm, [&] { return arg5.to_double(vm); }));

    auto arg6 = vm.argument(6);
    auto dy = TRY(throw_dom_exception_if_needed(vm, [&] { return arg6.to_double(vm); }));

    auto arg7 = vm.argument(7);
    auto dw = TRY(throw_dom_exception_if_needed(vm, [&] { return arg7.to_double(vm); }));

    auto arg8 = vm.argument(8);
    auto dh = TRY(throw_dom_exception_if_needed(vm, [&] { return arg8.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->draw_image(image, sx, sy, sw, sh, dx, dy, dw, dh); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_image_data)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_image_data");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(3, vm.argument_count())) {
    case 1:
        chosen_overload_callable_id = 1;
        break;
    case 2:
        chosen_overload_callable_id = 0;
        break;
    case 3:
        chosen_overload_callable_id = 0;
        break;
    }

    Vector<StringView> dictionary_types {
        "ImageDataSettings"sv,
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return create_image_data0(vm);
    case 1:
        return create_image_data1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_image_data0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_image_data0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "createImageData", "2");

    auto arg0 = vm.argument(0);
    auto sw = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg0, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg1 = vm.argument(1);
    auto sh = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg1, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg2 = vm.argument(2);
    ImageDataSettings settings = ImageDataSettings {};
    if (!arg2.is_undefined())
        settings = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_image_data_settings(vm, arg2); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->create_image_data(sw, sh, settings); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::create_image_data1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::create_image_data1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "createImageData");

    auto arg0 = vm.argument(0);
    auto image_data = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::ImageData>> {
        if (auto impl = arg0.as_if<HTML::ImageData>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "ImageData");
    }(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->create_image_data(image_data); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::get_image_data)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::get_image_data");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "getImageData", "4");

    auto arg0 = vm.argument(0);
    auto sx = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg0, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg1 = vm.argument(1);
    auto sy = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg1, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg2 = vm.argument(2);
    auto sw = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg2, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg3 = vm.argument(3);
    auto sh = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg3, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg4 = vm.argument(4);
    ImageDataSettings settings = ImageDataSettings {};
    if (!arg4.is_undefined())
        settings = TRY(throw_dom_exception_if_needed(vm, [&] { return convert_to_idl_value_for_image_data_settings(vm, arg4); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->get_image_data(sx, sy, sw, sh, settings); }));
    return JS::Value(R);
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::put_image_data)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::put_image_data");

    Optional<int> chosen_overload_callable_id;
    Optional<WebIDL::EffectiveOverloadSet> effective_overload_set;

    switch (min(7, vm.argument_count())) {
    case 3:
        chosen_overload_callable_id = 0;
        break;
    case 7:
        chosen_overload_callable_id = 1;
        break;
    }

    Vector<StringView> dictionary_types {
    };

    if (!chosen_overload_callable_id.has_value()) {
        if (!effective_overload_set.has_value())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::OverloadResolutionFailed);
        chosen_overload_callable_id = TRY(WebIDL::resolve_overload(vm, effective_overload_set.value(), dictionary_types)).callable_id;
    }


    switch (chosen_overload_callable_id.value()) {
    case 0:
        return put_image_data0(vm);
    case 1:
        return put_image_data1(vm);
    default:
        VERIFY_NOT_REACHED();
    }
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::put_image_data0)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::put_image_data0");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 3)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "putImageData", "3");

    auto arg0 = vm.argument(0);
    auto image_data = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::ImageData>> {
        if (auto impl = arg0.as_if<HTML::ImageData>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "ImageData");
    }(); }));

    auto arg1 = vm.argument(1);
    auto dx = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg1, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg2 = vm.argument(2);
    auto dy = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg2, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->put_image_data(image_data, dx, dy); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::put_image_data1)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::put_image_data1");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 7)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "putImageData", "7");

    auto arg0 = vm.argument(0);
    auto image_data = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<GC::Ref<HTML::ImageData>> {
        if (auto impl = arg0.as_if<HTML::ImageData>())
            return *impl;
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "ImageData");
    }(); }));

    auto arg1 = vm.argument(1);
    auto dx = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg1, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg2 = vm.argument(2);
    auto dy = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg2, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg3 = vm.argument(3);
    auto dirty_x = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg3, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg4 = vm.argument(4);
    auto dirty_y = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg4, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg5 = vm.argument(5);
    auto dirty_width = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg5, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    auto arg6 = vm.argument(6);
    auto dirty_height = TRY(throw_dom_exception_if_needed(vm, [&] { return WebIDL::convert_to_int<WebIDL::Long>(vm, arg6, WebIDL::EnforceRange::Yes, WebIDL::Clamp::No); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->put_image_data(image_data, dx, dy, dirty_x, dirty_y, dirty_width, dirty_height); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::set_line_dash)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::set_line_dash");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 1)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountOne, "setLineDash");

    auto arg0 = vm.argument(0);
    auto segments = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Vector<double>> {
        if (!arg0.is_object())
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObject, arg0);

        auto method = TRY(arg0.get_method(vm, vm.well_known_symbol_iterator()));
        if (!method)
            return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotIterable, arg0);

        return TRY([&]() -> JS::ThrowCompletionOr<Vector<double>> {
        // To create an IDL value of type sequence<T> given an iterable iterable and an iterator getter method, perform the following steps:
        // 1. Let iteratorRecord be ? GetIteratorFromMethod(iterable, method).
        auto iterator = TRY(JS::get_iterator_from_method(vm, arg0, *method));

        Vector<double> sequence;

        // 2. Initialize i to be 0.
        // 3. Repeat
        for (;;) {
            // 1. Let next be ? IteratorStepValue(iteratorRecord).
            auto next = TRY(JS::iterator_step_value(vm, iterator));

            // 2. If next is done, then return an IDL sequence value of type sequence<T> of length i, where the value of the element at index j is Sj.
            if (!next.has_value())
                break;

            // 3. Initialize Si to the result of converting next to an IDL value of type T.
            auto next_value = next.release_value();
            auto sequence_item = TRY(throw_dom_exception_if_needed(vm, [&] { return next_value.to_double(vm); }));

            // 4. Set i to i + 1.
            sequence.append(sequence_item);
        }

        return sequence;
    }());
    }(); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::get_line_dash)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::get_line_dash");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->get_line_dash(); }));
    return [&]() -> JS::Value {
        // An IDL sequence<T> value S is converted to a JavaScript value as follows:
        // 1. Let n be the length of S.
        auto sequence_length = R.size();

        // 2. Let A be a new Array object created as if by the expression [].
        auto sequence_array = MUST(JS::Array::create(realm, sequence_length));

        // 3. Initialize i to be 0.
        // 4. While i < n:
        for (size_t sequence_index = 0; sequence_index < sequence_length; ++sequence_index) {
            // 1. Let V be the value in S at index i.
            auto& sequence_element = R.at(sequence_index);

            // 2. Let E be the result of converting V to a JavaScript value.
            JS::Value js_sequence_element = JS::Value(sequence_element);

            // 3. Let P be the result of calling ! ToString(i).
            // 4. Perform ! CreateDataPropertyOrThrow(A, P, E).
            MUST(sequence_array->create_data_property(JS::PropertyKey { sequence_index }, js_sequence_element));

            // 5. Set i to i + 1.
        }

        // 5. Return A.
        return sequence_array;
    }();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::close_path)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::close_path");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::move_to)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::move_to");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "moveTo", "2");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::line_to)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::line_to");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 2)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "lineTo", "2");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

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

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::quadratic_curve_to)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::quadratic_curve_to");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "quadraticCurveTo", "4");

    auto arg0 = vm.argument(0);
    auto cpx = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto cpy = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->quadratic_curve_to(cpx, cpy, x, y); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::bezier_curve_to)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::bezier_curve_to");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 6)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "bezierCurveTo", "6");

    auto arg0 = vm.argument(0);
    auto cp1x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto cp1y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto cp2x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto cp2y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    auto arg5 = vm.argument(5);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg5.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->bezier_curve_to(cp1x, cp1y, cp2x, cp2y, x, y); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::arc_to)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::arc_to");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 5)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "arcTo", "5");

    auto arg0 = vm.argument(0);
    auto x1 = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y1 = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto x2 = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto y2 = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto radius = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->arc_to(x1, y1, x2, y2, radius); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::rect)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::rect");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "rect", "4");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto w = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto h = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->rect(x, y, w, h); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::round_rect)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::round_rect");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 4)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "roundRect", "4");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto w = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto h = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> radii = Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> { 0 };
    if (!arg4.is_undefined())
        radii = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>>> {

        if (arg4.is_nullish()) {
            return Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> { TRY(convert_to_idl_value_for_dom_point_init(vm, arg4)) };
        }

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

            // 1. Let method be ? GetMethod(V, @@iterator).
            auto method = TRY(arg4.get_method(vm, vm.well_known_symbol_iterator()));

            // 2. If method is not undefined, return the result of creating a sequence of that type from V and method.
            if (method) {
                auto sequence_union_type = TRY([&]() -> JS::ThrowCompletionOr<Vector<Variant<double, DOMPointInit>>> {
        // To create an IDL value of type sequence<T> given an iterable iterable and an iterator getter method, perform the following steps:
        // 1. Let iteratorRecord be ? GetIteratorFromMethod(iterable, method).
        auto iterator = TRY(JS::get_iterator_from_method(vm, arg4, *method));

        Vector<Variant<double, DOMPointInit>> sequence;

        // 2. Initialize i to be 0.
        // 3. Repeat
        for (;;) {
            // 1. Let next be ? IteratorStepValue(iteratorRecord).
            auto next = TRY(JS::iterator_step_value(vm, iterator));

            // 2. If next is done, then return an IDL sequence value of type sequence<T> of length i, where the value of the element at index j is Sj.
            if (!next.has_value())
                break;

            // 3. Initialize Si to the result of converting next to an IDL value of type T.
            auto next_value = next.release_value();
            auto sequence_item = TRY(throw_dom_exception_if_needed(vm, [&] { return [&]() -> JS::ThrowCompletionOr<Variant<double, DOMPointInit>> {

        if (next_value.is_nullish()) {
            return Variant<double, DOMPointInit> { TRY(convert_to_idl_value_for_dom_point_init(vm, next_value)) };
        }

        if (next_value.is_object()) {
            [[maybe_unused]] auto& object = next_value.as_object();
            return Variant<double, DOMPointInit> { TRY(convert_to_idl_value_for_dom_point_init(vm, next_value)) };
        }

        if (next_value.is_number()) {
            auto radii_number = TRY(next_value.to_double(vm));
            return Variant<double, DOMPointInit> { radii_number };
        }

        auto radii_number_fallback = TRY(next_value.to_double(vm));
        return Variant<double, DOMPointInit> { radii_number_fallback };

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

            // 4. Set i to i + 1.
            sequence.append(sequence_item);
        }

        return sequence;
    }());
                return Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> { sequence_union_type };
            }

            return Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> { TRY(convert_to_idl_value_for_dom_point_init(vm, arg4)) };
        }

        if (arg4.is_number()) {
            auto radii_number = TRY(arg4.to_double(vm));
            return Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> { radii_number };
        }

        auto radii_number_fallback = TRY(arg4.to_double(vm));
        return Variant<double, DOMPointInit, Vector<Variant<double, DOMPointInit>>> { radii_number_fallback };

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

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->round_rect(x, y, w, h, radii); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::arc)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::arc");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 5)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "arc", "5");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto radius = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto start_angle = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto end_angle = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    auto arg5 = vm.argument(5);
    bool counterclockwise = false;
    if (!arg5.is_undefined())
        counterclockwise = TRY(throw_dom_exception_if_needed(vm, [&] { return arg5.to_boolean(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->arc(x, y, radius, start_angle, end_angle, counterclockwise); }));
    return JS::js_undefined();
}

JS_DEFINE_NATIVE_FUNCTION(CanvasRenderingContext2DPrototype::ellipse)
{
    WebIDL::log_trace(vm, "CanvasRenderingContext2DPrototype::ellipse");
    [[maybe_unused]] auto& realm = *vm.current_realm();
    [[maybe_unused]] HTML::CanvasRenderingContext2D* idl_object = TRY(impl_from(vm));

    if (vm.argument_count() < 7)
        return vm.throw_completion<JS::TypeError>(JS::ErrorType::BadArgCountMany, "ellipse", "7");

    auto arg0 = vm.argument(0);
    auto x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg0.to_double(vm); }));

    auto arg1 = vm.argument(1);
    auto y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg1.to_double(vm); }));

    auto arg2 = vm.argument(2);
    auto radius_x = TRY(throw_dom_exception_if_needed(vm, [&] { return arg2.to_double(vm); }));

    auto arg3 = vm.argument(3);
    auto radius_y = TRY(throw_dom_exception_if_needed(vm, [&] { return arg3.to_double(vm); }));

    auto arg4 = vm.argument(4);
    auto rotation = TRY(throw_dom_exception_if_needed(vm, [&] { return arg4.to_double(vm); }));

    auto arg5 = vm.argument(5);
    auto start_angle = TRY(throw_dom_exception_if_needed(vm, [&] { return arg5.to_double(vm); }));

    auto arg6 = vm.argument(6);
    auto end_angle = TRY(throw_dom_exception_if_needed(vm, [&] { return arg6.to_double(vm); }));

    auto arg7 = vm.argument(7);
    bool counterclockwise = false;
    if (!arg7.is_undefined())
        counterclockwise = TRY(throw_dom_exception_if_needed(vm, [&] { return arg7.to_boolean(); }));

    [[maybe_unused]] auto R = TRY(throw_dom_exception_if_needed(vm, [&] { return idl_object->ellipse(x, y, radius_x, radius_y, rotation, start_angle, end_angle, counterclockwise); }));
    return JS::js_undefined();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<ImageSmoothingQuality> convert_to_idl_value_for_image_smoothing_quality(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 == "low"sv)
        return ImageSmoothingQuality::Low;
    if (value_as_string == "medium"sv)
        return ImageSmoothingQuality::Medium;
    if (value_as_string == "high"sv)
        return ImageSmoothingQuality::High;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "ImageSmoothingQuality");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(ImageSmoothingQuality 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 ImageSmoothingQuality::Low:
        return "low"_utf16;
    case ImageSmoothingQuality::Medium:
        return "medium"_utf16;
    case ImageSmoothingQuality::High:
        return "high"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<CanvasLineCap> convert_to_idl_value_for_canvas_line_cap(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 == "butt"sv)
        return CanvasLineCap::Butt;
    if (value_as_string == "round"sv)
        return CanvasLineCap::Round;
    if (value_as_string == "square"sv)
        return CanvasLineCap::Square;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "CanvasLineCap");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(CanvasLineCap 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 CanvasLineCap::Butt:
        return "butt"_utf16;
    case CanvasLineCap::Round:
        return "round"_utf16;
    case CanvasLineCap::Square:
        return "square"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<CanvasLineJoin> convert_to_idl_value_for_canvas_line_join(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 == "round"sv)
        return CanvasLineJoin::Round;
    if (value_as_string == "bevel"sv)
        return CanvasLineJoin::Bevel;
    if (value_as_string == "miter"sv)
        return CanvasLineJoin::Miter;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "CanvasLineJoin");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(CanvasLineJoin 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 CanvasLineJoin::Round:
        return "round"_utf16;
    case CanvasLineJoin::Bevel:
        return "bevel"_utf16;
    case CanvasLineJoin::Miter:
        return "miter"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<CanvasTextAlign> convert_to_idl_value_for_canvas_text_align(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 == "start"sv)
        return CanvasTextAlign::Start;
    if (value_as_string == "end"sv)
        return CanvasTextAlign::End;
    if (value_as_string == "left"sv)
        return CanvasTextAlign::Left;
    if (value_as_string == "right"sv)
        return CanvasTextAlign::Right;
    if (value_as_string == "center"sv)
        return CanvasTextAlign::Center;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "CanvasTextAlign");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(CanvasTextAlign 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 CanvasTextAlign::Start:
        return "start"_utf16;
    case CanvasTextAlign::End:
        return "end"_utf16;
    case CanvasTextAlign::Left:
        return "left"_utf16;
    case CanvasTextAlign::Right:
        return "right"_utf16;
    case CanvasTextAlign::Center:
        return "center"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<CanvasTextBaseline> convert_to_idl_value_for_canvas_text_baseline(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 == "top"sv)
        return CanvasTextBaseline::Top;
    if (value_as_string == "hanging"sv)
        return CanvasTextBaseline::Hanging;
    if (value_as_string == "middle"sv)
        return CanvasTextBaseline::Middle;
    if (value_as_string == "alphabetic"sv)
        return CanvasTextBaseline::Alphabetic;
    if (value_as_string == "ideographic"sv)
        return CanvasTextBaseline::Ideographic;
    if (value_as_string == "bottom"sv)
        return CanvasTextBaseline::Bottom;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "CanvasTextBaseline");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(CanvasTextBaseline 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 CanvasTextBaseline::Top:
        return "top"_utf16;
    case CanvasTextBaseline::Hanging:
        return "hanging"_utf16;
    case CanvasTextBaseline::Middle:
        return "middle"_utf16;
    case CanvasTextBaseline::Alphabetic:
        return "alphabetic"_utf16;
    case CanvasTextBaseline::Ideographic:
        return "ideographic"_utf16;
    case CanvasTextBaseline::Bottom:
        return "bottom"_utf16;
    }
    VERIFY_NOT_REACHED();
}

// https://webidl.spec.whatwg.org/#idl-enumeration
JS::ThrowCompletionOr<CanvasDirection> convert_to_idl_value_for_canvas_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 == "ltr"sv)
        return CanvasDirection::Ltr;
    if (value_as_string == "rtl"sv)
        return CanvasDirection::Rtl;
    if (value_as_string == "inherit"sv)
        return CanvasDirection::Inherit;
    return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidEnumerationValue, value_as_string, "CanvasDirection");
}

// https://webidl.spec.whatwg.org/#idl-enumeration
Utf16String idl_enum_to_string(CanvasDirection 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 CanvasDirection::Ltr:
        return "ltr"_utf16;
    case CanvasDirection::Rtl:
        return "rtl"_utf16;
    case CanvasDirection::Inherit:
        return "inherit"_utf16;
    }
    VERIFY_NOT_REACHED();
}

} // namespace Web::Bindings
