/*
 * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
 */

WI.Recording = class Recording extends WI.Object
{
    constructor(version, type, initialState, frames, data)
    {
        super();

        this._version = version;
        this._type = type;
        this._initialState = initialState;
        this._frames = frames;
        this._data = data;
        this._displayName = WI.UIString("Recording");

        this._swizzle = null;
        this._actions = [new WI.RecordingInitialStateAction].concat(...this._frames.map((frame) => frame.actions));
        this._visualActionIndexes = [];
        this._source = null;

        this._processContext = null;
        this._processStates = [];
        this._processing = false;
    }

    static fromPayload(payload, frames)
    {
        if (typeof payload !== "object" || payload === null)
            return null;

        if (typeof payload.version !== "number") {
            WI.Recording.synthesizeError(WI.UIString("non-number %s").format(WI.unlocalizedString("version")));
            return null;
        }

        if (payload.version < 1 || payload.version > WI.Recording.Version) {
            WI.Recording.synthesizeError(WI.UIString("unsupported %s").format(WI.unlocalizedString("version")));
            return null;
        }

        if (parseInt(payload.version) !== payload.version) {
            WI.Recording.synthesizeWarning(WI.UIString("non-integer %s").format(WI.unlocalizedString("version")));
            payload.version = parseInt(payload.version);
        }

        let type = null;
        switch (payload.type) {
        case InspectorBackend.Enum.Recording.Type.Canvas2D:
            type = WI.Recording.Type.Canvas2D;
            break;
        case InspectorBackend.Enum.Recording.Type.CanvasBitmapRenderer:
            type = WI.Recording.Type.CanvasBitmapRenderer;
            break;
        case InspectorBackend.Enum.Recording.Type.CanvasWebGL:
            type = WI.Recording.Type.CanvasWebGL;
            break;
        case InspectorBackend.Enum.Recording.Type.CanvasWebGL2:
            type = WI.Recording.Type.CanvasWebGL2;
            break;
        default:
            WI.Recording.synthesizeWarning(WI.UIString("unknown %s \u0022%s\u0022").format(WI.unlocalizedString("type"), payload.type));
            type = String(payload.type);
            break;
        }

        if (typeof payload.initialState !== "object" || payload.initialState === null) {
            if ("initialState" in payload)
                WI.Recording.synthesizeWarning(WI.UIString("non-object %s").format(WI.unlocalizedString("initialState")));

            payload.initialState = {};
        }

        if (typeof payload.initialState.attributes !== "object" || payload.initialState.attributes === null) {
            if ("attributes" in payload.initialState)
                WI.Recording.synthesizeWarning(WI.UIString("non-object %s").format(WI.unlocalizedString("initialState.attributes")));

            payload.initialState.attributes = {};
        }

        if (!Array.isArray(payload.initialState.states) || payload.initialState.states.some((item) => typeof item !== "object" || item === null)) {
            if ("states" in payload.initialState)
                WI.Recording.synthesizeWarning(WI.UIString("non-array %s").format(WI.unlocalizedString("initialState.states")));

            payload.initialState.states = [];

            // COMPATIBILITY (iOS 12.0): Recording.InitialState.states did not exist yet
            if (!isEmptyObject(payload.initialState.attributes)) {
                let {width, height, ...state} = payload.initialState.attributes;
                if (!isEmptyObject(state))
                    payload.initialState.states.push(state);
            }
        }

        if (!Array.isArray(payload.initialState.parameters)) {
            if ("parameters" in payload.initialState)
                WI.Recording.synthesizeWarning(WI.UIString("non-array %s").format(WI.unlocalizedString("initialState.attributes")));

            payload.initialState.parameters = [];
        }

        if (typeof payload.initialState.content !== "string") {
            if ("content" in payload.initialState)
                WI.Recording.synthesizeWarning(WI.UIString("non-string %s").format(WI.unlocalizedString("initialState.content")));

            payload.initialState.content = "";
        }

        if (!Array.isArray(payload.frames)) {
            if ("frames" in payload)
                WI.Recording.synthesizeWarning(WI.UIString("non-array %s").format(WI.unlocalizedString("frames")));

            payload.frames = [];
        }

        if (!Array.isArray(payload.data)) {
            if ("data" in payload)
                WI.Recording.synthesizeWarning(WI.UIString("non-array %s").format(WI.unlocalizedString("data")));

            payload.data = [];
        }

        if (!frames)
            frames = payload.frames.map(WI.RecordingFrame.fromPayload)

        return new WI.Recording(payload.version, type, payload.initialState, frames, payload.data);
    }

    static displayNameForRecordingType(recordingType)
    {
        switch (recordingType) {
        case Recording.Type.Canvas2D:
            return WI.UIString("2D");
        case Recording.Type.CanvasBitmapRenderer:
            return WI.UIString("Bitmap Renderer", "Recording Type Canvas Bitmap Renderer", "A type of canvas recording in the Graphics Tab");
        case Recording.Type.CanvasWebGL:
            return WI.unlocalizedString("WebGL");
        case Recording.Type.CanvasWebGL2:
            return WI.unlocalizedString("WebGL2");
        }

        console.assert(false, "Unknown recording type", recordingType);
        return null;
    }

    static displayNameForSwizzleType(swizzleType)
    {
        switch (swizzleType) {
        case WI.Recording.Swizzle.None:
            return WI.unlocalizedString("None");
        case WI.Recording.Swizzle.Number:
            return WI.unlocalizedString("Number");
        case WI.Recording.Swizzle.Boolean:
            return WI.unlocalizedString("Boolean");
        case WI.Recording.Swizzle.String:
            return WI.unlocalizedString("String");
        case WI.Recording.Swizzle.Array:
            return WI.unlocalizedString("Array");
        case WI.Recording.Swizzle.TypedArray:
            return WI.unlocalizedString("TypedArray");
        case WI.Recording.Swizzle.Image:
            return WI.unlocalizedString("Image");
        case WI.Recording.Swizzle.ImageData:
            return WI.unlocalizedString("ImageData");
        case WI.Recording.Swizzle.DOMMatrix:
            return WI.unlocalizedString("DOMMatrix");
        case WI.Recording.Swizzle.Path2D:
            return WI.unlocalizedString("Path2D");
        case WI.Recording.Swizzle.CanvasGradient:
            return WI.unlocalizedString("CanvasGradient");
        case WI.Recording.Swizzle.CanvasPattern:
            return WI.unlocalizedString("CanvasPattern");
        case WI.Recording.Swizzle.WebGLBuffer:
            return WI.unlocalizedString("WebGLBuffer");
        case WI.Recording.Swizzle.WebGLFramebuffer:
            return WI.unlocalizedString("WebGLFramebuffer");
        case WI.Recording.Swizzle.WebGLRenderbuffer:
            return WI.unlocalizedString("WebGLRenderbuffer");
        case WI.Recording.Swizzle.WebGLTexture:
            return WI.unlocalizedString("WebGLTexture");
        case WI.Recording.Swizzle.WebGLShader:
            return WI.unlocalizedString("WebGLShader");
        case WI.Recording.Swizzle.WebGLProgram:
            return WI.unlocalizedString("WebGLProgram");
        case WI.Recording.Swizzle.WebGLUniformLocation:
            return WI.unlocalizedString("WebGLUniformLocation");
        case WI.Recording.Swizzle.ImageBitmap:
            return WI.unlocalizedString("ImageBitmap");
        case WI.Recording.Swizzle.WebGLQuery:
            return WI.unlocalizedString("WebGLQuery");
        case WI.Recording.Swizzle.WebGLSampler:
            return WI.unlocalizedString("WebGLSampler");
        case WI.Recording.Swizzle.WebGLSync:
            return WI.unlocalizedString("WebGLSync");
        case WI.Recording.Swizzle.WebGLTransformFeedback:
            return WI.unlocalizedString("WebGLTransformFeedback");
        case WI.Recording.Swizzle.WebGLVertexArrayObject:
            return WI.unlocalizedString("WebGLVertexArrayObject");
        default:
            console.error("Unknown swizzle type", swizzleType);
            return null;
        }
    }

    static synthesizeWarning(message)
    {
        message = WI.UIString("Recording Warning: %s").format(message);

        if (window.InspectorTest) {
            console.warn(message);
            return;
        }

        let consoleMessage = new WI.ConsoleMessage(WI.mainTarget, WI.ConsoleMessage.MessageSource.Other, WI.ConsoleMessage.MessageLevel.Warning, message);
        consoleMessage.shouldRevealConsole = true;

        WI.consoleLogViewController.appendConsoleMessage(consoleMessage);
    }

    static synthesizeError(message)
    {
        message = WI.UIString("Recording Error: %s").format(message);

        if (window.InspectorTest) {
            console.error(message);
            return;
        }

        let consoleMessage = new WI.ConsoleMessage(WI.mainTarget, WI.ConsoleMessage.MessageSource.Other, WI.ConsoleMessage.MessageLevel.Error, message);
        consoleMessage.shouldRevealConsole = true;

        WI.consoleLogViewController.appendConsoleMessage(consoleMessage);
    }

    // Public

    get displayName() { return this._displayName; }
    get type() { return this._type; }
    get initialState() { return this._initialState; }
    get frames() { return this._frames; }
    get data() { return this._data; }
    get actions() { return this._actions; }
    get visualActionIndexes() { return this._visualActionIndexes; }

    get source() { return this._source; }
    set source(source) { this._source = source; }

    get processing() { return this._processing; }

    get ready()
    {
        return this._actions.lastValue.ready;
    }

    startProcessing()
    {
        console.assert(!this._processing, "Cannot start an already started process().");
        console.assert(!this.ready, "Cannot start a completed process().");
        if (this._processing || this.ready)
            return;

        this._processing = true;

        this._process();
    }

    stopProcessing()
    {
        console.assert(this._processing, "Cannot stop an already stopped process().");
        console.assert(!this.ready, "Cannot stop a completed process().");
        if (!this._processing || this.ready)
            return;

        this._processing = false;
    }

    createDisplayName(suggestedName)
    {
        let recordingNameSet;
        if (this._source) {
            recordingNameSet = this._source[WI.Recording.CanvasRecordingNamesSymbol];
            if (!recordingNameSet)
                this._source[WI.Recording.CanvasRecordingNamesSymbol] = recordingNameSet = new Set;
        } else
            recordingNameSet = WI.Recording._importedRecordingNameSet;

        let name;
        if (suggestedName) {
            name = suggestedName;
            let duplicateNumber = 2;
            while (recordingNameSet.has(name))
                name = `${suggestedName} (${duplicateNumber++})`;
        } else {
            let recordingNumber = 1;
            do {
                name = WI.UIString("Recording %d").format(recordingNumber++);
            } while (recordingNameSet.has(name));
        }

        recordingNameSet.add(name);
        this._displayName = name;
    }

    async swizzle(index, type)
    {
        if (!this._swizzle)
            this._swizzle = {};

        if (typeof this._swizzle[index] !== "object")
            this._swizzle[index] = {};

        if (type === WI.Recording.Swizzle.Number)
            return parseFloat(index);

        if (type === WI.Recording.Swizzle.Boolean)
            return !!index;

        if (type === WI.Recording.Swizzle.Array)
            return Array.isArray(index) ? index : [];

        if (type === WI.Recording.Swizzle.DOMMatrix)
            return new DOMMatrix(index);

        // FIXME: <https://webkit.org/b/176009> Web Inspector: send data for WebGL objects during a recording instead of a placeholder string
        if (type === WI.Recording.Swizzle.TypedArray
            || type === WI.Recording.Swizzle.WebGLBuffer
            || type === WI.Recording.Swizzle.WebGLFramebuffer
            || type === WI.Recording.Swizzle.WebGLRenderbuffer
            || type === WI.Recording.Swizzle.WebGLTexture
            || type === WI.Recording.Swizzle.WebGLShader
            || type === WI.Recording.Swizzle.WebGLProgram
            || type === WI.Recording.Swizzle.WebGLUniformLocation
            || type === WI.Recording.Swizzle.WebGLQuery
            || type === WI.Recording.Swizzle.WebGLSampler
            || type === WI.Recording.Swizzle.WebGLSync
            || type === WI.Recording.Swizzle.WebGLTransformFeedback
            || type === WI.Recording.Swizzle.WebGLVertexArrayObject) {
            return index;
        }

        if (!(type in this._swizzle[index])) {
            try {
                let data = this._data[index];
                switch (type) {
                case WI.Recording.Swizzle.None:
                    this._swizzle[index][type] = data;
                    break;

                case WI.Recording.Swizzle.String:
                    if (Array.isArray(data))
                        this._swizzle[index][type] = await Promise.all(data.map((item) => this.swizzle(item, WI.Recording.Swizzle.String)));
                    else
                        this._swizzle[index][type] = String(data);
                    break;

                case WI.Recording.Swizzle.Image:
                    this._swizzle[index][type] = await WI.ImageUtilities.promisifyLoad(data);
                    this._swizzle[index][type].__data = data;
                    break;

                case WI.Recording.Swizzle.ImageData: {
                    let [object, width, height] = await Promise.all([
                        this.swizzle(data[0], WI.Recording.Swizzle.Array),
                        this.swizzle(data[1], WI.Recording.Swizzle.Number),
                        this.swizzle(data[2], WI.Recording.Swizzle.Number),
                    ]);

                    object = await Promise.all(object.map((item) => this.swizzle(item, WI.Recording.Swizzle.Number)));

                    this._swizzle[index][type] = new ImageData(new Uint8ClampedArray(object), width, height);
                    this._swizzle[index][type].__data = {data: object, width, height};
                    break;
                }

                case WI.Recording.Swizzle.Path2D:
                    this._swizzle[index][type] = new Path2D(data);
                    this._swizzle[index][type].__data = data;
                    break;

                case WI.Recording.Swizzle.CanvasGradient: {
                    let [gradientType, points] = await Promise.all([
                        this.swizzle(data[0], WI.Recording.Swizzle.String),
                        this.swizzle(data[1], WI.Recording.Swizzle.Array),
                    ]);

                    points = await Promise.all(points.map((item) => this.swizzle(item, WI.Recording.Swizzle.Number)));

                    WI.ImageUtilities.scratchCanvasContext2D((context) => {
                        this._swizzle[index][type] = gradientType === "radial-gradient" ? context.createRadialGradient(...points) : context.createLinearGradient(...points);
                    });

                    let stops = [];
                    for (let stop of data[2]) {
                        let [offset, color] = await Promise.all([
                            this.swizzle(stop[0], WI.Recording.Swizzle.Number),
                            this.swizzle(stop[1], WI.Recording.Swizzle.String),
                        ]);
                        this._swizzle[index][type].addColorStop(offset, color);

                        stops.push({offset, color});
                    }

                    this._swizzle[index][type].__data = {type: gradientType, points, stops};
                    break;
                }

                case WI.Recording.Swizzle.CanvasPattern: {
                    let [image, repeat] = await Promise.all([
                        this.swizzle(data[0], WI.Recording.Swizzle.Image),
                        this.swizzle(data[1], WI.Recording.Swizzle.String),
                    ]);

                    WI.ImageUtilities.scratchCanvasContext2D((context) => {
                        this._swizzle[index][type] = context.createPattern(image, repeat);
                        this._swizzle[index][type].__image = image;
                    });

                    this._swizzle[index][type].__data = {image: image.__data, repeat};
                    break;
                }

                case WI.Recording.Swizzle.ImageBitmap: {
                    let image = await this.swizzle(index, WI.Recording.Swizzle.Image);
                    this._swizzle[index][type] = await createImageBitmap(image);
                    this._swizzle[index][type].__data = data;
                    break;
                }

                case WI.Recording.Swizzle.CallStack: {
                    let array = await this.swizzle(data, WI.Recording.Swizzle.Array);
                    this._swizzle[index][type] = await Promise.all(array.map((item) => this.swizzle(item, WI.Recording.Swizzle.CallFrame)));
                    break;
                }

                case WI.Recording.Swizzle.CallFrame: {
                    let array = await this.swizzle(data, WI.Recording.Swizzle.Array);
                    let [functionName, url] = await Promise.all([
                        this.swizzle(array[0], WI.Recording.Swizzle.String),
                        this.swizzle(array[1], WI.Recording.Swizzle.String),
                    ]);
                    this._swizzle[index][type] = WI.CallFrame.fromPayload(WI.assumingMainTarget(), {
                        functionName,
                        url,
                        lineNumber: array[2],
                        columnNumber: array[3],
                    });
                    break;
                }
                }
            } catch { }
        }

        return this._swizzle[index][type];
    }

    createContext()
    {
        let createCanvasContext = (type) => {
            let canvas = document.createElement("canvas");
            if ("width" in this._initialState.attributes)
                canvas.width = this._initialState.attributes.width;
            if ("height" in this._initialState.attributes)
                canvas.height = this._initialState.attributes.height;
            return canvas.getContext(type, ...this._initialState.parameters);
        };

        if (this._type === WI.Recording.Type.Canvas2D)
            return createCanvasContext("2d");

        if (this._type === WI.Recording.Type.CanvasBitmapRenderer)
            return createCanvasContext("bitmaprenderer");

        if (this._type === WI.Recording.Type.CanvasWebGL)
            return createCanvasContext("webgl");

        if (this._type === WI.Recording.Type.CanvasWebGL2)
            return createCanvasContext("webgl2");

        console.error("Unknown recording type", this._type);
        return null;
    }

    toJSON()
    {
        let initialState = {};
        if (!isEmptyObject(this._initialState.attributes))
            initialState.attributes = this._initialState.attributes;
        if (this._initialState.states.length)
            initialState.states = this._initialState.states;
        if (this._initialState.parameters.length)
            initialState.parameters = this._initialState.parameters;
        if (this._initialState.content && this._initialState.content.length)
            initialState.content = this._initialState.content;

        return {
            version: this._version,
            type: this._type,
            initialState,
            frames: this._frames.map((frame) => frame.toJSON()),
            data: this._data,
        };
    }

    toHTML()
    {
        console.assert(this._type === WI.Recording.Type.Canvas2D);
        console.assert(this.ready);

        let lines = [];
        let objects = [];

        function processObject(object) {
            objects.push({object, index: objects.length});
            return `objects[${objects.length - 1}]`;
        }

        function processValue(value) {
            if (typeof value === "object" && !Array.isArray(value))
                return processObject(value);
            return JSON.stringify(value);
        }

        function escapeHTML(s) {
            return s.replace(/[^0-9A-Za-z ]/g, (c) => {
                return `&#${c.charCodeAt(0)};`;
            });
        }

        lines.push(`<!DOCTYPE html>`);
        lines.push(`<head>`);
        lines.push(`<title>${escapeHTML(this._displayName)}</title>`);
        lines.push(`<style>`);
        lines.push(`    body {`);
        lines.push(`        margin: 0;`);
        lines.push(`    }`);
        lines.push(`    canvas {`);
        lines.push(`        max-width: calc(100% - 40px);`);
        lines.push(`        max-height: calc(100% - 40px);`);
        lines.push(`        padding: 20px;`);
        lines.push(`    }`);
        lines.push(`</style>`);
        lines.push(`</head>`);
        lines.push(`<body>`);
        lines.push(`<script>`);
        lines.push(`"use strict";`);

        lines.push(``);

        lines.push(`let promises = [];`);
        lines.push(`let objects = {};`);

        lines.push(``);

        lines.push(`let canvas = document.body.appendChild(document.createElement("canvas"));`);
        for (let [attribute, value] of Object.entries(this._initialState.attributes))
            lines.push(`canvas.${attribute} = ${JSON.stringify(value)};`);

        lines.push(``);

        let parametersString = this._initialState.parameters.map(processValue).join(`, `);
        lines.push(`let context = canvas.getContext("2d"${parametersString ? ", " + parametersString : ""});`);

        lines.push(``);

        lines.push(`let frames = [`);

        lines.push(`    function initialState() {`);
        if (this._initialState.content) {
            let image = new Image;
            image.__data = this._initialState.content;
            lines.push(`        context.drawImage(${processObject(image)}, 0, 0);`);
            lines.push(``);
        }
        for (let state of this._actions[0].states) {
            for (let [name, value] of state) {
                if (name === "getPath" || name === "currentX" || name === "currentY")
                    continue;

                let contextString = `context`;
                if (name === "setPath") {
                    lines.push(`        if (${JSON.stringify(name)} in context)`);
                    contextString = `    ` + contextString;
                }

                let callString = ``;
                if (WI.RecordingAction.isFunctionForType(this._type, name))
                    callString = `(` + value.map(processValue).join(`, `) + `)`;
                else
                    callString = ` = ${processValue(value)}`;

                lines.push(`        ${contextString}.${name}${callString};`);
            }

            if (state !== this._actions[0].states.lastValue) {
                lines.push(`        context.save();`);
                lines.push(``);
            }
        }
        lines.push(`    },`);

        lines.push(`    function startRecording() {`);
        lines.push(`        if (typeof console.record === "function")`);
        lines.push(`            console.record(context, {name: ${JSON.stringify(this._displayName)}});`);
        lines.push(`    },`);

        for (let i = 0; i < this._frames.length; ++i) {
            lines.push(`    function frame${i + 1}() {`);

            for (let action of this._frames[i].actions) {
                let contextString = `context`;
                if (action.contextReplacer)
                    contextString += `.${action.contextReplacer}`;

                if (!action.valid)
                    contextString = `// ` + contextString;

                let callString = ``;
                if (action.isFunction)
                    callString += `(` + action.parameters.map(processValue).join(`, `) + `)`;
                else if (!action.isGetter)
                    callString += ` = ` + processValue(action.parameters[0]);

                lines.push(`        ${contextString}.${action.name}${callString};`);
            }

            lines.push(`    },`);
        }

        lines.push(`    function stopRecording() {`);
        lines.push(`        if (typeof console.recordEnd === "function")`);
        lines.push(`            console.recordEnd(context);`);
        lines.push(`    },`);

        lines.push(`];`);

        lines.push(``);

        if (objects.length) {
            if (objects.some(({object}) => object instanceof CanvasGradient)) {
                lines.push(`function rebuildCanvasGradient(key, data) {`);
                lines.push(`    let gradient = null;`);
                lines.push(`    if (data.type === "radial-gradient")`);
                lines.push(`        gradient = context.createRadialGradient(data.points[0], data.points[1], data.points[2], data.points[3], data.points[4], data.points[5]);`);
                lines.push(`    else`);
                lines.push(`        gradient = context.createLinearGradient(data.points[0], data.points[1], data.points[2], data.points[3]);`);
                lines.push(`    for (let stop of data.stops)`);
                lines.push(`        gradient.addColorStop(stop.offset, stop.color);`);
                lines.push(`    objects[key] = gradient;`);
                lines.push(`}`);
            }

            if (objects.some(({object}) => object instanceof CanvasPattern)) {
                lines.push(`function rebuildCanvasPattern(key, data) {`);
                lines.push(`    promises.push(new Promise(function(resolve, reject) {`);
                lines.push(`        let image = new Image;`);
                lines.push(`        function resolveWithImage(event) {`);
                lines.push(`            objects[key] = context.createPattern(image, data.repeat);`);
                lines.push(`            resolve();`);
                lines.push(`        }`);
                lines.push(`        image.addEventListener("load", resolveWithImage);`);
                lines.push(`        image.addEventListener("error", resolveWithImage);`);
                lines.push(`        image.src = data.image;`);
                lines.push(`    }));`);
                lines.push(`}`);
            }

            if (objects.some(({object}) => object instanceof DOMMatrix)) {
                lines.push(`function rebuildDOMMatrix(key, data) {`);
                lines.push(`    objects[key] = new DOMMatrix(data);`);
                lines.push(`}`);
            }

            if (objects.some(({object}) => object instanceof Image)) {
                lines.push(`function rebuildImage(key, data) {`);
                lines.push(`    promises.push(new Promise(function(resolve, reject) {`);
                lines.push(`        let image = new Image;`);
                lines.push(`        function resolveWithImage(event) {`);
                lines.push(`            objects[key] = image;`);
                lines.push(`            resolve();`);
                lines.push(`        }`);
                lines.push(`        image.addEventListener("load", resolveWithImage);`);
                lines.push(`        image.addEventListener("error", resolveWithImage);`);
                lines.push(`        image.src = data;`);
                lines.push(`    }));`);
                lines.push(`}`);
            }

            if (objects.some(({object}) => object instanceof ImageBitmap)) {
                lines.push(`function rebuildImageBitmap(key, data) {`);
                lines.push(`    promises.push(new Promise(function(resolve, reject) {`);
                lines.push(`        let image = new Image;`);
                lines.push(`        function resolveWithImage(event) {`);
                lines.push(`            createImageBitmap(image).then(function(imageBitmap) {`);
                lines.push(`                objects[key] = imageBitmap;`);
                lines.push(`                resolve();`);
                lines.push(`            });`);
                lines.push(`        }`);
                lines.push(`        image.addEventListener("load", resolveWithImage);`);
                lines.push(`        image.addEventListener("error", resolveWithImage);`);
                lines.push(`        image.src = data;`);
                lines.push(`    }));`);
                lines.push(`}`);
            }

            if (objects.some(({object}) => object instanceof ImageData)) {
                lines.push(`function rebuildImageData(key, data) {`);
                lines.push(`    objects[key] = new ImageData(new Uint8ClampedArray(data.data), parseInt(data.width), parseInt(data.height));`);
                lines.push(`}`);
            }

            if (objects.some(({object}) => object instanceof Path2D)) {
                lines.push(`function rebuildPath2D(key, data) {`);
                lines.push(`    objects[key] = new Path2D(data);`);
                lines.push(`}`);
            }

            lines.push(``);

            for (let {object, index} of objects) {
                if (object instanceof CanvasGradient) {
                    lines.push(`rebuildCanvasGradient(${index}, ${JSON.stringify(object.__data)});`);
                    continue;
                }

                if (object instanceof CanvasPattern) {
                    lines.push(`rebuildCanvasPattern(${index}, ${JSON.stringify(object.__data)});`);
                    continue;
                }

                if (object instanceof DOMMatrix) {
                    lines.push(`rebuildDOMMatrix(${index}, ${JSON.stringify(object.toString())});`)
                    continue;
                }

                if (object instanceof Image) {
                    lines.push(`rebuildImage(${index}, ${JSON.stringify(object.__data)});`)
                    continue;
                }

                if (object instanceof ImageBitmap) {
                    lines.push(`rebuildImageBitmap(${index}, ${JSON.stringify(object.__data)});`)
                    continue;
                }

                if (object instanceof ImageData) {
                    lines.push(`rebuildImageData(${index}, ${JSON.stringify(object.__data)});`);
                    continue;
                }

                if (object instanceof Path2D) {
                    lines.push(`rebuildPath2D(${index}, ${JSON.stringify(object.__data || "")});`)
                    continue;
                }
            }

            lines.push(``);
        }

        lines.push(`Promise.all(promises).then(function() {`);
        lines.push(`    window.requestAnimationFrame(function executeFrame() {`);
        lines.push(`        frames.shift()();`);
        lines.push(`        if (frames.length)`);
        lines.push(`            window.requestAnimationFrame(executeFrame);`);
        lines.push(`    });`);
        lines.push(`});`);

        lines.push(`</script>`);
        lines.push(`</body>`);
        return lines.join(`\n`);
    }

    // Private

    async _process()
    {
        if (!this._processContext) {
            this._processContext = this.createContext();

            if (this._type === WI.Recording.Type.Canvas2D) {
                let initialContent = await WI.ImageUtilities.promisifyLoad(this._initialState.content);
                this._processContext.drawImage(initialContent, 0, 0);

                for (let initialState of this._initialState.states) {
                    let state = await WI.RecordingState.swizzleInitialState(this, initialState);
                    state.apply(this._type, this._processContext);

                    // The last state represents the current state, which should not be saved.
                    if (initialState !== this._initialState.states.lastValue) {
                        this._processContext.save();
                        this._processStates.push(WI.RecordingState.fromContext(this._type, this._processContext));
                    }
                }
            }
        }

        // The first action is always a WI.RecordingInitialStateAction, which doesn't need to swizzle().
        // Since it is not associated with a WI.RecordingFrame, it has to manually process().
        if (!this._actions[0].ready) {
            this._actions[0].process(this, this._processContext, this._processStates);
            this.dispatchEventToListeners(WI.Recording.Event.ProcessedAction, {action: this._actions[0], index: 0});
        }

        const workInterval = 10;
        let startTime = Date.now();

        let cumulativeActionIndex = 0;
        let lastAction = this._actions[cumulativeActionIndex];
        for (let frameIndex = 0; frameIndex < this._frames.length; ++frameIndex) {
            let frame = this._frames[frameIndex];

            if (frame.actions.lastValue.ready) {
                cumulativeActionIndex += frame.actions.length;
                lastAction = frame.actions.lastValue;
                continue;
            }

            for (let actionIndex = 0; actionIndex < frame.actions.length; ++actionIndex) {
                ++cumulativeActionIndex;

                let action = frame.actions[actionIndex];
                if (action.ready) {
                    lastAction = action;
                    continue;
                }

                await action.swizzle(this);

                action.process(this, this._processContext, this._processStates, {lastAction});

                if (action.isVisual)
                    this._visualActionIndexes.push(cumulativeActionIndex);

                if (!actionIndex)
                    this.dispatchEventToListeners(WI.Recording.Event.StartProcessingFrame, {frame, index: frameIndex});

                this.dispatchEventToListeners(WI.Recording.Event.ProcessedAction, {action, index: cumulativeActionIndex});

                if (Date.now() - startTime > workInterval) {
                    await Promise.delay(); // yield

                    startTime = Date.now();
                }

                lastAction = action;

                if (!this._processing)
                    return;
            }

            if (!this._processing)
                return;
        }

        this._swizzle = null;
        this._processContext = null;
        this._processing = false;
    }
};

