#include <AK/Assertions.h>
#include <AK/Vector.h>
#include <Compositor/WebGLCommandReplayer.h>

namespace Compositor {

using namespace Web::WebGL;

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ActiveTexture const& command, ReadonlyBytes)
{
    gl.active_texture(command.texture);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::AttachShader const& command, ReadonlyBytes)
{
    auto program = objects.lookup(command.program);
    auto shader = objects.lookup(command.shader);
    gl.attach_shader(program, shader);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BeginQuery const& command, ReadonlyBytes)
{
    auto id = objects.lookup(command.id);
    gl.begin_query(command.target, id);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BeginTransformFeedback const& command, ReadonlyBytes)
{
    gl.begin_transform_feedback(command.primitive_mode);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindAttribLocation const& command, ReadonlyBytes payload)
{
    auto program = objects.lookup(command.program);
    auto name_bytes = WebGLCommandList::resolve_string_span(payload, command.name);
    gl.bind_attrib_location(program, command.index, reinterpret_cast<GLchar const*>(name_bytes.data()));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindBuffer const& command, ReadonlyBytes)
{
    auto buffer = objects.lookup(command.buffer);
    gl.bind_buffer(command.target, buffer);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindBufferBase const& command, ReadonlyBytes)
{
    auto buffer = objects.lookup(command.buffer);
    gl.bind_buffer_base(command.target, command.index, buffer);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindBufferRange const& command, ReadonlyBytes)
{
    auto buffer = objects.lookup(command.buffer);
    gl.bind_buffer_range(command.target, command.index, buffer, command.offset, command.size);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindFramebuffer const& command, ReadonlyBytes)
{
    GLuint framebuffer = command.framebuffer ? objects.lookup(command.framebuffer) : gl.default_framebuffer();
    gl.bind_framebuffer(command.target, framebuffer);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindRenderbuffer const& command, ReadonlyBytes)
{
    GLuint renderbuffer = command.renderbuffer ? objects.lookup(command.renderbuffer) : gl.default_renderbuffer();
    gl.bind_renderbuffer(command.target, renderbuffer);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindSampler const& command, ReadonlyBytes)
{
    auto sampler = objects.lookup(command.sampler);
    gl.bind_sampler(command.unit, sampler);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindTexture const& command, ReadonlyBytes)
{
    auto texture = objects.lookup(command.texture);
    gl.bind_texture(command.target, texture);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindTransformFeedback const& command, ReadonlyBytes)
{
    auto id = objects.lookup(command.id);
    gl.bind_transform_feedback(command.target, id);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindVertexArray const& command, ReadonlyBytes)
{
    auto array = objects.lookup(command.array);
    gl.bind_vertex_array(array);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::BindVertexArrayOES const& command, ReadonlyBytes)
{
    auto array = objects.lookup(command.array);
    gl.bind_vertex_array_oes(array);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BlendColor const& command, ReadonlyBytes)
{
    gl.blend_color(command.red, command.green, command.blue, command.alpha);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BlendEquation const& command, ReadonlyBytes)
{
    gl.blend_equation(command.mode);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BlendEquationSeparate const& command, ReadonlyBytes)
{
    gl.blend_equation_separate(command.mode_rgb, command.mode_alpha);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BlendFunc const& command, ReadonlyBytes)
{
    gl.blend_func(command.sfactor, command.dfactor);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BlendFuncSeparate const& command, ReadonlyBytes)
{
    gl.blend_func_separate(command.sfactor_rgb, command.dfactor_rgb, command.sfactor_alpha, command.dfactor_alpha);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BlitFramebuffer const& command, ReadonlyBytes)
{
    gl.blit_framebuffer(command.src_x0, command.src_y0, command.src_x1, command.src_y1, command.dst_x0, command.dst_y0, command.dst_x1, command.dst_y1, command.mask, command.filter);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BufferData const& command, ReadonlyBytes payload)
{
    ReadonlyBytes data_bytes;
    if (command.has_data) {
        if (command.data.size != 0)
            data_bytes = WebGLCommandList::resolve_data_span(payload, command.data);
        VERIFY(!(static_cast<i64>(data_bytes.size()) != static_cast<i64>(static_cast<i64>(command.size))));
    } else {
        VERIFY(command.data.size == 0);
    }
    gl.buffer_data(command.target, command.size, command.has_data ? data_bytes.data() : nullptr, command.usage);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::BufferSubData const& command, ReadonlyBytes payload)
{
    auto data_bytes = WebGLCommandList::resolve_data_span(payload, command.data);
    VERIFY(!(static_cast<i64>(data_bytes.size()) != static_cast<i64>(static_cast<i64>(command.size))));
    gl.buffer_sub_data(command.target, command.offset, command.size, data_bytes.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Clear const& command, ReadonlyBytes)
{
    gl.clear(command.mask);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearBufferfi const& command, ReadonlyBytes)
{
    gl.clear_bufferfi(command.buffer, command.drawbuffer, command.depth, command.stencil);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearBufferfv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>((static_cast<i64>(command.buffer) == GL_COLOR ? 4 : 1) * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.clear_bufferfv(command.buffer, command.drawbuffer, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearBufferiv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>((static_cast<i64>(command.buffer) == GL_COLOR ? 4 : 1) * sizeof(GLint))));
    auto value = WebGLCommandList::resolve_typed_span<GLint>(payload, command.value);
    gl.clear_bufferiv(command.buffer, command.drawbuffer, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearBufferuiv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>((static_cast<i64>(command.buffer) == GL_COLOR ? 4 : 1) * sizeof(GLuint))));
    auto value = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.value);
    gl.clear_bufferuiv(command.buffer, command.drawbuffer, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearColor const& command, ReadonlyBytes)
{
    gl.clear_color(command.red, command.green, command.blue, command.alpha);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearDepthf const& command, ReadonlyBytes)
{
    gl.clear_depthf(command.d);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ClearStencil const& command, ReadonlyBytes)
{
    gl.clear_stencil(command.s);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ColorMask const& command, ReadonlyBytes)
{
    gl.color_mask(command.red, command.green, command.blue, command.alpha);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::CompileShader const& command, ReadonlyBytes)
{
    auto shader = objects.lookup(command.shader);
    gl.compile_shader(shader);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CompressedTexImage2DRobustANGLE const& command, ReadonlyBytes payload)
{
    auto data_bytes = WebGLCommandList::resolve_data_span(payload, command.data);
    VERIFY(!(static_cast<i64>(data_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    gl.compressed_tex_image2d_robust_angle(command.target, command.level, command.internalformat, command.width, command.height, command.border, command.image_size, command.buf_size, data_bytes.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CompressedTexImage3DRobustANGLE const& command, ReadonlyBytes payload)
{
    auto data_bytes = WebGLCommandList::resolve_data_span(payload, command.data);
    VERIFY(!(static_cast<i64>(data_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    gl.compressed_tex_image3d_robust_angle(command.target, command.level, command.internalformat, command.width, command.height, command.depth, command.border, command.image_size, command.buf_size, data_bytes.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CompressedTexSubImage2DRobustANGLE const& command, ReadonlyBytes payload)
{
    auto data_bytes = WebGLCommandList::resolve_data_span(payload, command.data);
    VERIFY(!(static_cast<i64>(data_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    gl.compressed_tex_sub_image2d_robust_angle(command.target, command.level, command.xoffset, command.yoffset, command.width, command.height, command.format, command.image_size, command.buf_size, data_bytes.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CompressedTexSubImage3DRobustANGLE const& command, ReadonlyBytes payload)
{
    auto data_bytes = WebGLCommandList::resolve_data_span(payload, command.data);
    VERIFY(!(static_cast<i64>(data_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    gl.compressed_tex_sub_image3d_robust_angle(command.target, command.level, command.xoffset, command.yoffset, command.zoffset, command.width, command.height, command.depth, command.format, command.image_size, command.buf_size, data_bytes.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CopyBufferSubData const& command, ReadonlyBytes)
{
    gl.copy_buffer_sub_data(command.read_target, command.write_target, command.read_offset, command.write_offset, command.size);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CopyTexImage2D const& command, ReadonlyBytes)
{
    gl.copy_tex_image2d(command.target, command.level, command.internalformat, command.x, command.y, command.width, command.height, command.border);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CopyTexSubImage2D const& command, ReadonlyBytes)
{
    gl.copy_tex_sub_image2d(command.target, command.level, command.xoffset, command.yoffset, command.x, command.y, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::CreateProgram const& command, ReadonlyBytes)
{
    TRY(objects.add(command.id, gl.create_program()));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::CreateShader const& command, ReadonlyBytes)
{
    TRY(objects.add(command.id, gl.create_shader(command.type)));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::CullFace const& command, ReadonlyBytes)
{
    gl.cull_face(command.mode);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteBuffers const& command, ReadonlyBytes payload)
{
    auto buffers_bytes = WebGLCommandList::resolve_data_span(payload, command.buffers);
    VERIFY(!(static_cast<i64>(buffers_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto buffers = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.buffers);
    Vector<GLuint> buffers_names;
    buffers_names.ensure_capacity(buffers.size());
    for (auto id : buffers)
        buffers_names.unchecked_append(objects.take(id));
    gl.delete_buffers(command.n, buffers_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteFramebuffers const& command, ReadonlyBytes payload)
{
    auto framebuffers_bytes = WebGLCommandList::resolve_data_span(payload, command.framebuffers);
    VERIFY(!(static_cast<i64>(framebuffers_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto framebuffers = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.framebuffers);
    Vector<GLuint> framebuffers_names;
    framebuffers_names.ensure_capacity(framebuffers.size());
    for (auto id : framebuffers)
        framebuffers_names.unchecked_append(objects.take(id));
    gl.delete_framebuffers(command.n, framebuffers_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteProgram const& command, ReadonlyBytes)
{
    auto program = objects.take(command.program);
    gl.delete_program(program);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteQueries const& command, ReadonlyBytes payload)
{
    auto ids_bytes = WebGLCommandList::resolve_data_span(payload, command.ids);
    VERIFY(!(static_cast<i64>(ids_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto ids = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.ids);
    Vector<GLuint> ids_names;
    ids_names.ensure_capacity(ids.size());
    for (auto id : ids)
        ids_names.unchecked_append(objects.take(id));
    gl.delete_queries(command.n, ids_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteRenderbuffers const& command, ReadonlyBytes payload)
{
    auto renderbuffers_bytes = WebGLCommandList::resolve_data_span(payload, command.renderbuffers);
    VERIFY(!(static_cast<i64>(renderbuffers_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto renderbuffers = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.renderbuffers);
    Vector<GLuint> renderbuffers_names;
    renderbuffers_names.ensure_capacity(renderbuffers.size());
    for (auto id : renderbuffers)
        renderbuffers_names.unchecked_append(objects.take(id));
    gl.delete_renderbuffers(command.n, renderbuffers_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteSamplers const& command, ReadonlyBytes payload)
{
    auto samplers_bytes = WebGLCommandList::resolve_data_span(payload, command.samplers);
    VERIFY(!(static_cast<i64>(samplers_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * sizeof(GLuint))));
    auto samplers = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.samplers);
    Vector<GLuint> samplers_names;
    samplers_names.ensure_capacity(samplers.size());
    for (auto id : samplers)
        samplers_names.unchecked_append(objects.take(id));
    gl.delete_samplers(command.count, samplers_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteShader const& command, ReadonlyBytes)
{
    auto shader = objects.take(command.shader);
    gl.delete_shader(shader);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteSync const& command, ReadonlyBytes)
{
    auto sync = objects.take_sync(command.sync);
    gl.delete_sync(sync);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteTextures const& command, ReadonlyBytes payload)
{
    auto textures_bytes = WebGLCommandList::resolve_data_span(payload, command.textures);
    VERIFY(!(static_cast<i64>(textures_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto textures = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.textures);
    Vector<GLuint> textures_names;
    textures_names.ensure_capacity(textures.size());
    for (auto id : textures)
        textures_names.unchecked_append(objects.take(id));
    gl.delete_textures(command.n, textures_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteTransformFeedbacks const& command, ReadonlyBytes payload)
{
    auto ids_bytes = WebGLCommandList::resolve_data_span(payload, command.ids);
    VERIFY(!(static_cast<i64>(ids_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto ids = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.ids);
    Vector<GLuint> ids_names;
    ids_names.ensure_capacity(ids.size());
    for (auto id : ids)
        ids_names.unchecked_append(objects.take(id));
    gl.delete_transform_feedbacks(command.n, ids_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteVertexArrays const& command, ReadonlyBytes payload)
{
    auto arrays_bytes = WebGLCommandList::resolve_data_span(payload, command.arrays);
    VERIFY(!(static_cast<i64>(arrays_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto arrays = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.arrays);
    Vector<GLuint> arrays_names;
    arrays_names.ensure_capacity(arrays.size());
    for (auto id : arrays)
        arrays_names.unchecked_append(objects.take(id));
    gl.delete_vertex_arrays(command.n, arrays_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DeleteVertexArraysOES const& command, ReadonlyBytes payload)
{
    auto arrays_bytes = WebGLCommandList::resolve_data_span(payload, command.arrays);
    VERIFY(!(static_cast<i64>(arrays_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLuint))));
    auto arrays = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.arrays);
    Vector<GLuint> arrays_names;
    arrays_names.ensure_capacity(arrays.size());
    for (auto id : arrays)
        arrays_names.unchecked_append(objects.take(id));
    gl.delete_vertex_arrays_oes(command.n, arrays_names.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DepthFunc const& command, ReadonlyBytes)
{
    gl.depth_func(command.func);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DepthMask const& command, ReadonlyBytes)
{
    gl.depth_mask(command.flag);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DepthRangef const& command, ReadonlyBytes)
{
    gl.depth_rangef(command.n, command.f);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::DetachShader const& command, ReadonlyBytes)
{
    auto program = objects.lookup(command.program);
    auto shader = objects.lookup(command.shader);
    gl.detach_shader(program, shader);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Disable const& command, ReadonlyBytes)
{
    gl.disable(command.cap);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DisableVertexAttribArray const& command, ReadonlyBytes)
{
    gl.disable_vertex_attrib_array(command.index);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawArrays const& command, ReadonlyBytes)
{
    gl.draw_arrays(command.mode, command.first, command.count);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawArraysInstanced const& command, ReadonlyBytes)
{
    gl.draw_arrays_instanced(command.mode, command.first, command.count, command.instancecount);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawArraysInstancedANGLE const& command, ReadonlyBytes)
{
    gl.draw_arrays_instanced_angle(command.mode, command.first, command.count, command.primcount);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawBuffers const& command, ReadonlyBytes payload)
{
    auto bufs_bytes = WebGLCommandList::resolve_data_span(payload, command.bufs);
    VERIFY(!(static_cast<i64>(bufs_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLenum))));
    auto bufs = WebGLCommandList::resolve_typed_span<GLenum>(payload, command.bufs);
    gl.draw_buffers(command.n, bufs.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawBuffersEXT const& command, ReadonlyBytes payload)
{
    auto bufs_bytes = WebGLCommandList::resolve_data_span(payload, command.bufs);
    VERIFY(!(static_cast<i64>(bufs_bytes.size()) != static_cast<i64>(static_cast<i64>(command.n) * sizeof(GLenum))));
    auto bufs = WebGLCommandList::resolve_typed_span<GLenum>(payload, command.bufs);
    gl.draw_buffers_ext(command.n, bufs.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawElements const& command, ReadonlyBytes)
{
    gl.draw_elements(command.mode, command.count, command.type, reinterpret_cast<void const*>(static_cast<uintptr_t>(command.indices)));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawElementsInstanced const& command, ReadonlyBytes)
{
    gl.draw_elements_instanced(command.mode, command.count, command.type, reinterpret_cast<void const*>(static_cast<uintptr_t>(command.indices)), command.instancecount);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawElementsInstancedANGLE const& command, ReadonlyBytes)
{
    gl.draw_elements_instanced_angle(command.mode, command.count, command.type, reinterpret_cast<void const*>(static_cast<uintptr_t>(command.indices)), command.primcount);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::DrawRangeElements const& command, ReadonlyBytes)
{
    gl.draw_range_elements(command.mode, command.start, command.end, command.count, command.type, reinterpret_cast<void const*>(static_cast<uintptr_t>(command.indices)));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Enable const& command, ReadonlyBytes)
{
    gl.enable(command.cap);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::EnableVertexAttribArray const& command, ReadonlyBytes)
{
    gl.enable_vertex_attrib_array(command.index);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::EndQuery const& command, ReadonlyBytes)
{
    gl.end_query(command.target);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::EndTransformFeedback const&, ReadonlyBytes)
{
    gl.end_transform_feedback();
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::FenceSync const& command, ReadonlyBytes)
{
    TRY(objects.add_sync(command.id, gl.fence_sync(command.condition, command.flags)));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Flush const&, ReadonlyBytes)
{
    gl.flush();
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::FramebufferRenderbuffer const& command, ReadonlyBytes)
{
    auto renderbuffer = objects.lookup(command.renderbuffer);
    gl.framebuffer_renderbuffer(command.target, command.attachment, command.renderbuffertarget, renderbuffer);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::FramebufferTexture2D const& command, ReadonlyBytes)
{
    auto texture = objects.lookup(command.texture);
    gl.framebuffer_texture2d(command.target, command.attachment, command.textarget, texture, command.level);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::FramebufferTextureLayer const& command, ReadonlyBytes)
{
    auto texture = objects.lookup(command.texture);
    gl.framebuffer_texture_layer(command.target, command.attachment, texture, command.level, command.layer);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::FrontFace const& command, ReadonlyBytes)
{
    gl.front_face(command.mode);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenBuffers const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.buffers);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_buffers(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenFramebuffers const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.framebuffers);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_framebuffers(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenQueries const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.ids);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_queries(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenRenderbuffers const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.renderbuffers);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_renderbuffers(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenSamplers const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.samplers);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.count));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_samplers(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenTextures const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.textures);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_textures(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenTransformFeedbacks const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.ids);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_transform_feedbacks(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenVertexArrays const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.arrays);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_vertex_arrays(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::GenVertexArraysOES const& command, ReadonlyBytes payload)
{
    auto ids = WebGLCommandList::resolve_typed_span<WebGLObjectId>(payload, command.arrays);
    VERIFY(static_cast<i64>(ids.size()) == static_cast<i64>(command.n));
    for (auto id : ids) {
        GLuint name = 0;
        gl.gen_vertex_arrays_oes(1, &name);
        TRY(objects.add(id, name));
    }
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::GenerateMipmap const& command, ReadonlyBytes)
{
    gl.generate_mipmap(command.target);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Hint const& command, ReadonlyBytes)
{
    gl.hint(command.target, command.mode);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::InvalidateFramebuffer const& command, ReadonlyBytes payload)
{
    auto attachments_bytes = WebGLCommandList::resolve_data_span(payload, command.attachments);
    VERIFY(!(static_cast<i64>(attachments_bytes.size()) != static_cast<i64>(static_cast<i64>(command.num_attachments) * sizeof(GLenum))));
    auto attachments = WebGLCommandList::resolve_typed_span<GLenum>(payload, command.attachments);
    gl.invalidate_framebuffer(command.target, command.num_attachments, attachments.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::InvalidateSubFramebuffer const& command, ReadonlyBytes payload)
{
    auto attachments_bytes = WebGLCommandList::resolve_data_span(payload, command.attachments);
    VERIFY(!(static_cast<i64>(attachments_bytes.size()) != static_cast<i64>(static_cast<i64>(command.num_attachments) * sizeof(GLenum))));
    auto attachments = WebGLCommandList::resolve_typed_span<GLenum>(payload, command.attachments);
    gl.invalidate_sub_framebuffer(command.target, command.num_attachments, attachments.data(), command.x, command.y, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::LineWidth const& command, ReadonlyBytes)
{
    gl.line_width(command.width);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::LinkProgram const& command, ReadonlyBytes)
{
    auto program = objects.lookup(command.program);
    gl.link_program(program);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::PauseTransformFeedback const&, ReadonlyBytes)
{
    gl.pause_transform_feedback();
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::PixelStorei const& command, ReadonlyBytes)
{
    gl.pixel_storei(command.pname, command.param);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::PolygonOffset const& command, ReadonlyBytes)
{
    gl.polygon_offset(command.factor, command.units);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ReadBuffer const& command, ReadonlyBytes)
{
    gl.read_buffer(command.src);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::RenderbufferStorage const& command, ReadonlyBytes)
{
    gl.renderbuffer_storage(command.target, command.internalformat, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::RenderbufferStorageMultisample const& command, ReadonlyBytes)
{
    gl.renderbuffer_storage_multisample(command.target, command.samples, command.internalformat, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::RequestExtensionANGLE const& command, ReadonlyBytes payload)
{
    auto name_bytes = WebGLCommandList::resolve_string_span(payload, command.name);
    gl.request_extension_angle(reinterpret_cast<GLchar const*>(name_bytes.data()));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::ResumeTransformFeedback const&, ReadonlyBytes)
{
    gl.resume_transform_feedback();
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::SampleCoverage const& command, ReadonlyBytes)
{
    gl.sample_coverage(command.value, command.invert);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::SamplerParameterf const& command, ReadonlyBytes)
{
    auto sampler = objects.lookup(command.sampler);
    gl.sampler_parameterf(sampler, command.pname, command.param);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::SamplerParameteri const& command, ReadonlyBytes)
{
    auto sampler = objects.lookup(command.sampler);
    gl.sampler_parameteri(sampler, command.pname, command.param);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Scissor const& command, ReadonlyBytes)
{
    gl.scissor(command.x, command.y, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::StencilFunc const& command, ReadonlyBytes)
{
    gl.stencil_func(command.func, command.ref, command.mask);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::StencilFuncSeparate const& command, ReadonlyBytes)
{
    gl.stencil_func_separate(command.face, command.func, command.ref, command.mask);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::StencilMask const& command, ReadonlyBytes)
{
    gl.stencil_mask(command.mask);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::StencilMaskSeparate const& command, ReadonlyBytes)
{
    gl.stencil_mask_separate(command.face, command.mask);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::StencilOp const& command, ReadonlyBytes)
{
    gl.stencil_op(command.fail, command.zfail, command.zpass);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::StencilOpSeparate const& command, ReadonlyBytes)
{
    gl.stencil_op_separate(command.face, command.sfail, command.dpfail, command.dppass);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexImage2DRobustANGLE const& command, ReadonlyBytes payload)
{
    ReadonlyBytes pixels_bytes;
    if (command.has_pixels) {
        if (command.pixels.size != 0)
            pixels_bytes = WebGLCommandList::resolve_data_span(payload, command.pixels);
        VERIFY(!(static_cast<i64>(pixels_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    } else {
        VERIFY(command.pixels.size == 0);
    }
    gl.tex_image2d_robust_angle(command.target, command.level, command.internalformat, command.width, command.height, command.border, command.format, command.type, command.buf_size, command.has_pixels ? pixels_bytes.data() : nullptr);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexImage3DRobustANGLE const& command, ReadonlyBytes payload)
{
    ReadonlyBytes pixels_bytes;
    if (command.has_pixels) {
        if (command.pixels.size != 0)
            pixels_bytes = WebGLCommandList::resolve_data_span(payload, command.pixels);
        VERIFY(!(static_cast<i64>(pixels_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    } else {
        VERIFY(command.pixels.size == 0);
    }
    gl.tex_image3d_robust_angle(command.target, command.level, command.internalformat, command.width, command.height, command.depth, command.border, command.format, command.type, command.buf_size, command.has_pixels ? pixels_bytes.data() : nullptr);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexParameterf const& command, ReadonlyBytes)
{
    gl.tex_parameterf(command.target, command.pname, command.param);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexParameteri const& command, ReadonlyBytes)
{
    gl.tex_parameteri(command.target, command.pname, command.param);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexStorage2D const& command, ReadonlyBytes)
{
    gl.tex_storage2d(command.target, command.levels, command.internalformat, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexStorage3D const& command, ReadonlyBytes)
{
    gl.tex_storage3d(command.target, command.levels, command.internalformat, command.width, command.height, command.depth);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexSubImage2DRobustANGLE const& command, ReadonlyBytes payload)
{
    ReadonlyBytes pixels_bytes;
    if (command.has_pixels) {
        if (command.pixels.size != 0)
            pixels_bytes = WebGLCommandList::resolve_data_span(payload, command.pixels);
        VERIFY(!(static_cast<i64>(pixels_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    } else {
        VERIFY(command.pixels.size == 0);
    }
    gl.tex_sub_image2d_robust_angle(command.target, command.level, command.xoffset, command.yoffset, command.width, command.height, command.format, command.type, command.buf_size, command.has_pixels ? pixels_bytes.data() : nullptr);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::TexSubImage3DRobustANGLE const& command, ReadonlyBytes payload)
{
    ReadonlyBytes pixels_bytes;
    if (command.has_pixels) {
        if (command.pixels.size != 0)
            pixels_bytes = WebGLCommandList::resolve_data_span(payload, command.pixels);
        VERIFY(!(static_cast<i64>(pixels_bytes.size()) != static_cast<i64>(static_cast<i64>(command.buf_size))));
    } else {
        VERIFY(command.pixels.size == 0);
    }
    gl.tex_sub_image3d_robust_angle(command.target, command.level, command.xoffset, command.yoffset, command.zoffset, command.width, command.height, command.depth, command.format, command.type, command.buf_size, command.has_pixels ? pixels_bytes.data() : nullptr);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform1f const& command, ReadonlyBytes)
{
    gl.uniform1f(command.location, command.v0);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform1fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 1 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform1fv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform1i const& command, ReadonlyBytes)
{
    gl.uniform1i(command.location, command.v0);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform1iv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 1 * sizeof(GLint))));
    auto value = WebGLCommandList::resolve_typed_span<GLint>(payload, command.value);
    gl.uniform1iv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform1ui const& command, ReadonlyBytes)
{
    gl.uniform1ui(command.location, command.v0);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform1uiv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 1 * sizeof(GLuint))));
    auto value = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.value);
    gl.uniform1uiv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform2f const& command, ReadonlyBytes)
{
    gl.uniform2f(command.location, command.v0, command.v1);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform2fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 2 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform2fv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform2i const& command, ReadonlyBytes)
{
    gl.uniform2i(command.location, command.v0, command.v1);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform2iv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 2 * sizeof(GLint))));
    auto value = WebGLCommandList::resolve_typed_span<GLint>(payload, command.value);
    gl.uniform2iv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform2ui const& command, ReadonlyBytes)
{
    gl.uniform2ui(command.location, command.v0, command.v1);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform2uiv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 2 * sizeof(GLuint))));
    auto value = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.value);
    gl.uniform2uiv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform3f const& command, ReadonlyBytes)
{
    gl.uniform3f(command.location, command.v0, command.v1, command.v2);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform3fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 3 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform3fv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform3i const& command, ReadonlyBytes)
{
    gl.uniform3i(command.location, command.v0, command.v1, command.v2);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform3iv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 3 * sizeof(GLint))));
    auto value = WebGLCommandList::resolve_typed_span<GLint>(payload, command.value);
    gl.uniform3iv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform3ui const& command, ReadonlyBytes)
{
    gl.uniform3ui(command.location, command.v0, command.v1, command.v2);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform3uiv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 3 * sizeof(GLuint))));
    auto value = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.value);
    gl.uniform3uiv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform4f const& command, ReadonlyBytes)
{
    gl.uniform4f(command.location, command.v0, command.v1, command.v2, command.v3);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform4fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 4 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform4fv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform4i const& command, ReadonlyBytes)
{
    gl.uniform4i(command.location, command.v0, command.v1, command.v2, command.v3);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform4iv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 4 * sizeof(GLint))));
    auto value = WebGLCommandList::resolve_typed_span<GLint>(payload, command.value);
    gl.uniform4iv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform4ui const& command, ReadonlyBytes)
{
    gl.uniform4ui(command.location, command.v0, command.v1, command.v2, command.v3);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Uniform4uiv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 4 * sizeof(GLuint))));
    auto value = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.value);
    gl.uniform4uiv(command.location, command.count, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::UniformBlockBinding const& command, ReadonlyBytes)
{
    auto program = objects.lookup(command.program);
    gl.uniform_block_binding(program, command.uniform_block_index, command.uniform_block_binding);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix2fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 4 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix2fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix2x3fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 6 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix2x3fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix2x4fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 8 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix2x4fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix3fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 9 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix3fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix3x2fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 6 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix3x2fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix3x4fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 12 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix3x4fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix4fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 16 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix4fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix4x2fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 8 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix4x2fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::UniformMatrix4x3fv const& command, ReadonlyBytes payload)
{
    auto value_bytes = WebGLCommandList::resolve_data_span(payload, command.value);
    VERIFY(!(static_cast<i64>(value_bytes.size()) != static_cast<i64>(static_cast<i64>(command.count) * 12 * sizeof(GLfloat))));
    auto value = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.value);
    gl.uniform_matrix4x3fv(command.location, command.count, command.transpose, value.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::UseProgram const& command, ReadonlyBytes)
{
    auto program = objects.lookup(command.program);
    gl.use_program(program);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::ValidateProgram const& command, ReadonlyBytes)
{
    auto program = objects.lookup(command.program);
    gl.validate_program(program);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib1f const& command, ReadonlyBytes)
{
    gl.vertex_attrib1f(command.index, command.x);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib1fv const& command, ReadonlyBytes payload)
{
    auto v_bytes = WebGLCommandList::resolve_data_span(payload, command.v);
    VERIFY(!(static_cast<i64>(v_bytes.size()) != static_cast<i64>(1 * sizeof(GLfloat))));
    auto v = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.v);
    gl.vertex_attrib1fv(command.index, v.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib2f const& command, ReadonlyBytes)
{
    gl.vertex_attrib2f(command.index, command.x, command.y);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib2fv const& command, ReadonlyBytes payload)
{
    auto v_bytes = WebGLCommandList::resolve_data_span(payload, command.v);
    VERIFY(!(static_cast<i64>(v_bytes.size()) != static_cast<i64>(2 * sizeof(GLfloat))));
    auto v = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.v);
    gl.vertex_attrib2fv(command.index, v.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib3f const& command, ReadonlyBytes)
{
    gl.vertex_attrib3f(command.index, command.x, command.y, command.z);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib3fv const& command, ReadonlyBytes payload)
{
    auto v_bytes = WebGLCommandList::resolve_data_span(payload, command.v);
    VERIFY(!(static_cast<i64>(v_bytes.size()) != static_cast<i64>(3 * sizeof(GLfloat))));
    auto v = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.v);
    gl.vertex_attrib3fv(command.index, v.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib4f const& command, ReadonlyBytes)
{
    gl.vertex_attrib4f(command.index, command.x, command.y, command.z, command.w);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttrib4fv const& command, ReadonlyBytes payload)
{
    auto v_bytes = WebGLCommandList::resolve_data_span(payload, command.v);
    VERIFY(!(static_cast<i64>(v_bytes.size()) != static_cast<i64>(4 * sizeof(GLfloat))));
    auto v = WebGLCommandList::resolve_typed_span<GLfloat>(payload, command.v);
    gl.vertex_attrib4fv(command.index, v.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribDivisor const& command, ReadonlyBytes)
{
    gl.vertex_attrib_divisor(command.index, command.divisor);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribDivisorANGLE const& command, ReadonlyBytes)
{
    gl.vertex_attrib_divisor_angle(command.index, command.divisor);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribI4i const& command, ReadonlyBytes)
{
    gl.vertex_attrib_i4i(command.index, command.x, command.y, command.z, command.w);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribI4iv const& command, ReadonlyBytes payload)
{
    auto v_bytes = WebGLCommandList::resolve_data_span(payload, command.v);
    VERIFY(!(static_cast<i64>(v_bytes.size()) != static_cast<i64>(4 * sizeof(GLint))));
    auto v = WebGLCommandList::resolve_typed_span<GLint>(payload, command.v);
    gl.vertex_attrib_i4iv(command.index, v.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribI4ui const& command, ReadonlyBytes)
{
    gl.vertex_attrib_i4ui(command.index, command.x, command.y, command.z, command.w);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribI4uiv const& command, ReadonlyBytes payload)
{
    auto v_bytes = WebGLCommandList::resolve_data_span(payload, command.v);
    VERIFY(!(static_cast<i64>(v_bytes.size()) != static_cast<i64>(4 * sizeof(GLuint))));
    auto v = WebGLCommandList::resolve_typed_span<GLuint>(payload, command.v);
    gl.vertex_attrib_i4uiv(command.index, v.data());
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribIPointer const& command, ReadonlyBytes)
{
    gl.vertex_attrib_i_pointer(command.index, command.size, command.type, command.stride, reinterpret_cast<void const*>(static_cast<uintptr_t>(command.pointer)));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::VertexAttribPointer const& command, ReadonlyBytes)
{
    gl.vertex_attrib_pointer(command.index, command.size, command.type, command.normalized, command.stride, reinterpret_cast<void const*>(static_cast<uintptr_t>(command.pointer)));
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap&, Web::WebGL::Commands::Viewport const& command, ReadonlyBytes)
{
    gl.viewport(command.x, command.y, command.width, command.height);
    return {};
}

ErrorOr<void> replay_webgl_command(OpenGLContext& gl, WebGLObjectMap& objects, Web::WebGL::Commands::WaitSync const& command, ReadonlyBytes)
{
    auto sync = objects.lookup_sync(command.sync);
    gl.wait_sync(sync, command.flags, command.timeout);
    return {};
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::CheckFramebufferStatus::Request const& request, ReadonlyBytes)
{
    auto return_value = gl.check_framebuffer_status(request.target);
    SyncCalls::CheckFramebufferStatus::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::ClientWaitSync::Request const& request, ReadonlyBytes)
{
    auto sync = objects.lookup_sync(request.sync);
    auto return_value = gl.client_wait_sync(sync, request.flags, 0);
    SyncCalls::ClientWaitSync::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::Finish::Request const&, ReadonlyBytes)
{
    gl.finish();
    SyncCalls::Finish::Reply reply {  };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetActiveAttrib::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    GLsizei length {};
    GLint size {};
    GLenum type {};
    auto name_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLchar));
    Vector<GLchar> name;
    name.resize(name_byte_size / sizeof(GLchar));
    gl.get_active_attrib(program, request.index, request.buf_size, &length, &size, &type, name.data());
    WebGLDataSpan name_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetActiveAttrib::Reply)), static_cast<u32>(name.size() * sizeof(GLchar)) };
    SyncCalls::GetActiveAttrib::Reply reply { .length = length, .size = size, .type = type, .name = name_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { name.data(), name.size() * sizeof(GLchar) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetActiveUniform::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    GLsizei length {};
    GLint size {};
    GLenum type {};
    auto name_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLchar));
    Vector<GLchar> name;
    name.resize(name_byte_size / sizeof(GLchar));
    gl.get_active_uniform(program, request.index, request.buf_size, &length, &size, &type, name.data());
    WebGLDataSpan name_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetActiveUniform::Reply)), static_cast<u32>(name.size() * sizeof(GLchar)) };
    SyncCalls::GetActiveUniform::Reply reply { .length = length, .size = size, .type = type, .name = name_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { name.data(), name.size() * sizeof(GLchar) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetActiveUniformBlockName::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    GLsizei length {};
    auto uniform_block_name_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLchar));
    Vector<GLchar> uniform_block_name;
    uniform_block_name.resize(uniform_block_name_byte_size / sizeof(GLchar));
    gl.get_active_uniform_block_name(program, request.uniform_block_index, request.buf_size, &length, uniform_block_name.data());
    WebGLDataSpan uniform_block_name_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetActiveUniformBlockName::Reply)), static_cast<u32>(uniform_block_name.size() * sizeof(GLchar)) };
    SyncCalls::GetActiveUniformBlockName::Reply reply { .length = length, .uniform_block_name = uniform_block_name_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { uniform_block_name.data(), uniform_block_name.size() * sizeof(GLchar) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetActiveUniformBlockivRobustANGLE::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_active_uniform_blockiv_robust_angle(program, request.uniform_block_index, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetActiveUniformBlockivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetActiveUniformBlockivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetActiveUniformsiv::Request const& request, ReadonlyBytes payload)
{
    auto program = objects.lookup(request.program);
    auto uniform_indices = WebGLCommandList::resolve_typed_span<GLuint>(payload, request.uniform_indices);
    VERIFY(static_cast<i64>(uniform_indices.size() * sizeof(GLuint)) == static_cast<i64>(static_cast<i64>(request.uniform_count) * sizeof(GLuint)));
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.uniform_count) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_active_uniformsiv(program, request.uniform_count, uniform_indices.data(), request.pname, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetActiveUniformsiv::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetActiveUniformsiv::Reply reply { .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetAttribLocation::Request const& request, ReadonlyBytes payload)
{
    auto program = objects.lookup(request.program);
    auto name_bytes = WebGLCommandList::resolve_string_span(payload, request.name);
    auto return_value = gl.get_attrib_location(program, reinterpret_cast<GLchar const*>(name_bytes.data()));
    SyncCalls::GetAttribLocation::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetBooleanvRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto data_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLboolean));
    Vector<GLboolean> data;
    data.resize(data_byte_size / sizeof(GLboolean));
    gl.get_booleanv_robust_angle(request.pname, request.buf_size, &length, data.data());
    WebGLDataSpan data_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetBooleanvRobustANGLE::Reply)), static_cast<u32>(data.size() * sizeof(GLboolean)) };
    SyncCalls::GetBooleanvRobustANGLE::Reply reply { .length = length, .data = data_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { data.data(), data.size() * sizeof(GLboolean) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetBufferParameterivRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_buffer_parameteriv_robust_angle(request.target, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetBufferParameterivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetBufferParameterivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetError::Request const&, ReadonlyBytes)
{
    auto return_value = gl.get_error();
    SyncCalls::GetError::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetFloatvRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto data_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLfloat));
    Vector<GLfloat> data;
    data.resize(data_byte_size / sizeof(GLfloat));
    gl.get_floatv_robust_angle(request.pname, request.buf_size, &length, data.data());
    WebGLDataSpan data_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetFloatvRobustANGLE::Reply)), static_cast<u32>(data.size() * sizeof(GLfloat)) };
    SyncCalls::GetFloatvRobustANGLE::Reply reply { .length = length, .data = data_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { data.data(), data.size() * sizeof(GLfloat) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetInteger64vRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto data_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint64));
    Vector<GLint64> data;
    data.resize(data_byte_size / sizeof(GLint64));
    gl.get_integer64v_robust_angle(request.pname, request.buf_size, &length, data.data());
    WebGLDataSpan data_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetInteger64vRobustANGLE::Reply)), static_cast<u32>(data.size() * sizeof(GLint64)) };
    SyncCalls::GetInteger64vRobustANGLE::Reply reply { .length = length, .data = data_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { data.data(), data.size() * sizeof(GLint64) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetIntegervRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto data_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> data;
    data.resize(data_byte_size / sizeof(GLint));
    gl.get_integerv_robust_angle(request.pname, request.buf_size, &length, data.data());
    WebGLDataSpan data_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetIntegervRobustANGLE::Reply)), static_cast<u32>(data.size() * sizeof(GLint)) };
    SyncCalls::GetIntegervRobustANGLE::Reply reply { .length = length, .data = data_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { data.data(), data.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetInternalformativRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_internalformativ_robust_angle(request.target, request.internalformat, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetInternalformativRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetInternalformativRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetProgramInfoLog::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    GLsizei length {};
    auto info_log_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLchar));
    Vector<GLchar> info_log;
    info_log.resize(info_log_byte_size / sizeof(GLchar));
    gl.get_program_info_log(program, request.buf_size, &length, info_log.data());
    WebGLDataSpan info_log_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetProgramInfoLog::Reply)), static_cast<u32>(info_log.size() * sizeof(GLchar)) };
    SyncCalls::GetProgramInfoLog::Reply reply { .length = length, .info_log = info_log_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { info_log.data(), info_log.size() * sizeof(GLchar) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetProgramiv::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    auto params_byte_size = static_cast<size_t>(sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_programiv(program, request.pname, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetProgramiv::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetProgramiv::Reply reply { .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetProgramivRobustANGLE::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_programiv_robust_angle(program, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetProgramivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetProgramivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetQueryObjectuivRobustANGLE::Request const& request, ReadonlyBytes)
{
    auto id = objects.lookup(request.id);
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLuint));
    Vector<GLuint> params;
    params.resize(params_byte_size / sizeof(GLuint));
    gl.get_query_objectuiv_robust_angle(id, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetQueryObjectuivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLuint)) };
    SyncCalls::GetQueryObjectuivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLuint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetRenderbufferParameterivRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_renderbuffer_parameteriv_robust_angle(request.target, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetRenderbufferParameterivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetRenderbufferParameterivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetShaderInfoLog::Request const& request, ReadonlyBytes)
{
    auto shader = objects.lookup(request.shader);
    GLsizei length {};
    auto info_log_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLchar));
    Vector<GLchar> info_log;
    info_log.resize(info_log_byte_size / sizeof(GLchar));
    gl.get_shader_info_log(shader, request.buf_size, &length, info_log.data());
    WebGLDataSpan info_log_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetShaderInfoLog::Reply)), static_cast<u32>(info_log.size() * sizeof(GLchar)) };
    SyncCalls::GetShaderInfoLog::Reply reply { .length = length, .info_log = info_log_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { info_log.data(), info_log.size() * sizeof(GLchar) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetShaderPrecisionFormat::Request const& request, ReadonlyBytes)
{
    auto range_byte_size = static_cast<size_t>(2 * sizeof(GLint));
    Vector<GLint> range;
    range.resize(range_byte_size / sizeof(GLint));
    auto precision_byte_size = static_cast<size_t>(sizeof(GLint));
    Vector<GLint> precision;
    precision.resize(precision_byte_size / sizeof(GLint));
    gl.get_shader_precision_format(request.shadertype, request.precisiontype, range.data(), precision.data());
    WebGLDataSpan range_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetShaderPrecisionFormat::Reply)), static_cast<u32>(range.size() * sizeof(GLint)) };
    WebGLDataSpan precision_span { WebGLCommandList::next_inline_data_offset(range_span), static_cast<u32>(precision.size() * sizeof(GLint)) };
    SyncCalls::GetShaderPrecisionFormat::Reply reply { .range = range_span, .precision = precision_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { range.data(), range.size() * sizeof(GLint) }, ReadonlyBytes { precision.data(), precision.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetShaderSource::Request const& request, ReadonlyBytes)
{
    auto shader = objects.lookup(request.shader);
    GLsizei length {};
    auto source_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLchar));
    Vector<GLchar> source;
    source.resize(source_byte_size / sizeof(GLchar));
    gl.get_shader_source(shader, request.buf_size, &length, source.data());
    WebGLDataSpan source_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetShaderSource::Reply)), static_cast<u32>(source.size() * sizeof(GLchar)) };
    SyncCalls::GetShaderSource::Reply reply { .length = length, .source = source_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { source.data(), source.size() * sizeof(GLchar) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetShaderiv::Request const& request, ReadonlyBytes)
{
    auto shader = objects.lookup(request.shader);
    auto params_byte_size = static_cast<size_t>(sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_shaderiv(shader, request.pname, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetShaderiv::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetShaderiv::Reply reply { .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetShaderivRobustANGLE::Request const& request, ReadonlyBytes)
{
    auto shader = objects.lookup(request.shader);
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_shaderiv_robust_angle(shader, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetShaderivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetShaderivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetSynciv::Request const& request, ReadonlyBytes)
{
    auto sync = objects.lookup_sync(request.sync);
    GLsizei length {};
    auto values_byte_size = static_cast<size_t>(static_cast<i64>(request.count) * sizeof(GLint));
    Vector<GLint> values;
    values.resize(values_byte_size / sizeof(GLint));
    gl.get_synciv(sync, request.pname, request.count, &length, values.data());
    WebGLDataSpan values_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetSynciv::Reply)), static_cast<u32>(values.size() * sizeof(GLint)) };
    SyncCalls::GetSynciv::Reply reply { .length = length, .values = values_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { values.data(), values.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetTexParameterfvRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLfloat));
    Vector<GLfloat> params;
    params.resize(params_byte_size / sizeof(GLfloat));
    gl.get_tex_parameterfv_robust_angle(request.target, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetTexParameterfvRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLfloat)) };
    SyncCalls::GetTexParameterfvRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLfloat) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetTexParameterivRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_tex_parameteriv_robust_angle(request.target, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetTexParameterivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetTexParameterivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetUniformBlockIndex::Request const& request, ReadonlyBytes payload)
{
    auto program = objects.lookup(request.program);
    auto uniform_block_name_bytes = WebGLCommandList::resolve_string_span(payload, request.uniform_block_name);
    auto return_value = gl.get_uniform_block_index(program, reinterpret_cast<GLchar const*>(uniform_block_name_bytes.data()));
    SyncCalls::GetUniformBlockIndex::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::GetUniformLocation::Request const& request, ReadonlyBytes payload)
{
    auto program = objects.lookup(request.program);
    auto name_bytes = WebGLCommandList::resolve_string_span(payload, request.name);
    auto return_value = gl.get_uniform_location(program, reinterpret_cast<GLchar const*>(name_bytes.data()));
    SyncCalls::GetUniformLocation::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetVertexAttribfvRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLfloat));
    Vector<GLfloat> params;
    params.resize(params_byte_size / sizeof(GLfloat));
    gl.get_vertex_attribfv_robust_angle(request.index, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetVertexAttribfvRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLfloat)) };
    SyncCalls::GetVertexAttribfvRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLfloat) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::GetVertexAttribivRobustANGLE::Request const& request, ReadonlyBytes)
{
    GLsizei length {};
    auto params_byte_size = static_cast<size_t>(static_cast<i64>(request.buf_size) * sizeof(GLint));
    Vector<GLint> params;
    params.resize(params_byte_size / sizeof(GLint));
    gl.get_vertex_attribiv_robust_angle(request.index, request.pname, request.buf_size, &length, params.data());
    WebGLDataSpan params_span { WebGLCommandList::first_inline_data_offset(sizeof(SyncCalls::GetVertexAttribivRobustANGLE::Reply)), static_cast<u32>(params.size() * sizeof(GLint)) };
    SyncCalls::GetVertexAttribivRobustANGLE::Reply reply { .length = length, .params = params_span };
    return WebGLSyncCall::encode_reply(reply, ReadonlyBytes { params.data(), params.size() * sizeof(GLint) });
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsBuffer::Request const& request, ReadonlyBytes)
{
    auto buffer = objects.lookup(request.buffer);
    auto return_value = gl.is_buffer(buffer);
    SyncCalls::IsBuffer::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap&, SyncCalls::IsEnabled::Request const& request, ReadonlyBytes)
{
    auto return_value = gl.is_enabled(request.cap);
    SyncCalls::IsEnabled::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsFramebuffer::Request const& request, ReadonlyBytes)
{
    auto framebuffer = objects.lookup(request.framebuffer);
    auto return_value = gl.is_framebuffer(framebuffer);
    SyncCalls::IsFramebuffer::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsProgram::Request const& request, ReadonlyBytes)
{
    auto program = objects.lookup(request.program);
    auto return_value = gl.is_program(program);
    SyncCalls::IsProgram::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsRenderbuffer::Request const& request, ReadonlyBytes)
{
    auto renderbuffer = objects.lookup(request.renderbuffer);
    auto return_value = gl.is_renderbuffer(renderbuffer);
    SyncCalls::IsRenderbuffer::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsShader::Request const& request, ReadonlyBytes)
{
    auto shader = objects.lookup(request.shader);
    auto return_value = gl.is_shader(shader);
    SyncCalls::IsShader::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsTexture::Request const& request, ReadonlyBytes)
{
    auto texture = objects.lookup(request.texture);
    auto return_value = gl.is_texture(texture);
    SyncCalls::IsTexture::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsVertexArray::Request const& request, ReadonlyBytes)
{
    auto array = objects.lookup(request.array);
    auto return_value = gl.is_vertex_array(array);
    SyncCalls::IsVertexArray::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

static ByteBuffer handle_one(OpenGLContext& gl, WebGLObjectMap& objects, SyncCalls::IsVertexArrayOES::Request const& request, ReadonlyBytes)
{
    auto array = objects.lookup(request.array);
    auto return_value = gl.is_vertex_array_oes(array);
    SyncCalls::IsVertexArrayOES::Reply reply { .return_value = return_value };
    return WebGLSyncCall::encode_reply(reply);
}

ErrorOr<ByteBuffer> handle_webgl_sync_call(OpenGLContext& gl, WebGLObjectMap& objects, ReadonlyBytes request)
{
    return WebGLSyncCall::dispatch_request(request, [&]<typename Call>(typename Call::Request const& call_request, ReadonlyBytes payload) -> ErrorOr<ByteBuffer> {
        return handle_one(gl, objects, call_request, payload);
    });
}

}
