/*
 * Copyright (C) 2017 Apple Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "InspectorCanvas.h"

#include "AffineTransform.h"
#include "CachedImage.h"
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "CanvasRenderingContext.h"
#include "CanvasRenderingContext2D.h"
#include "Document.h"
#include "Element.h"
#include "FloatPoint.h"
#include "Gradient.h"
#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
#include "HTMLVideoElement.h"
#include "Image.h"
#include "ImageBitmap.h"
#include "ImageBitmapRenderingContext.h"
#include "ImageBuffer.h"
#include "ImageData.h"
#include "InspectorDOMAgent.h"
#include "JSCanvasDirection.h"
#include "JSCanvasFillRule.h"
#include "JSCanvasLineCap.h"
#include "JSCanvasLineJoin.h"
#include "JSCanvasRenderingContext2D.h"
#include "JSCanvasTextAlign.h"
#include "JSCanvasTextBaseline.h"
#include "JSExecState.h"
#include "JSImageBitmapRenderingContext.h"
#include "JSImageSmoothingQuality.h"
#include "Path2D.h"
#include "Pattern.h"
#include "RecordingSwizzleTypes.h"
#include "SVGPathUtilities.h"
#include "StringAdaptors.h"
#include <JavaScriptCore/IdentifiersFactory.h>
#include <JavaScriptCore/ScriptCallStackFactory.h>
#include <wtf/Function.h>

#if ENABLE(CSS_TYPED_OM)
#include "TypedOMCSSImageValue.h"
#endif

#if ENABLE(WEBGL)
#include "JSWebGLRenderingContext.h"
#include "WebGLRenderingContext.h"
#endif

#if ENABLE(WEBGL2)
#include "JSWebGL2RenderingContext.h"
#include "WebGL2RenderingContext.h"
#endif

#if ENABLE(WEBGPU)
#include "GPUCanvasContext.h"
#include "JSWebGPUDevice.h"
#include "WebGPUDevice.h"
#endif

namespace WebCore {

using namespace Inspector;

#if ENABLE(WEBGPU)
static HTMLCanvasElement* canvasIfContextMatchesDevice(CanvasRenderingContext& context, WebGPUDevice& device)
{
    if (is<GPUCanvasContext>(context)) {
        auto& contextGPU = downcast<GPUCanvasContext>(context);
        if (auto* webGPUSwapChain = contextGPU.swapChain()) {
            if (auto* gpuSwapChain = webGPUSwapChain->swapChain()) {
                if (gpuSwapChain == device.device().swapChain()) {
                    if (is<HTMLCanvasElement>(contextGPU.canvasBase()))
                        return &downcast<HTMLCanvasElement>(contextGPU.canvasBase());
                }
            }
        }
    }
    return nullptr;
}
#endif

Ref<InspectorCanvas> InspectorCanvas::create(CanvasRenderingContext& context)
{
    return adoptRef(*new InspectorCanvas(context));
}

#if ENABLE(WEBGPU)
Ref<InspectorCanvas> InspectorCanvas::create(WebGPUDevice& device)
{
    return adoptRef(*new InspectorCanvas(device));
}
#endif

InspectorCanvas::InspectorCanvas(CanvasRenderingContext& context)
    : m_identifier("canvas:" + IdentifiersFactory::createIdentifier())
    , m_context(context)
{
#if ENABLE(WEBGPU)
    // The actual "context" for WebGPU is the `WebGPUDevice`, not the <canvas>.
    ASSERT(!is<GPUCanvasContext>(context));
#endif
}

#if ENABLE(WEBGPU)
InspectorCanvas::InspectorCanvas(WebGPUDevice& device)
    : m_identifier("canvas:" + IdentifiersFactory::createIdentifier())
    , m_context(device)
{
}
#endif

CanvasRenderingContext* InspectorCanvas::canvasContext() const
{
    if (auto* contextWrapper = WTF::get_if<std::reference_wrapper<CanvasRenderingContext>>(m_context))
        return &contextWrapper->get();
    return nullptr;
}

HTMLCanvasElement* InspectorCanvas::canvasElement() const
{
    return WTF::switchOn(m_context,
        [] (std::reference_wrapper<CanvasRenderingContext> contextWrapper) -> HTMLCanvasElement* {
            auto& context = contextWrapper.get();
            if (is<HTMLCanvasElement>(context.canvasBase()))
                return &downcast<HTMLCanvasElement>(context.canvasBase());
            return nullptr;
        },
#if ENABLE(WEBGPU)
        [&] (std::reference_wrapper<WebGPUDevice> deviceWrapper) -> HTMLCanvasElement* {
            auto& device = deviceWrapper.get();
            {
                LockHolder lock(CanvasRenderingContext::instancesMutex());
                for (auto* canvasRenderingContext : CanvasRenderingContext::instances(lock)) {
                    if (auto* canvasElement = canvasIfContextMatchesDevice(*canvasRenderingContext, device))
                        return canvasElement;
                }
            }
            return nullptr;
        },
#endif
        [] (Monostate) {
            ASSERT_NOT_REACHED();
            return nullptr;
        }
    );
    return nullptr;
}

#if ENABLE(WEBGPU)
WebGPUDevice* InspectorCanvas::deviceContext() const
{
    if (auto* deviceWrapper = WTF::get_if<std::reference_wrapper<WebGPUDevice>>(m_context))
        return &deviceWrapper->get();
    return nullptr;
}

bool InspectorCanvas::isDeviceForCanvasContext(CanvasRenderingContext& context) const
{
    if (auto* device = deviceContext())
        return canvasIfContextMatchesDevice(context, *device);
    return false;
}
#endif

ScriptExecutionContext* InspectorCanvas::scriptExecutionContext() const
{
    return WTF::switchOn(m_context,
        [] (std::reference_wrapper<CanvasRenderingContext> contextWrapper) {
            auto& context = contextWrapper.get();
            return context.canvasBase().scriptExecutionContext();
        },
#if ENABLE(WEBGPU)
        [] (std::reference_wrapper<WebGPUDevice> deviceWrapper) {
            auto& device = deviceWrapper.get();
            return device.scriptExecutionContext();
        },
#endif
        [] (Monostate) {
            ASSERT_NOT_REACHED();
            return nullptr;
        }
    );
}

JSC::JSValue InspectorCanvas::resolveContext(JSC::JSGlobalObject* exec) const
{
    JSC::JSLockHolder lock(exec);

    auto* globalObject = deprecatedGlobalObjectForPrototype(exec);

    return WTF::switchOn(m_context,
        [&] (std::reference_wrapper<CanvasRenderingContext> contextWrapper) {
            auto& context = contextWrapper.get();
            if (is<CanvasRenderingContext2D>(context))
                return toJS(exec, globalObject, downcast<CanvasRenderingContext2D>(context));
            if (is<ImageBitmapRenderingContext>(context))
                return toJS(exec, globalObject, downcast<ImageBitmapRenderingContext>(context));
#if ENABLE(WEBGL)
            if (is<WebGLRenderingContext>(context))
                return toJS(exec, globalObject, downcast<WebGLRenderingContext>(context));
#endif
#if ENABLE(WEBGL2)
            if (is<WebGL2RenderingContext>(context))
                return toJS(exec, globalObject, downcast<WebGL2RenderingContext>(context));
#endif
            return JSC::JSValue();
        },
#if ENABLE(WEBGPU)
        [&] (std::reference_wrapper<WebGPUDevice> deviceWrapper) {
            return toJS(exec, globalObject, deviceWrapper.get());
        },
#endif
        [] (Monostate) {
            ASSERT_NOT_REACHED();
            return JSC::JSValue();
        }
    );
}

HashSet<Element*> InspectorCanvas::clientNodes() const
{
    return WTF::switchOn(m_context,
        [] (std::reference_wrapper<CanvasRenderingContext> contextWrapper) {
            auto& context = contextWrapper.get();
            return context.canvasBase().cssCanvasClients();
        },
#if ENABLE(WEBGPU)
        [&] (std::reference_wrapper<WebGPUDevice> deviceWrapper) {
            auto& device = deviceWrapper.get();

            HashSet<Element*> canvasElementClients;
            {
                LockHolder lock(CanvasRenderingContext::instancesMutex());
                for (auto* canvasRenderingContext : CanvasRenderingContext::instances(lock)) {
                    if (auto* canvasElement = canvasIfContextMatchesDevice(*canvasRenderingContext, device))
                        canvasElementClients.add(canvasElement);
                }
            }
            return canvasElementClients;
        },
#endif
        [] (Monostate) {
            ASSERT_NOT_REACHED();
            return HashSet<Element*>();
        }
    );
}

void InspectorCanvas::canvasChanged()
{
    auto* context = canvasContext();
    ASSERT(context);

    if (!context->callTracingActive())
        return;

    // Since 2D contexts are able to be fully reproduced in the frontend, we don't need snapshots.
    if (is<CanvasRenderingContext2D>(context))
        return;

    m_contentChanged = true;
}

void InspectorCanvas::resetRecordingData()
{
    m_initialState = nullptr;
    m_frames = nullptr;
    m_currentActions = nullptr;
    m_serializedDuplicateData = nullptr;
    m_indexedDuplicateData.clear();
    m_recordingName = { };
    m_bufferLimit = 100 * 1024 * 1024;
    m_bufferUsed = 0;
    m_frameCount = WTF::nullopt;
    m_framesCaptured = 0;
    m_contentChanged = false;

    auto* context = canvasContext();
    ASSERT(context);
    // FIXME: <https://webkit.org/b/201651> Web Inspector: Canvas: support canvas recordings for WebGPUDevice

    context->setCallTracingActive(false);
}

bool InspectorCanvas::hasRecordingData() const
{
    return m_bufferUsed > 0;
}

bool InspectorCanvas::currentFrameHasData() const
{
    return !!m_frames;
}

static bool shouldSnapshotBitmapRendererAction(const String& name)
{
    return name == "transferFromImageBitmap";
}

#if ENABLE(WEBGL)
static bool shouldSnapshotWebGLAction(const String& name)
{
    return name == "clear"
        || name == "drawArrays"
        || name == "drawElements";
}
#endif

#if ENABLE(WEBGL2)
static bool shouldSnapshotWebGL2Action(const String& name)
{
    return name == "clear"
        || name == "drawArrays"
        || name == "drawArraysInstanced"
        || name == "drawElements"
        || name == "drawElementsInstanced";
}
#endif

void InspectorCanvas::recordAction(const String& name, std::initializer_list<RecordCanvasActionVariant>&& parameters)
{
    if (!m_initialState) {
        // We should only construct the initial state for the first action of the recording.
        ASSERT(!m_frames && !m_currentActions);

        m_initialState = buildInitialState();
        m_bufferUsed += m_initialState->memoryCost();
    }

    if (!m_frames)
        m_frames = JSON::ArrayOf<Inspector::Protocol::Recording::Frame>::create();

    if (!m_currentActions) {
        m_currentActions = JSON::ArrayOf<JSON::Value>::create();

        auto frame = Inspector::Protocol::Recording::Frame::create()
            .setActions(m_currentActions)
            .release();

        m_frames->addItem(WTFMove(frame));
        ++m_framesCaptured;

        m_currentFrameStartTime = MonotonicTime::now();
    }

    appendActionSnapshotIfNeeded();

    m_lastRecordedAction = buildAction(name, WTFMove(parameters));
    m_bufferUsed += m_lastRecordedAction->memoryCost();
    m_currentActions->addItem(m_lastRecordedAction.get());

    auto* context = canvasContext();
    ASSERT(context);
    // FIXME: <https://webkit.org/b/201651> Web Inspector: Canvas: support canvas recordings for WebGPUDevice

    if (is<ImageBitmapRenderingContext>(context) && shouldSnapshotBitmapRendererAction(name))
        m_contentChanged = true;
#if ENABLE(WEBGL)
    else if (is<WebGLRenderingContext>(context) && shouldSnapshotWebGLAction(name))
        m_contentChanged = true;
#endif
#if ENABLE(WEBGL2)
    else if (is<WebGL2RenderingContext>(context) && shouldSnapshotWebGL2Action(name))
        m_contentChanged = true;
#endif
}

void InspectorCanvas::finalizeFrame()
{
    appendActionSnapshotIfNeeded();

    if (m_frames && m_frames->length() && !std::isnan(m_currentFrameStartTime)) {
        auto currentFrame = static_cast<Inspector::Protocol::Recording::Frame*>(m_frames->get(m_frames->length() - 1).get());
        currentFrame->setDuration((MonotonicTime::now() - m_currentFrameStartTime).milliseconds());

        m_currentFrameStartTime = MonotonicTime::nan();
    }

    m_currentActions = nullptr;
}

void InspectorCanvas::markCurrentFrameIncomplete()
{
    if (!m_currentActions || !m_frames || !m_frames->length())
        return;

    static_cast<Inspector::Protocol::Recording::Frame*>(m_frames->get(m_frames->length() - 1).get())->setIncomplete(true);
}

void InspectorCanvas::setBufferLimit(long memoryLimit)
{
    m_bufferLimit = std::min<long>(memoryLimit, std::numeric_limits<int>::max());
}

bool InspectorCanvas::hasBufferSpace() const
{
    return m_bufferUsed < m_bufferLimit;
}

void InspectorCanvas::setFrameCount(long frameCount)
{
    if (frameCount > 0)
        m_frameCount = std::min<long>(frameCount, std::numeric_limits<int>::max());
    else
        m_frameCount = WTF::nullopt;
}

bool InspectorCanvas::overFrameCount() const
{
    return m_frameCount && m_framesCaptured >= m_frameCount.value();
}

Ref<Inspector::Protocol::Canvas::Canvas> InspectorCanvas::buildObjectForCanvas(bool captureBacktrace)
{
    using ContextTypeType = Optional<Inspector::Protocol::Canvas::ContextType>;
    auto contextType = WTF::switchOn(m_context,
        [] (std::reference_wrapper<CanvasRenderingContext> contextWrapper) -> ContextTypeType {
            auto& context = contextWrapper.get();
            if (is<CanvasRenderingContext2D>(context))
                return Inspector::Protocol::Canvas::ContextType::Canvas2D;
            if (is<ImageBitmapRenderingContext>(context))
                return Inspector::Protocol::Canvas::ContextType::BitmapRenderer;
#if ENABLE(WEBGL)
            if (is<WebGLRenderingContext>(context))
                return Inspector::Protocol::Canvas::ContextType::WebGL;
#endif
#if ENABLE(WEBGL2)
            if (is<WebGL2RenderingContext>(context))
                return Inspector::Protocol::Canvas::ContextType::WebGL2;
#endif
            return WTF::nullopt;
        },
#if ENABLE(WEBGPU)
        [] (std::reference_wrapper<WebGPUDevice>) {
            return Inspector::Protocol::Canvas::ContextType::WebGPU;
        },
#endif
        [] (Monostate) {
            ASSERT_NOT_REACHED();
            return WTF::nullopt;
        }
    );
    if (!contextType) {
        ASSERT_NOT_REACHED();
        contextType = Inspector::Protocol::Canvas::ContextType::Canvas2D;
    }

    auto canvas = Inspector::Protocol::Canvas::Canvas::create()
        .setCanvasId(m_identifier)
        .setContextType(contextType.value())
        .release();

    if (auto* node = canvasElement()) {
        String cssCanvasName = node->document().nameForCSSCanvasElement(*node);
        if (!cssCanvasName.isEmpty())
            canvas->setCssCanvasName(cssCanvasName);

        // FIXME: <https://webkit.org/b/178282> Web Inspector: send a DOM node with each Canvas payload and eliminate Canvas.requestNode
    }

    using ContextAttributesType = RefPtr<Inspector::Protocol::Canvas::ContextAttributes>;
    auto contextAttributes = WTF::switchOn(m_context,
        [] (std::reference_wrapper<CanvasRenderingContext> contextWrapper) -> ContextAttributesType {
            auto& context = contextWrapper.get();
            if (is<ImageBitmapRenderingContext>(context)) {
                auto contextAttributesPayload = Inspector::Protocol::Canvas::ContextAttributes::create()
                    .release();
                contextAttributesPayload->setAlpha(downcast<ImageBitmapRenderingContext>(context).hasAlpha());
                return WTFMove(contextAttributesPayload);
            }

#if ENABLE(WEBGL)
            if (is<WebGLRenderingContextBase>(context)) {
                if (const auto& attributes = downcast<WebGLRenderingContextBase>(context).getContextAttributes()) {
                    auto contextAttributesPayload = Inspector::Protocol::Canvas::ContextAttributes::create()
                        .release();
                    contextAttributesPayload->setAlpha(attributes->alpha);
                    contextAttributesPayload->setDepth(attributes->depth);
                    contextAttributesPayload->setStencil(attributes->stencil);
                    contextAttributesPayload->setAntialias(attributes->antialias);
                    contextAttributesPayload->setPremultipliedAlpha(attributes->premultipliedAlpha);
                    contextAttributesPayload->setPreserveDrawingBuffer(attributes->preserveDrawingBuffer);
                    switch (attributes->powerPreference) {
                    case WebGLPowerPreference::Default:
                        contextAttributesPayload->setPowerPreference("default");
                        break;
                    case WebGLPowerPreference::LowPower:
                        contextAttributesPayload->setPowerPreference("low-power");
                        break;
                    case WebGLPowerPreference::HighPerformance:
                        contextAttributesPayload->setPowerPreference("high-performance");
                        break;
                    }
                    contextAttributesPayload->setFailIfMajorPerformanceCaveat(attributes->failIfMajorPerformanceCaveat);
                    return WTFMove(contextAttributesPayload);
                }
            }
#endif
            return nullptr;
        },
#if ENABLE(WEBGPU)
        [] (std::reference_wrapper<WebGPUDevice> deviceWrapper) -> ContextAttributesType {
            auto& device = deviceWrapper.get();
            if (const auto& options = device.adapter().options()) {
                auto contextAttributesPayload = Inspector::Protocol::Canvas::ContextAttributes::create()
                    .release();
                if (const auto& powerPreference = options->powerPreference) {
                    switch (powerPreference.value()) {
                    case GPUPowerPreference::LowPower:
                        contextAttributesPayload->setPowerPreference("low-power");
                        break;

                    case GPUPowerPreference::HighPerformance:
                        contextAttributesPayload->setPowerPreference("high-performance");
                        break;
                    }
                }
                return WTFMove(contextAttributesPayload);
            }
            return nullptr;
        },
#endif
        [] (Monostate) {
            ASSERT_NOT_REACHED();
            return nullptr;
        }
    );
    if (contextAttributes)
        canvas->setContextAttributes(WTFMove(contextAttributes));

    // FIXME: <https://webkit.org/b/180833> Web Inspector: support OffscreenCanvas for Canvas related operations

    if (auto* node = canvasElement()) {
        if (size_t memoryCost = node->memoryCost())
            canvas->setMemoryCost(memoryCost);
    }

    if (captureBacktrace) {
        auto stackTrace = Inspector::createScriptCallStack(JSExecState::currentState(), Inspector::ScriptCallStack::maxCallStackSizeToCapture);
        canvas->setBacktrace(stackTrace->buildInspectorArray());
    }

    return canvas;
}

Ref<Inspector::Protocol::Recording::Recording> InspectorCanvas::releaseObjectForRecording()
{
    ASSERT(!m_currentActions);
    ASSERT(!m_lastRecordedAction);
    ASSERT(!m_frames);

    auto* context = canvasContext();
    ASSERT(context);
    // FIXME: <https://webkit.org/b/201651> Web Inspector: Canvas: support canvas recordings for WebGPUDevice

    Inspector::Protocol::Recording::Type type;
    if (is<CanvasRenderingContext2D>(context))
        type = Inspector::Protocol::Recording::Type::Canvas2D;
    else if (is<ImageBitmapRenderingContext>(context))
        type = Inspector::Protocol::Recording::Type::CanvasBitmapRenderer;
#if ENABLE(WEBGL)
    else if (is<WebGLRenderingContext>(context))
        type = Inspector::Protocol::Recording::Type::CanvasWebGL;
#endif
#if ENABLE(WEBGL2)
    else if (is<WebGL2RenderingContext>(context))
        type = Inspector::Protocol::Recording::Type::CanvasWebGL2;
#endif
    else {
        ASSERT_NOT_REACHED();
        type = Inspector::Protocol::Recording::Type::Canvas2D;
    }

    auto recording = Inspector::Protocol::Recording::Recording::create()
        .setVersion(Inspector::Protocol::Recording::VERSION)
        .setType(type)
        .setInitialState(m_initialState.releaseNonNull())
        .setData(m_serializedDuplicateData.releaseNonNull())
        .release();

    if (!m_recordingName.isEmpty())
        recording->setName(m_recordingName);

    resetRecordingData();

    return recording;
}

String InspectorCanvas::getCanvasContentAsDataURL(ErrorString& errorString)
{
    auto* node = canvasElement();
    if (!node) {
        errorString = "Missing HTMLCanvasElement of canvas for given canvasId"_s;
        return emptyString();
    }

#if ENABLE(WEBGL)
    auto* context = node->renderingContext();
    if (is<WebGLRenderingContextBase>(context))
        downcast<WebGLRenderingContextBase>(*context).setPreventBufferClearForInspector(true);
#endif

    ExceptionOr<UncachedString> result = node->toDataURL("image/png"_s);

#if ENABLE(WEBGL)
    if (is<WebGLRenderingContextBase>(context))
        downcast<WebGLRenderingContextBase>(*context).setPreventBufferClearForInspector(false);
#endif

    if (result.hasException()) {
        errorString = result.releaseException().releaseMessage();
        return emptyString();
    }

    return result.releaseReturnValue().string;
}

void InspectorCanvas::appendActionSnapshotIfNeeded()
{
    if (!m_lastRecordedAction)
        return;

    if (m_contentChanged) {
        m_bufferUsed -= m_lastRecordedAction->memoryCost();

        ErrorString ignored;
        m_lastRecordedAction->addItem(indexForData(getCanvasContentAsDataURL(ignored)));

        m_bufferUsed += m_lastRecordedAction->memoryCost();
    }

    m_lastRecordedAction = nullptr;
    m_contentChanged = false;
}

int InspectorCanvas::indexForData(DuplicateDataVariant data)
{
    size_t index = m_indexedDuplicateData.findMatching([&] (auto item) {
        if (data == item)
            return true;

        auto traceA = WTF::get_if<RefPtr<ScriptCallStack>>(data);
        auto traceB = WTF::get_if<RefPtr<ScriptCallStack>>(item);
        if (traceA && *traceA && traceB && *traceB)
            return (*traceA)->isEqual((*traceB).get());

        return false;
    });
    if (index != notFound) {
        ASSERT(index < static_cast<size_t>(std::numeric_limits<int>::max()));
        return static_cast<int>(index);
    }

    if (!m_serializedDuplicateData)
        m_serializedDuplicateData = JSON::ArrayOf<JSON::Value>::create();

    RefPtr<JSON::Value> item;
    WTF::switchOn(data,
        [&] (const RefPtr<HTMLImageElement>& imageElement) {
            String dataURL = "data:,"_s;

            if (CachedImage* cachedImage = imageElement->cachedImage()) {
                Image* image = cachedImage->image();
                if (image && image != &Image::nullImage()) {
                    std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(image->size(), RenderingMode::Unaccelerated);
                    imageBuffer->context().drawImage(*image, FloatPoint(0, 0));
                    dataURL = imageBuffer->toDataURL("image/png");
                }
            }

            index = indexForData(dataURL);
        },
#if ENABLE(VIDEO)
        [&] (RefPtr<HTMLVideoElement>& videoElement) {
            String dataURL = "data:,"_s;

            unsigned videoWidth = videoElement->videoWidth();
            unsigned videoHeight = videoElement->videoHeight();
            std::unique_ptr<ImageBuffer> imageBuffer = ImageBuffer::create(FloatSize(videoWidth, videoHeight), RenderingMode::Unaccelerated);
            if (imageBuffer) {
                videoElement->paintCurrentFrameInContext(imageBuffer->context(), FloatRect(0, 0, videoWidth, videoHeight));
                dataURL = imageBuffer->toDataURL("image/png");
            }

            index = indexForData(dataURL);
        },
#endif
        [&] (RefPtr<HTMLCanvasElement>& canvasElement) {
            String dataURL = "data:,"_s;

            ExceptionOr<UncachedString> result = canvasElement->toDataURL("image/png"_s);
            if (!result.hasException())
                dataURL = result.releaseReturnValue().string;

            index = indexForData(dataURL);
        },
        [&] (const RefPtr<CanvasGradient>& canvasGradient) { item = buildArrayForCanvasGradient(*canvasGradient); },
        [&] (const RefPtr<CanvasPattern>& canvasPattern) { item = buildArrayForCanvasPattern(*canvasPattern); },
        [&] (const RefPtr<ImageData>& imageData) { item = buildArrayForImageData(*imageData); },
        [&] (RefPtr<ImageBitmap>& imageBitmap) {
            index = indexForData(imageBitmap->buffer()->toDataURL("image/png"));
        },
        [&] (const RefPtr<ScriptCallStack>& scriptCallStack) {
            auto array = JSON::ArrayOf<double>::create();
            for (size_t i = 0; i < scriptCallStack->size(); ++i)
                array->addItem(indexForData(scriptCallStack->at(i)));
            item = WTFMove(array);
        },
#if ENABLE(CSS_TYPED_OM)
        [&] (const RefPtr<TypedOMCSSImageValue>& cssImageValue) {
            String dataURL = "data:,"_s;

            if (auto* cachedImage = cssImageValue->image()) {
                auto* image = cachedImage->image();
                if (image && image != &Image::nullImage()) {
                    auto imageBuffer = ImageBuffer::create(image->size(), RenderingMode::Unaccelerated);
                    imageBuffer->context().drawImage(*image, FloatPoint(0, 0));
                    dataURL = imageBuffer->toDataURL("image/png");
                }
            }

            index = indexForData(dataURL);
        },
#endif
        [&] (const ScriptCallFrame& scriptCallFrame) {
            auto array = JSON::ArrayOf<double>::create();
            array->addItem(indexForData(scriptCallFrame.functionName()));
            array->addItem(indexForData(scriptCallFrame.sourceURL()));
            array->addItem(static_cast<int>(scriptCallFrame.lineNumber()));
            array->addItem(static_cast<int>(scriptCallFrame.columnNumber()));
            item = WTFMove(array);
        },
        [&] (const String& value) { item = JSON::Value::create(value); }
    );

    if (item) {
        m_bufferUsed += item->memoryCost();
        m_serializedDuplicateData->addItem(WTFMove(item));

        m_indexedDuplicateData.append(data);
        index = m_indexedDuplicateData.size() - 1;
    }

    ASSERT(index < static_cast<size_t>(std::numeric_limits<int>::max()));
    return static_cast<int>(index);
}

String InspectorCanvas::stringIndexForKey(const String& key)
{
    return String::number(indexForData(key));
}

static Ref<JSON::ArrayOf<double>> buildArrayForAffineTransform(const AffineTransform& affineTransform)
{
    auto array = JSON::ArrayOf<double>::create();
    array->addItem(affineTransform.a());
    array->addItem(affineTransform.b());
    array->addItem(affineTransform.c());
    array->addItem(affineTransform.d());
    array->addItem(affineTransform.e());
    array->addItem(affineTransform.f());
    return array;
}

template<typename T> static Ref<JSON::ArrayOf<JSON::Value>> buildArrayForVector(const Vector<T>& vector)
{
    auto array = JSON::ArrayOf<JSON::Value>::create();
    for (auto& item : vector)
        array->addItem(item);
    return array;
}

Ref<Inspector::Protocol::Recording::InitialState> InspectorCanvas::buildInitialState()
{
    auto* context = canvasContext();
    ASSERT(context);
    // FIXME: <https://webkit.org/b/201651> Web Inspector: Canvas: support canvas recordings for WebGPUDevice

    auto initialStatePayload = Inspector::Protocol::Recording::InitialState::create().release();

    auto attributesPayload = JSON::Object::create();
    attributesPayload->setInteger("width"_s, context->canvasBase().width());
    attributesPayload->setInteger("height"_s, context->canvasBase().height());

    auto statesPayload = JSON::ArrayOf<JSON::Object>::create();

    auto parametersPayload = JSON::ArrayOf<JSON::Value>::create();

    if (is<CanvasRenderingContext2D>(context)) {
        auto& context2d = downcast<CanvasRenderingContext2D>(*context);
        for (auto& state : context2d.stateStack()) {
            auto statePayload = JSON::Object::create();

            statePayload->setArray(stringIndexForKey("setTransform"_s), buildArrayForAffineTransform(state.transform));
            statePayload->setDouble(stringIndexForKey("globalAlpha"_s), context2d.globalAlpha());
            statePayload->setInteger(stringIndexForKey("globalCompositeOperation"_s), indexForData(context2d.globalCompositeOperation()));
            statePayload->setDouble(stringIndexForKey("lineWidth"_s), context2d.lineWidth());
            statePayload->setInteger(stringIndexForKey("lineCap"_s), indexForData(convertEnumerationToString(context2d.lineCap())));
            statePayload->setInteger(stringIndexForKey("lineJoin"_s), indexForData(convertEnumerationToString(context2d.lineJoin())));
            statePayload->setDouble(stringIndexForKey("miterLimit"_s), context2d.miterLimit());
            statePayload->setDouble(stringIndexForKey("shadowOffsetX"_s), context2d.shadowOffsetX());
            statePayload->setDouble(stringIndexForKey("shadowOffsetY"_s), context2d.shadowOffsetY());
            statePayload->setDouble(stringIndexForKey("shadowBlur"_s), context2d.shadowBlur());
            statePayload->setInteger(stringIndexForKey("shadowColor"_s), indexForData(context2d.shadowColor()));

            // The parameter to `setLineDash` is itself an array, so we need to wrap the parameters
            // list in an array to allow spreading.
            auto setLineDash = JSON::ArrayOf<JSON::Value>::create();
            setLineDash->addItem(buildArrayForVector(state.lineDash));
            statePayload->setArray(stringIndexForKey("setLineDash"_s), WTFMove(setLineDash));

            statePayload->setDouble(stringIndexForKey("lineDashOffset"_s), context2d.lineDashOffset());
            statePayload->setInteger(stringIndexForKey("font"_s), indexForData(context2d.font()));
            statePayload->setInteger(stringIndexForKey("textAlign"_s), indexForData(convertEnumerationToString(context2d.textAlign())));
            statePayload->setInteger(stringIndexForKey("textBaseline"_s), indexForData(convertEnumerationToString(context2d.textBaseline())));
            statePayload->setInteger(stringIndexForKey("direction"_s), indexForData(convertEnumerationToString(context2d.direction())));

            int strokeStyleIndex;
            if (auto canvasGradient = state.strokeStyle.canvasGradient())
                strokeStyleIndex = indexForData(canvasGradient);
            else if (auto canvasPattern = state.strokeStyle.canvasPattern())
                strokeStyleIndex = indexForData(canvasPattern);
            else
                strokeStyleIndex = indexForData(state.strokeStyle.color());
            statePayload->setInteger(stringIndexForKey("strokeStyle"_s), strokeStyleIndex);

            int fillStyleIndex;
            if (auto canvasGradient = state.fillStyle.canvasGradient())
                fillStyleIndex = indexForData(canvasGradient);
            else if (auto canvasPattern = state.fillStyle.canvasPattern())
                fillStyleIndex = indexForData(canvasPattern);
            else
                fillStyleIndex = indexForData(state.fillStyle.color());
            statePayload->setInteger(stringIndexForKey("fillStyle"_s), fillStyleIndex);

            statePayload->setBoolean(stringIndexForKey("imageSmoothingEnabled"_s), context2d.imageSmoothingEnabled());
            statePayload->setInteger(stringIndexForKey("imageSmoothingQuality"_s), indexForData(convertEnumerationToString(context2d.imageSmoothingQuality())));

            auto setPath = JSON::ArrayOf<JSON::Value>::create();
            setPath->addItem(indexForData(buildStringFromPath(context2d.getPath()->path())));
            statePayload->setArray(stringIndexForKey("setPath"_s), WTFMove(setPath));

            statesPayload->addItem(WTFMove(statePayload));
        }
    }
#if ENABLE(WEBGL)
    else if (is<WebGLRenderingContextBase>(context)) {
        auto& contextWebGLBase = downcast<WebGLRenderingContextBase>(*context);
        if (Optional<WebGLContextAttributes> webGLContextAttributes = contextWebGLBase.getContextAttributes()) {
            auto webGLContextAttributesPayload = JSON::Object::create();
            webGLContextAttributesPayload->setBoolean("alpha"_s, webGLContextAttributes->alpha);
            webGLContextAttributesPayload->setBoolean("depth"_s, webGLContextAttributes->depth);
            webGLContextAttributesPayload->setBoolean("stencil"_s, webGLContextAttributes->stencil);
            webGLContextAttributesPayload->setBoolean("antialias"_s, webGLContextAttributes->antialias);
            webGLContextAttributesPayload->setBoolean("premultipliedAlpha"_s, webGLContextAttributes->premultipliedAlpha);
            webGLContextAttributesPayload->setBoolean("preserveDrawingBuffer"_s, webGLContextAttributes->preserveDrawingBuffer);
            webGLContextAttributesPayload->setBoolean("failIfMajorPerformanceCaveat"_s, webGLContextAttributes->failIfMajorPerformanceCaveat);
            parametersPayload->addItem(WTFMove(webGLContextAttributesPayload));
        }
    }
#endif

    initialStatePayload->setAttributes(WTFMove(attributesPayload));

    if (statesPayload->length())
        initialStatePayload->setStates(WTFMove(statesPayload));

    if (parametersPayload->length())
        initialStatePayload->setParameters(WTFMove(parametersPayload));

    ErrorString ignored;
    initialStatePayload->setContent(getCanvasContentAsDataURL(ignored));

    return initialStatePayload;
}

Ref<JSON::ArrayOf<JSON::Value>> InspectorCanvas::buildAction(const String& name, std::initializer_list<RecordCanvasActionVariant>&& parameters)
{
    auto action = JSON::ArrayOf<JSON::Value>::create();
    action->addItem(indexForData(name));

    auto parametersData = JSON::ArrayOf<JSON::Value>::create();
    auto swizzleTypes = JSON::ArrayOf<int>::create();

    auto addParameter = [&parametersData, &swizzleTypes] (auto value, RecordingSwizzleTypes swizzleType) {
        parametersData->addItem(value);
        swizzleTypes->addItem(static_cast<int>(swizzleType));
    };

    // Declared before it's initialized so it can be used recursively.
    Function<void(const RecordCanvasActionVariant&)> parseParameter;
    parseParameter = [&] (const auto& parameter) {
        WTF::switchOn(parameter,
            [&] (CanvasDirection value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (CanvasFillRule value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (CanvasLineCap value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (CanvasLineJoin value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (CanvasTextAlign value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (CanvasTextBaseline value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (ImageSmoothingQuality value) { addParameter(indexForData(convertEnumerationToString(value)), RecordingSwizzleTypes::String); },
            [&] (const DOMMatrix2DInit& value) {
                auto array = JSON::ArrayOf<double>::create();
                array->addItem(value.a.valueOr(1));
                array->addItem(value.b.valueOr(0));
                array->addItem(value.c.valueOr(0));
                array->addItem(value.d.valueOr(1));
                array->addItem(value.e.valueOr(0));
                array->addItem(value.f.valueOr(0));
                addParameter(array.ptr(), RecordingSwizzleTypes::DOMMatrix);
            },
            [&] (const Element* value) {
                if (value) {
                    // Elements are not serializable, so add a string as a placeholder since the actual
                    // element cannot be reconstructed in the frontend.
                    addParameter(indexForData("Element"), RecordingSwizzleTypes::None);
                }
            },
            [&] (HTMLImageElement* value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::Image); },
            [&] (ImageBitmap* value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::ImageBitmap); },
            [&] (ImageData* value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::ImageData); },
            [&] (const Path2D* value) {
                if (value)
                    addParameter(indexForData(buildStringFromPath(value->path())), RecordingSwizzleTypes::Path2D); },
#if ENABLE(WEBGL)
            // FIXME: <https://webkit.org/b/176009> Web Inspector: send data for WebGL objects during a recording instead of a placeholder string
            [&] (const WebGLBuffer* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLBuffer);
            },
            [&] (const WebGLFramebuffer* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLFramebuffer);
            },
            [&] (const WebGLProgram* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLProgram);
            },
            [&] (const WebGLQuery* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLQuery);
            },
            [&] (const WebGLRenderbuffer* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLRenderbuffer);
            },
            [&] (const WebGLSampler* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLSampler);
            },
            [&] (const WebGLShader* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLShader);
            },
            [&] (const WebGLSync* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLSync);
            },
            [&] (const WebGLTexture* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLTexture);
            },
            [&] (const WebGLTransformFeedback* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLTransformFeedback);
            },
            [&] (const WebGLUniformLocation* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLUniformLocation);
            },
            [&] (const WebGLVertexArrayObject* value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::WebGLVertexArrayObject);
            },
#endif
            [&] (const RefPtr<ArrayBuffer>& value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::TypedArray);
            },
            [&] (const RefPtr<ArrayBufferView>& value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::TypedArray);
            },
            [&] (const RefPtr<CanvasGradient>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::CanvasGradient);
            },
            [&] (const RefPtr<CanvasPattern>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::CanvasPattern);
            },
            [&] (const RefPtr<Float32Array>& value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::TypedArray);
            },
            [&] (const RefPtr<HTMLCanvasElement>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::Image);
            },
            [&] (const RefPtr<HTMLImageElement>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::Image);
            },
#if ENABLE(VIDEO)
            [&] (const RefPtr<HTMLVideoElement>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::Image);
            },
#endif
#if ENABLE(CSS_TYPED_OM)
            [&] (const RefPtr<TypedOMCSSImageValue>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::Image);
            },
#endif
            [&] (const RefPtr<ImageBitmap>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::ImageBitmap);
            },
            [&] (const RefPtr<ImageData>& value) {
                if (value)
                    addParameter(indexForData(value), RecordingSwizzleTypes::ImageData);
            },
            [&] (const RefPtr<Int32Array>& value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::TypedArray);
            },
            [&] (const RefPtr<Uint32Array>& value) {
                if (value)
                    addParameter(0, RecordingSwizzleTypes::TypedArray);
            },
            [&] (const CanvasImageSource& value) {
                WTF::visit(parseParameter, value);
            },
            [&] (const CanvasRenderingContext2DBase::Style& value) {
                WTF::visit(parseParameter, value);
            },
#if ENABLE(WEBGL)
            [&] (const WebGLRenderingContextBase::BufferDataSource& value) {
                WTF::visit(parseParameter, value);
            },
            [&] (const Optional<WebGLRenderingContextBase::BufferDataSource>& value) {
                if (value)
                    parseParameter(value.value());
            },
            [&] (const WebGLRenderingContextBase::TexImageSource& value) {
                WTF::visit(parseParameter, value);
            },
            [&] (const Optional<WebGLRenderingContextBase::TexImageSource>& value) {
                if (value)
                    parseParameter(value.value());
            },
#endif
            [&] (const Vector<String>& value) {
                auto deduplicated = value.map([&] (const String& item) {
                    return indexForData(item);
                });
                addParameter(buildArrayForVector(deduplicated).ptr(), RecordingSwizzleTypes::String);
            },
            [&] (const Vector<float>& value) { addParameter(buildArrayForVector(value).ptr(), RecordingSwizzleTypes::Array); },
            [&] (const Vector<uint32_t>& value) {
                auto mapped = value.map([&] (uint32_t item) {
                    return static_cast<double>(item);
                });
                addParameter(buildArrayForVector(mapped).ptr(), RecordingSwizzleTypes::Array);
            },
            [&] (const Vector<int32_t>& value) { addParameter(buildArrayForVector(value).ptr(), RecordingSwizzleTypes::Array); },
#if ENABLE(WEBGL)
            [&] (const WebGLRenderingContextBase::Float32List::VariantType& value) {
                WTF::visit(parseParameter, value);
            },
            [&] (const WebGLRenderingContextBase::Int32List::VariantType& value) {
                WTF::visit(parseParameter, value);
            },
#endif
#if ENABLE(WEBGL2)
            [&] (const WebGL2RenderingContext::Uint32List::VariantType& value) {
                WTF::visit(parseParameter, value);
            },
#endif
            [&] (const String& value) { addParameter(indexForData(value), RecordingSwizzleTypes::String); },
            [&] (double value) { addParameter(value, RecordingSwizzleTypes::Number); },
            [&] (float value) { addParameter(value, RecordingSwizzleTypes::Number); },
            [&] (const Optional<float>& value) {
                if (value)
                    parseParameter(value.value());
            },
            [&] (uint64_t value) { addParameter(static_cast<double>(value), RecordingSwizzleTypes::Number); },
            [&] (int64_t value) { addParameter(static_cast<double>(value), RecordingSwizzleTypes::Number); },
            [&] (uint32_t value) { addParameter(static_cast<double>(value), RecordingSwizzleTypes::Number); },
            [&] (int32_t value) { addParameter(value, RecordingSwizzleTypes::Number); },
            [&] (uint8_t value) { addParameter(static_cast<int>(value), RecordingSwizzleTypes::Number); },
            [&] (bool value) { addParameter(value, RecordingSwizzleTypes::Boolean); }
        );
    };
    for (auto& parameter : parameters)
        parseParameter(parameter);

    action->addItem(WTFMove(parametersData));
    action->addItem(WTFMove(swizzleTypes));

    auto trace = Inspector::createScriptCallStack(JSExecState::currentState(), Inspector::ScriptCallStack::maxCallStackSizeToCapture);
    action->addItem(indexForData(trace.ptr()));

    return action;
}

Ref<JSON::ArrayOf<JSON::Value>> InspectorCanvas::buildArrayForCanvasGradient(const CanvasGradient& canvasGradient)
{
    const auto& gradient = canvasGradient.gradient();
    
    String type = gradient.type() == Gradient::Type::Radial ? "radial-gradient"_s : gradient.type() == Gradient::Type::Linear ? "linear-gradient"_s : "conic-gradient"_s;

    auto parameters = JSON::ArrayOf<float>::create();
    WTF::switchOn(gradient.data(),
        [&parameters] (const Gradient::LinearData& data) {
            parameters->addItem(data.point0.x());
            parameters->addItem(data.point0.y());
            parameters->addItem(data.point1.x());
            parameters->addItem(data.point1.y());
        },
        [&parameters] (const Gradient::RadialData& data) {
            parameters->addItem(data.point0.x());
            parameters->addItem(data.point0.y());
            parameters->addItem(data.startRadius);
            parameters->addItem(data.point1.x());
            parameters->addItem(data.point1.y());
            parameters->addItem(data.endRadius);
        },
        [&parameters] (const Gradient::ConicData& data) {
            parameters->addItem(data.point0.x());
            parameters->addItem(data.point0.y());
            parameters->addItem(data.angleRadians);
        }
    );

    auto stops = JSON::ArrayOf<JSON::Value>::create();
    for (auto& colorStop : gradient.stops()) {
        auto stop = JSON::ArrayOf<JSON::Value>::create();
        stop->addItem(colorStop.offset);
        stop->addItem(indexForData(colorStop.color.cssText()));
        stops->addItem(WTFMove(stop));
    }

    auto array = JSON::ArrayOf<JSON::Value>::create();
    array->addItem(indexForData(type));
    array->addItem(WTFMove(parameters));
    array->addItem(WTFMove(stops));
    return array;
}

Ref<JSON::ArrayOf<JSON::Value>> InspectorCanvas::buildArrayForCanvasPattern(const CanvasPattern& canvasPattern)
{
    Image& tileImage = canvasPattern.pattern().tileImage();
    auto imageBuffer = ImageBuffer::create(tileImage.size(), RenderingMode::Unaccelerated);
    imageBuffer->context().drawImage(tileImage, FloatPoint(0, 0));

    String repeat;
    bool repeatX = canvasPattern.pattern().repeatX();
    bool repeatY = canvasPattern.pattern().repeatY();
    if (repeatX && repeatY)
        repeat = "repeat"_s;
    else if (repeatX && !repeatY)
        repeat = "repeat-x"_s;
    else if (!repeatX && repeatY)
        repeat = "repeat-y"_s;
    else
        repeat = "no-repeat"_s;

    auto array = JSON::ArrayOf<JSON::Value>::create();
    array->addItem(indexForData(imageBuffer->toDataURL("image/png")));
    array->addItem(indexForData(repeat));
    return array;
}

Ref<JSON::ArrayOf<JSON::Value>> InspectorCanvas::buildArrayForImageData(const ImageData& imageData)
{
    auto data = JSON::ArrayOf<int>::create();
    for (size_t i = 0; i < imageData.data()->length(); ++i)
        data->addItem(imageData.data()->item(i));

    auto array = JSON::ArrayOf<JSON::Value>::create();
    array->addItem(WTFMove(data));
    array->addItem(imageData.width());
    array->addItem(imageData.height());
    return array;
}

} // namespace WebCore