// Keep this in sync with Inspector::Protocol::Recording::VERSION.
WI.Recording.Version = 1;

WI.Recording.Event = {
    ProcessedAction: "recording-processed-action",
    StartProcessingFrame: "recording-start-processing-frame",
};

WI.Recording._importedRecordingNameSet = new Set;

WI.Recording.CanvasRecordingNamesSymbol = Symbol("canvas-recording-names");

WI.Recording.Type = {
    Canvas2D: "canvas-2d",
    CanvasBitmapRenderer: "canvas-bitmaprenderer",
    CanvasWebGL: "canvas-webgl",
    CanvasWebGL2: "canvas-webgl2",
};

// Keep this in sync with WebCore::RecordingSwizzleTypes.
WI.Recording.Swizzle = {
    None: 0,
    Number: 1,
    Boolean: 2,
    String: 3,
    Array: 4,
    TypedArray: 5,
    Image: 6,
    ImageData: 7,
    DOMMatrix: 8,
    Path2D: 9,
    CanvasGradient: 10,
    CanvasPattern: 11,
    WebGLBuffer: 12,
    WebGLFramebuffer: 13,
    WebGLRenderbuffer: 14,
    WebGLTexture: 15,
    WebGLShader: 16,
    WebGLProgram: 17,
    WebGLUniformLocation: 18,
    ImageBitmap: 19,
    WebGLQuery: 20,
    WebGLSampler: 21,
    WebGLSync: 22,
    WebGLTransformFeedback: 23,
    WebGLVertexArrayObject: 24,

    // Special frontend-only swizzle types.
    CallStack: Symbol("CallStack"),
    CallFrame: Symbol("CallFrame"),
};
