15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
2591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Copyright (C) 2013 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
325d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * FIXME: ES5 strict mode check is suppressed due to multiple uses of arguments.callee.
335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @fileoverview
345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * @suppress {es5Strict}
355d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) */
365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)/**
38591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * @param {InjectedScriptHostClass} InjectedScriptHost
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {Window} inspectedWindow
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number} injectedScriptId
41591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * @param {!InjectedScript} injectedScript
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
43591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch(function (InjectedScriptHost, inspectedWindow, injectedScriptId, injectedScript) {
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var TypeUtils = {
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * http://www.khronos.org/registry/typedarray/specs/latest/#7
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @const
49f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @type {!Array.<function(new:ArrayBufferView, (!ArrayBuffer|!ArrayBufferView), number=, number=)>}
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _typedArrayClasses: (function(typeNames) {
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var result = [];
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = typeNames.length; i < n; ++i) {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (inspectedWindow[typeNames[i]])
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                result.push(inspectedWindow[typeNames[i]]);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    })(["Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "Float32Array", "Float64Array"]),
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
61926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @const
62926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @type {!Array.<string>}
63926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
64926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _supportedPropertyPrefixes: ["webkit"],
65926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
66926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {*} array
68f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {function(new:ArrayBufferView, (!ArrayBuffer|!ArrayBufferView), number=, number=)|null}
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    typedArrayClass: function(array)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var classes = TypeUtils._typedArrayClasses;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = classes.length; i < n; ++i) {
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (array instanceof classes[i])
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return classes[i];
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {*} obj
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {*}
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clone: function(obj)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!obj)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return obj;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var type = typeof obj;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (type !== "object" && type !== "function")
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return obj;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Handle Array and ArrayBuffer instances.
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (typeof obj.slice === "function") {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            console.assert(obj instanceof Array || obj instanceof ArrayBuffer);
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return obj.slice(0);
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var typedArrayClass = TypeUtils.typedArrayClass(obj);
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (typedArrayClass)
101f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            return new typedArrayClass(/** @type {!ArrayBufferView} */ (obj));
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (obj instanceof HTMLImageElement) {
104f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            var img = /** @type {!HTMLImageElement} */ (obj);
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            // Special case for Images with Blob URIs: cloneNode will fail if the Blob URI has already been revoked.
106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            // FIXME: Maybe this is a bug in WebKit core?
107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (/^blob:/.test(img.src))
108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return TypeUtils.cloneIntoCanvas(img);
109926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return img.cloneNode(true);
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (obj instanceof HTMLCanvasElement)
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return TypeUtils.cloneIntoCanvas(obj);
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (obj instanceof HTMLVideoElement)
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return TypeUtils.cloneIntoCanvas(obj, obj.videoWidth, obj.videoHeight);
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (obj instanceof ImageData) {
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var context = TypeUtils._dummyCanvas2dContext();
120926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            // FIXME: suppress type checks due to outdated builtin externs for createImageData.
121926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var result = (/** @type {?} */ (context)).createImageData(obj);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var i = 0, n = obj.data.length; i < n; ++i)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)              result.data[i] = obj.data[i];
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return result;
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // Try to convert to a primitive value via valueOf().
12851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (typeof obj.valueOf === "function") {
12951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            var value = obj.valueOf();
13051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            var valueType = typeof value;
13151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            if (valueType !== "object" && valueType !== "function")
13251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                return value;
13351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
13451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.error("ASSERT_NOT_REACHED: failed to clone object: ", obj);
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return obj;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
140f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!HTMLImageElement|!HTMLCanvasElement|!HTMLVideoElement} obj
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number=} width
142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number=} height
143f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!HTMLCanvasElement}
144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    cloneIntoCanvas: function(obj, width, height)
146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
147f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var canvas = /** @type {!HTMLCanvasElement} */ (inspectedWindow.document.createElement("canvas"));
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        canvas.width = width || +obj.width;
149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        canvas.height = height || +obj.height;
150f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var context = /** @type {!CanvasRenderingContext2D} */ (Resource.wrappedObject(canvas.getContext("2d")));
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        context.drawImage(obj, 0, 0);
152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return canvas;
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
154926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
155926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
156f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Object=} obj
157f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Object}
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    cloneObject: function(obj)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!obj)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return null;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var result = {};
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var key in obj)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            result[key] = obj[key];
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Array.<string>} names
171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Object.<string, boolean>}
172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    createPrefixedPropertyNamesSet: function(names)
174926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var result = Object.create(null);
176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var i = 0, name; name = names[i]; ++i) {
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            result[name] = true;
178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var suffix = name.substr(0, 1).toUpperCase() + name.substr(1);
179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (var j = 0, prefix; prefix = TypeUtils._supportedPropertyPrefixes[j]; ++j)
180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                result[prefix + suffix] = true;
181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return result;
183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
185926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {number}
1877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
1887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    now: function()
1897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
1907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        try {
1917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return inspectedWindow.performance.now();
1927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        } catch(e) {
1937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            try {
1947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                return Date.now();
1957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            } catch(ex) {
1967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            }
1977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
1987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return 0;
1997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
2007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
202e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string} property
203e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Object} obj
204e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {boolean}
205e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
206e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    isEnumPropertyName: function(property, obj)
207e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
208e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return (/^[A-Z][A-Z0-9_]+$/.test(property) && typeof obj[property] === "number");
209e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
210e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
211e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
212f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!CanvasRenderingContext2D}
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _dummyCanvas2dContext: function()
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var context = TypeUtils._dummyCanvas2dContextInstance;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!context) {
218f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            var canvas = /** @type {!HTMLCanvasElement} */ (inspectedWindow.document.createElement("canvas"));
219f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            context = /** @type {!CanvasRenderingContext2D} */ (Resource.wrappedObject(canvas.getContext("2d")));
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            TypeUtils._dummyCanvas2dContextInstance = context;
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return context;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
226f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)/** @typedef {{name:string, valueIsEnum:(boolean|undefined), value:*, values:(!Array.<!TypeUtils.InternalResourceStateDescriptor>|undefined), isArray:(boolean|undefined)}} */
2277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochTypeUtils.InternalResourceStateDescriptor;
2287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @interface
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function StackTrace()
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StackTrace.prototype = {
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} index
239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {{sourceURL: string, lineNumber: number, columnNumber: number}|undefined}
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    callFrame: function(index)
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number=} stackTraceLimit
248f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {?Function=} topMostFunctionToIgnore
249f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @return {?StackTrace}
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StackTrace.create = function(stackTraceLimit, topMostFunctionToIgnore)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof Error.captureStackTrace === "function")
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return new StackTraceV8(stackTraceLimit, topMostFunctionToIgnore || arguments.callee);
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Support JSC, and maybe other browsers.
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return null;
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @implements {StackTrace}
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {number=} stackTraceLimit
263f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {?Function=} topMostFunctionToIgnore
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @see http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function StackTraceV8(stackTraceLimit, topMostFunctionToIgnore)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var oldPrepareStackTrace = Error.prepareStackTrace;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var oldStackTraceLimit = Error.stackTraceLimit;
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof stackTraceLimit === "number")
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Error.stackTraceLimit = stackTraceLimit;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
274f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Object} error
275f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<!CallSite>} structuredStackTrace
276a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @return {!Array.<{sourceURL: string, lineNumber: number, columnNumber: number}>}
277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
278926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Error.prepareStackTrace = function(error, structuredStackTrace)
279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return structuredStackTrace.map(function(callSite) {
281926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return {
282926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                sourceURL: callSite.getFileName(),
283926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                lineNumber: callSite.getLineNumber(),
284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                columnNumber: callSite.getColumnNumber()
285926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            };
286926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        });
287926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
288926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
289a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    var holder = /** @type {{stack: !Array.<{sourceURL: string, lineNumber: number, columnNumber: number}>}} */ ({});
290926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Error.captureStackTrace(holder, topMostFunctionToIgnore || arguments.callee);
291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._stackTrace = holder.stack;
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Error.stackTraceLimit = oldStackTraceLimit;
294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Error.prepareStackTrace = oldPrepareStackTrace;
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StackTraceV8.prototype = {
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} index
301926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {{sourceURL: string, lineNumber: number, columnNumber: number}|undefined}
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    callFrame: function(index)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._stackTrace[index];
306f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    }
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
3117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * @template T
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Cache()
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.reset();
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Cache.prototype = {
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size: function()
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._size;
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    reset: function()
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        /** @type {!Object.<number, !T>} */
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._items = Object.create(null);
331926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        /** @type {number} */
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._size = 0;
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} key
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {boolean}
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    has: function(key)
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return key in this._items;
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} key
3467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {T|undefined}
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    get: function(key)
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._items[key];
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} key
3557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @param {!T} item
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    put: function(key, item)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this.has(key))
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++this._size;
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._items[key] = item;
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
367f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {?Resource|!Object} thisObject
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} functionName
369f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Array|!Arguments} args
370f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Resource|*=} result
371f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {?StackTrace=} stackTrace
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Call(thisObject, functionName, args, result, stackTrace)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._thisObject = thisObject;
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._functionName = functionName;
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._args = Array.prototype.slice.call(args, 0);
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._result = result;
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._stackTrace = stackTrace || null;
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!this._functionName)
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(this._args.length === 2 && typeof this._args[0] === "string");
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Call.prototype = {
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
387f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Resource}
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource: function()
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Resource.forObject(this._thisObject);
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {string}
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    functionName: function()
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._functionName;
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {boolean}
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    isPropertySetter: function()
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !this._functionName;
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
409197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Array}
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    args: function()
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._args;
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {*}
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result: function()
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._result;
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
427f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?StackTrace}
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stackTrace: function()
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._stackTrace;
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
435f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?StackTrace} stackTrace
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setStackTrace: function(stackTrace)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._stackTrace = stackTrace;
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {*} result
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setResult: function(result)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._result = result;
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} name
452f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Object} attachment
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setAttachment: function(name, attachment)
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (attachment) {
457f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            /** @type {?Object.<string, !Object>|undefined} */
458926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._attachments = this._attachments || Object.create(null);
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._attachments[name] = attachment;
460f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        } else if (this._attachments) {
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete this._attachments[name];
462f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        }
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} name
467f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Object}
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    attachment: function(name)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
471f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        return this._attachments ? (this._attachments[name] || null) : null;
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    freeze: function()
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._freezed)
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._freezed = true;
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = this._args.length; i < n; ++i) {
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // FIXME: freeze the Resources also!
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!Resource.forObject(this._args[i]))
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this._args[i] = TypeUtils.clone(this._args[i]);
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
487f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!ReplayableCall}
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    toReplayable: function(cache)
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.freeze();
493f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var thisObject = /** @type {!ReplayableResource} */ (Resource.toReplayable(this._thisObject, cache));
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var result = Resource.toReplayable(this._result, cache);
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var args = this._args.map(function(obj) {
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return Resource.toReplayable(obj, cache);
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var attachments = TypeUtils.cloneObject(this._attachments);
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return new ReplayableCall(thisObject, this._functionName, args, result, this._stackTrace, attachments);
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!ReplayableCall} replayableCall
504f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
505926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Call}
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replay: function(replayableCall, cache)
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
509e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var replayableResult = replayableCall.result();
510e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (replayableResult instanceof ReplayableResource && !cache.has(replayableResult.id())) {
511e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var resource = replayableResult.replay(cache);
512e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            console.assert(resource.calls().length > 0, "Expected create* call for the Resource");
513e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return resource.calls()[0];
514e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
515e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
516926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var replayObject = ReplayableResource.replay(replayableCall.replayableResource(), cache);
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var replayArgs = replayableCall.args().map(function(obj) {
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return ReplayableResource.replay(obj, cache);
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var replayResult = undefined;
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (replayableCall.isPropertySetter())
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            replayObject[replayArgs[0]] = replayArgs[1];
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var replayFunction = replayObject[replayableCall.functionName()];
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            console.assert(typeof replayFunction === "function", "Expected a function to replay");
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            replayResult = replayFunction.apply(replayObject, replayArgs);
528e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
529e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (replayableResult instanceof ReplayableResource) {
530e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                var resource = replayableResult.replay(cache);
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!resource.wrappedObject())
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    resource.setWrappedObject(replayResult);
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
535197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._thisObject = replayObject;
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._functionName = replayableCall.functionName();
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._args = replayArgs;
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._result = replayResult;
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._stackTrace = replayableCall.stackTrace();
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._freezed = true;
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var attachments = replayableCall.attachments();
543f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        this._attachments = attachments ? TypeUtils.cloneObject(attachments) : null;
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
550f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!ReplayableResource} thisObject
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} functionName
552f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Array.<!ReplayableResource|*>} args
553f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!ReplayableResource|*} result
554f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {?StackTrace} stackTrace
555f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {?Object.<string, !Object>} attachments
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function ReplayableCall(thisObject, functionName, args, result, stackTrace, attachments)
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._thisObject = thisObject;
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._functionName = functionName;
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._args = args;
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._result = result;
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._stackTrace = stackTrace;
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (attachments)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._attachments = attachments;
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ReplayableCall.prototype = {
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
570f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!ReplayableResource}
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
572926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    replayableResource: function()
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._thisObject;
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {string}
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    functionName: function()
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._functionName;
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {boolean}
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    isPropertySetter: function()
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return !this._functionName;
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
594591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @return {string}
595591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
596591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    propertyName: function()
597591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
598591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        console.assert(this.isPropertySetter());
599591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return /** @type {string} */ (this._args[0]);
600591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
601591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
602591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
603591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @return {*}
604591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
605591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    propertyValue: function()
606591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
607591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        console.assert(this.isPropertySetter());
608591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return this._args[1];
609591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    },
610591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
611591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    /**
612f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!ReplayableResource|*>}
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    args: function()
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._args;
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
620f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!ReplayableResource|*}
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result: function()
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._result;
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
628f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?StackTrace}
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stackTrace: function()
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._stackTrace;
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
636f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Object.<string, !Object>}
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    attachments: function()
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._attachments;
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} name
645f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object}
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    attachment: function(name)
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._attachments && this._attachments[name];
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
653f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Call}
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replay: function(cache)
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var call = /** @type {!Call} */ (Object.create(Call.prototype));
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return call.replay(this, cache);
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Object} wrappedObject
666926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
668926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function Resource(wrappedObject, name)
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {number} */
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._id = ++Resource._uniqueId;
672926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {string} */
673926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._name = name || "Resource";
674926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {number} */
675926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._kindId = Resource._uniqueKindIds[this._name] = (Resource._uniqueKindIds[this._name] || 0) + 1;
676f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {?ResourceTrackingManager} */
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._resourceManager = null;
678f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {!Array.<!Call>} */
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._calls = [];
680926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
681926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * This is to prevent GC from collecting associated resources.
682926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * Otherwise, for example in WebGL, subsequent calls to gl.getParameter()
683926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * may return a recently created instance that is no longer bound to a
684926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * Resource object (thus, no history to replay it later).
685926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     *
686f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @type {!Object.<string, !Resource>}
687926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
688926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._boundResources = Object.create(null);
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this.setWrappedObject(wrappedObject);
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {number}
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource._uniqueId = 0;
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
698926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {!Object.<string, number>}
699926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
700926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Resource._uniqueKindIds = {};
701926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
702926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {*} obj
704f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @return {?Resource}
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource.forObject = function(obj)
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!obj)
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (obj instanceof Resource)
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return obj;
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (typeof obj === "object")
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return obj["__resourceObject"];
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return null;
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
718f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Resource|*} obj
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {*}
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource.wrappedObject = function(obj)
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var resource = Resource.forObject(obj);
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return resource ? resource.wrappedObject() : obj;
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
728f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Resource|*} obj
729f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Cache.<!ReplayableResource>} cache
730f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @return {!ReplayableResource|*}
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource.toReplayable = function(obj, cache)
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var resource = Resource.forObject(obj);
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return resource ? resource.toReplayable(cache) : obj;
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource.prototype = {
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    id: function()
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._id;
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {string}
7497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
7507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    name: function()
7517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
7527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return this._name;
7537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
7547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
7557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
7567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {string}
7577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
7587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    description: function()
7597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
7607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return this._name + "@" + this._kindId;
7617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
7627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
7637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
764f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object}
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    wrappedObject: function()
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._wrappedObject;
7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {!Object} value
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setWrappedObject: function(value)
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(value, "wrappedObject should not be NULL");
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(!(value instanceof Resource), "Binding a Resource object to another Resource object?");
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._wrappedObject = value;
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._bindObjectToResource(value);
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
783f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object}
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    proxyObject: function()
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._proxyObject)
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._proxyObject = this._wrapObject();
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._proxyObject;
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
793f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?ResourceTrackingManager}
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    manager: function()
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._resourceManager;
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
801f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!ResourceTrackingManager} value
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setManager: function(value)
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._resourceManager = value;
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
809e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {!Array.<!Call>}
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    calls: function()
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._calls;
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
817f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?ContextResource}
818926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
819926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    contextResource: function()
820926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
821926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this instanceof ContextResource)
822f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            return /** @type {!ContextResource} */ (this);
823926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
824926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this._calculatingContextResource)
825926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return null;
826926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
827926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._calculatingContextResource = true;
828926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var result = null;
829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var i = 0, n = this._calls.length; i < n; ++i) {
830926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            result = this._calls[i].resource().contextResource();
831926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (result)
832926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                break;
833926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
834926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        delete this._calculatingContextResource;
835926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        console.assert(result, "Failed to find context resource for " + this._name + "@" + this._kindId);
836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return result;
837926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
838926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
839926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
840f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
8417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
8427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    currentState: function()
8437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
8447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var result = [];
8457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var proxyObject = this.proxyObject();
8467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (!proxyObject)
8477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return result;
8487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var statePropertyNames = this._proxyStatePropertyNames || [];
8497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        for (var i = 0, n = statePropertyNames.length; i < n; ++i) {
8507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var pname = statePropertyNames[i];
8517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            result.push({ name: pname, value: proxyObject[pname] });
8527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
853e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
8547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return result;
8557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
8567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
8577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
858926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {string}
859926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
860926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    toDataURL: function()
861926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
862926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return "";
863926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
864926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
865926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
866f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
867926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!ReplayableResource}
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    toReplayable: function(cache)
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var result = cache.get(this._id);
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (result)
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return result;
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var data = {
875926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            id: this._id,
876926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            name: this._name,
877926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            kindId: this._kindId
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = new ReplayableResource(this, data);
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cache.put(this._id, result); // Put into the cache early to avoid loops.
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data.calls = this._calls.map(function(call) {
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return call.toReplayable(cache);
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._populateReplayableData(data, cache);
885926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var contextResource = this.contextResource();
886926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (contextResource !== this)
887926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            data.contextResource = Resource.toReplayable(contextResource, cache);
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
892926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
893f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _populateReplayableData: function(data, cache)
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Do nothing. Should be overridden by subclasses.
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
901926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
902f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
903926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Resource}
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replay: function(data, cache)
9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var resource = cache.get(data.id);
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (resource)
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return resource;
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._id = data.id;
911926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._name = data.name;
912926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._kindId = data.kindId;
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._resourceManager = null;
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._calls = [];
915926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._boundResources = Object.create(null);
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._wrappedObject = null;
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        cache.put(data.id, this); // Put into the cache early to avoid loops.
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._doReplayCalls(data, cache);
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(this._wrappedObject, "Resource should be reconstructed!");
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this;
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
924926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
925f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _doReplayCalls: function(data, cache)
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = data.calls.length; i < n; ++i)
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._calls.push(data.calls[i].replay(cache));
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall: function(call)
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        call.freeze();
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._calls.push(call);
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
943e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Call} call
944e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
945e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    onCallReplayed: function(call)
946e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
947e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        // Ignore by default.
948e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
949e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
950e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {!Object} object
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _bindObjectToResource: function(object)
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Object.defineProperty(object, "__resourceObject", {
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            value: this,
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            writable: false,
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            enumerable: false,
9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            configurable: true
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
9615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
964926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {string} key
965926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {*} obj
966926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
967926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _registerBoundResource: function(key, obj)
968926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
969926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var resource = Resource.forObject(obj);
970926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (resource)
971926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._boundResources[key] = resource;
972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else
973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            delete this._boundResources[key];
974926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
977f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Object}
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
9795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _wrapObject: function()
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var wrappedObject = this.wrappedObject();
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!wrappedObject)
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return null;
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var proxy = Object.create(wrappedObject.__proto__); // In order to emulate "instanceof".
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var customWrapFunctions = this._customWrapFunctions();
987a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        /** @type {!Array.<string>} */
9887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        this._proxyStatePropertyNames = [];
9897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
9907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        /**
9917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch         * @param {string} property
992f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @this {Resource}
9937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch         */
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function processProperty(property)
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (typeof wrappedObject[property] === "function") {
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var customWrapFunction = customWrapFunctions[property];
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (customWrapFunction)
9997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                    proxy[property] = this._wrapCustomFunction(this, wrappedObject, wrappedObject[property], property, customWrapFunction);
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else
10017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                    proxy[property] = this._wrapFunction(this, wrappedObject, wrappedObject[property], property);
1002e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            } else if (TypeUtils.isEnumPropertyName(property, wrappedObject)) {
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Fast access to enums and constants.
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                proxy[property] = wrappedObject[property];
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            } else {
10067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                this._proxyStatePropertyNames.push(property);
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                Object.defineProperty(proxy, property, {
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    get: function()
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    {
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var obj = wrappedObject[property];
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var resource = Resource.forObject(obj);
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return resource ? resource : obj;
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    },
10147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                    set: this._wrapPropertySetter(this, wrappedObject, property),
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    enumerable: true
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                });
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var isEmpty = true;
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var property in wrappedObject) {
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            isEmpty = false;
10237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            processProperty.call(this, property);
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (isEmpty)
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return wrappedObject; // Nothing to proxy.
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._bindObjectToResource(proxy);
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return proxy;
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Resource} resource
1034926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} originalObject
1035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Function} originalFunction
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} functionName
1037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Function} customWrapFunction
1038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Function}
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _wrapCustomFunction: function(resource, originalObject, originalFunction, functionName, customWrapFunction)
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return function()
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var manager = resource.manager();
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var isCapturing = manager && manager.capturing();
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isCapturing)
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                manager.captureArguments(resource, arguments);
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var wrapFunction = new Resource.WrapFunction(originalObject, originalFunction, functionName, arguments);
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            customWrapFunction.apply(wrapFunction, arguments);
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isCapturing) {
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var call = wrapFunction.call();
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                call.setStackTrace(StackTrace.create(1, arguments.callee));
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                manager.captureCall(call);
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return wrapFunction.result();
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1060926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Resource} resource
1061926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} originalObject
1062926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Function} originalFunction
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} functionName
1064926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Function}
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _wrapFunction: function(resource, originalObject, originalFunction, functionName)
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return function()
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var manager = resource.manager();
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!manager || !manager.capturing())
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return originalFunction.apply(originalObject, arguments);
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            manager.captureArguments(resource, arguments);
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var result = originalFunction.apply(originalObject, arguments);
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var stackTrace = StackTrace.create(1, arguments.callee);
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var call = new Call(resource, functionName, arguments, result, stackTrace);
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            manager.captureCall(call);
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return result;
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1083926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Resource} resource
1084926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} originalObject
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} propertyName
1086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {function(*)}
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _wrapPropertySetter: function(resource, originalObject, propertyName)
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return function(value)
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            resource._registerBoundResource(propertyName, value);
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var manager = resource.manager();
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!manager || !manager.capturing()) {
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                originalObject[propertyName] = Resource.wrappedObject(value);
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var args = [propertyName, value];
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            manager.captureArguments(resource, args);
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            originalObject[propertyName] = Resource.wrappedObject(value);
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var stackTrace = StackTrace.create(1, arguments.callee);
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var call = new Call(resource, "", args, undefined, stackTrace);
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            manager.captureCall(call);
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1108f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object.<string, !Function>}
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _customWrapFunctions: function()
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Object.create(null); // May be overridden by subclasses.
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
1118f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Object} originalObject
1119f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Function} originalFunction
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} functionName
1121f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Array|!Arguments} args
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource.WrapFunction = function(originalObject, originalFunction, functionName, args)
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._originalObject = originalObject;
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._originalFunction = originalFunction;
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._functionName = functionName;
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._args = args;
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._resource = Resource.forObject(originalObject);
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    console.assert(this._resource, "Expected a wrapped call on a Resource object.");
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Resource.WrapFunction.prototype = {
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {*}
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    result: function()
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._executed) {
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._executed = true;
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._result = this._originalFunction.apply(this._originalObject, this._args);
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._result;
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1147926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Call}
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    call: function()
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._call)
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._call = new Call(this._resource, this._functionName, this._args, this.result());
11535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._call;
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {*} result
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    overrideResult: function(result)
11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var call = this.call();
11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        call.setResult(result);
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._result = result;
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {function(new:Resource, !Object, string)} resourceConstructor
1169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} resourceName
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {function(this:Resource.WrapFunction)}
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)Resource.WrapFunction.resourceFactoryMethod = function(resourceConstructor, resourceName)
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1174f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @this {Resource.WrapFunction} */
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return function()
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1177f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var wrappedObject = /** @type {?Object} */ (this.result());
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!wrappedObject)
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
1180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var resource = new resourceConstructor(wrappedObject, resourceName);
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var manager = this._resource.manager();
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (manager)
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            manager.registerResource(resource);
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.overrideResult(resource.proxyObject());
11855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resource.pushCall(this.call());
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Resource} originalResource
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!Object} data
11935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function ReplayableResource(originalResource, data)
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._proto = originalResource.__proto__;
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._data = data;
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ReplayableResource.prototype = {
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {number}
1203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    id: function()
1205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1206926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._data.id;
1207926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1208926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1209926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1210926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {string}
1211926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    name: function()
1213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1214926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._data.name;
1215926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1216926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {string}
1219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    description: function()
1221926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1222926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._data.name + "@" + this._data.kindId;
1223926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1224926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1225926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1226926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!ReplayableResource}
1227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
12287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    contextResource: function()
1229926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1230926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._data.contextResource || this;
1231926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1233926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1234f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
1235926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Resource}
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replay: function(cache)
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1239926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var result = /** @type {!Resource} */ (Object.create(this._proto));
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        result = result.replay(this._data, cache)
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(result.__proto__ === this._proto, "Wrong type of a replay result");
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1247f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!ReplayableResource|*} obj
1248f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @param {!Cache.<!Resource>} cache
12495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @return {*}
12505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
12515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ReplayableResource.replay = function(obj, cache)
12525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
12535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return (obj instanceof ReplayableResource) ? obj.replay(cache).wrappedObject() : obj;
12545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
12575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
12585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {Resource}
1259926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1260926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
1261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
1262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function ContextResource(wrappedObject, name)
1263926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
1264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Resource.call(this, wrappedObject, name);
1265926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1267926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)ContextResource.prototype = {
1268926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    __proto__: Resource.prototype
1269926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
1270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1271926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
1272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
1273926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends {Resource}
1274926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1275926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
12765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1277926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function LogEverythingResource(wrappedObject, name)
12785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Resource.call(this, wrappedObject, name);
12805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LogEverythingResource.prototype = {
12835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
12845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1285f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object.<string, !Function>}
12865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
12875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _customWrapFunctions: function()
12885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
12895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var wrapFunctions = Object.create(null);
12905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var wrappedObject = this.wrappedObject();
12915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (wrappedObject) {
12925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var property in wrappedObject) {
1293f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                /** @this {Resource.WrapFunction} */
12945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                wrapFunctions[property] = function()
12955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                {
12965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    this._resource.pushCall(this.call());
12975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
12985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
12995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
13005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return wrapFunctions;
13015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
13025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: Resource.prototype
13045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
13075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// WebGL
13085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
13095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
13115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
13125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {Resource}
1313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
13155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1316926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLBoundResource(wrappedObject, name)
13175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1318926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Resource.call(this, wrappedObject, name);
1319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {!Object.<string, *>} */
13205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._state = {};
13215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
13225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLBoundResource.prototype = {
13245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
13255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1326926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
1327f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
13285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
13295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _populateReplayableData: function(data, cache)
13305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var state = this._state;
13325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data.state = {};
13335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Object.keys(state).forEach(function(parameter) {
13345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            data.state[parameter] = Resource.toReplayable(state[parameter], cache);
13355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
13365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
13375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
13395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
1341f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
13425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
13435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _doReplayCalls: function(data, cache)
13445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
13455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = this._replayContextResource(data, cache).wrappedObject();
13465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1347f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        /** @type {!Object.<string, !Array.<string>>} */
13485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var bindingsData = {
13495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            TEXTURE_2D: ["bindTexture", "TEXTURE_BINDING_2D"],
13505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            TEXTURE_CUBE_MAP: ["bindTexture", "TEXTURE_BINDING_CUBE_MAP"],
13515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ARRAY_BUFFER: ["bindBuffer", "ARRAY_BUFFER_BINDING"],
13525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ELEMENT_ARRAY_BUFFER: ["bindBuffer", "ELEMENT_ARRAY_BUFFER_BINDING"],
13535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FRAMEBUFFER: ["bindFramebuffer", "FRAMEBUFFER_BINDING"],
13545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            RENDERBUFFER: ["bindRenderbuffer", "RENDERBUFFER_BINDING"]
13555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
13565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var originalBindings = {};
13575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Object.keys(bindingsData).forEach(function(bindingTarget) {
13585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var bindingParameter = bindingsData[bindingTarget][1];
13595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            originalBindings[bindingTarget] = gl.getParameter(gl[bindingParameter]);
13605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
13615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var state = {};
1363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        Object.keys(data.state).forEach(function(parameter) {
1364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            state[parameter] = ReplayableResource.replay(data.state[parameter], cache);
1365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        });
1366926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._state = state;
13675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Resource.prototype._doReplayCalls.call(this, data, cache);
13685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Object.keys(bindingsData).forEach(function(bindingTarget) {
13705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var bindMethodName = bindingsData[bindingTarget][0];
13715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gl[bindMethodName].call(gl, gl[bindingTarget], originalBindings[bindingTarget]);
13725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
13735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
13745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
1376926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
1377f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
1378f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?WebGLRenderingContextResource}
1379926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
13805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _replayContextResource: function(data, cache)
13815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1382f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var calls = /** @type {!Array.<!ReplayableCall>} */ (data.calls);
13835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = calls.length; i < n; ++i) {
1384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var resource = ReplayableResource.replay(calls[i].replayableResource(), cache);
13855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var contextResource = WebGLRenderingContextResource.forObject(resource);
13865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (contextResource)
13875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return contextResource;
13885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
13895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
13905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
13915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
13935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} target
13945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {string} bindMethodName
13955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
13965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushBinding: function(target, bindMethodName)
13975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1398e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (this._state.bindTarget !== target) {
1399e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            this._state.bindTarget = target;
14005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this.pushCall(new Call(WebGLRenderingContextResource.forObject(this), bindMethodName, [target, this]));
14015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
14025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
14035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: Resource.prototype
14055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
14085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
14095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {WebGLBoundResource}
1410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
14125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLTextureResource(wrappedObject, name)
14145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WebGLBoundResource.call(this, wrappedObject, name);
14165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
14175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLTextureResource.prototype = {
14195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1420e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override (overrides @return type)
1421f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLTexture}
1422e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1423e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    wrappedObject: function()
1424e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1425e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return this._wrappedObject;
1426e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1427e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1428e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1429e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
1430f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
1431e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1432e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
1433e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1434e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
1435e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(this);
1436e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = glResource.wrappedObject();
1437e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var texture = this.wrappedObject();
1438e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!gl || !texture)
1439e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1440e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "isTexture", value: gl.isTexture(texture) });
1441e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
1442e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1443e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var target = this._state.bindTarget;
1444e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof target !== "number")
1445e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1446e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1447e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var bindingParameter;
1448e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        switch (target) {
1449e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case gl.TEXTURE_2D:
1450e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            bindingParameter = gl.TEXTURE_BINDING_2D;
1451e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            break;
1452e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case gl.TEXTURE_CUBE_MAP:
1453e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            bindingParameter = gl.TEXTURE_BINDING_CUBE_MAP;
1454e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            break;
1455e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        default:
1456e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            console.error("ASSERT_NOT_REACHED: unknown texture target " + target);
1457e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1458e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
1459e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "target", value: target, valueIsEnum: true });
1460e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1461f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var oldTexture = /** @type {!WebGLTexture} */ (gl.getParameter(bindingParameter));
1462e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldTexture !== texture)
1463e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindTexture(target, texture);
1464e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1465e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var textureParameters = [
1466e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "TEXTURE_MAG_FILTER",
1467e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "TEXTURE_MIN_FILTER",
1468e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "TEXTURE_WRAP_S",
1469e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "TEXTURE_WRAP_T",
1470e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "TEXTURE_MAX_ANISOTROPY_EXT" // EXT_texture_filter_anisotropic extension
1471e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        ];
1472e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        glResource.queryStateValues(gl.getTexParameter, target, textureParameters, result);
1473e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1474e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldTexture !== texture)
1475e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindTexture(target, oldTexture);
1476e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
1477e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1478e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1479e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
14805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
1482f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
14835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
14845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _doReplayCalls: function(data, cache)
14855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
14865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = this._replayContextResource(data, cache).wrappedObject();
14875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var state = {};
14895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
14905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            state[parameter] = gl.getParameter(gl[parameter]);
14915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
14925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLBoundResource.prototype._doReplayCalls.call(this, data, cache);
14945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
14965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gl.pixelStorei(gl[parameter], state[parameter]);
14975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
14985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
14995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
15015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
15035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
15045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall: function(call)
15055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1506926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var gl = WebGLRenderingContextResource.forObject(call.resource()).wrappedObject();
15075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
15085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var value = gl.getParameter(gl[parameter]);
15095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (this._state[parameter] !== value) {
15105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this._state[parameter] = value;
15115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var pixelStoreCall = new Call(gl, "pixelStorei", [gl[parameter], value]);
15125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                WebGLBoundResource.prototype.pushCall.call(this, pixelStoreCall);
15135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
15145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }, this);
15155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: remove any older calls that no longer contribute to the resource state.
15175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: optimize memory usage: maybe it's more efficient to store one texImage2D call instead of many texSubImage2D.
15185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLBoundResource.prototype.pushCall.call(this, call);
15195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
15205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * Handles: texParameteri, texParameterf
1523926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
15245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    pushCall_texParameter: function(call)
15265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
15275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var args = call.args();
15285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var pname = args[1];
15295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var param = args[2];
15305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._state[pname] !== param) {
15315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._state[pname] = param;
15325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            WebGLBoundResource.prototype.pushCall.call(this, call);
15335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
15345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
15355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * Handles: copyTexImage2D, copyTexSubImage2D
15385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * copyTexImage2D and copyTexSubImage2D define a texture image with pixels from the current framebuffer.
1539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
15405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
15415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall_copyTexImage2D: function(call)
15425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(call.resource());
15445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = glResource.wrappedObject();
1545f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var framebufferResource = /** @type {!WebGLFramebufferResource} */ (glResource.currentBinding(gl.FRAMEBUFFER));
15465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (framebufferResource)
15475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this.pushCall(new Call(glResource, "bindFramebuffer", [gl.FRAMEBUFFER, framebufferResource]));
15485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
15495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // FIXME: Implement this case.
15505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            console.error("ASSERT_NOT_REACHED: Could not properly process a gl." + call.functionName() + " call while the DRAWING BUFFER is bound.");
15515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
15525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.pushCall(call);
15535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
15545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: WebGLBoundResource.prototype
15565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
15595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
15605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {Resource}
1561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1562926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
15635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLProgramResource(wrappedObject, name)
15655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Resource.call(this, wrappedObject, name);
15675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
15685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
15695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLProgramResource.prototype = {
15705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1571926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @override (overrides @return type)
1572f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLProgram}
1573926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1574926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    wrappedObject: function()
1575926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._wrappedObject;
1577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
15805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1581f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
15825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1583e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
15845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1585e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        /**
1586e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)         * @param {!Object} obj
1587f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @param {!Array.<!TypeUtils.InternalResourceStateDescriptor>} output
1588e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)         */
1589e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        function convertToStateDescriptors(obj, output)
1590e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        {
1591e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            for (var pname in obj)
1592e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                output.push({ name: pname, value: obj[pname], valueIsEnum: (pname === "type") });
1593e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
1594e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1595e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
1596e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var program = this.wrappedObject();
1597e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!program)
1598e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
15995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(this);
16005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = glResource.wrappedObject();
1601e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var programParameters = ["DELETE_STATUS", "LINK_STATUS", "VALIDATE_STATUS"];
1602e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        glResource.queryStateValues(gl.getProgramParameter, program, programParameters, result);
1603e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "getProgramInfoLog", value: gl.getProgramInfoLog(program) });
1604e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "isProgram", value: gl.isProgram(program) });
1605e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
1606e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1607e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        // ATTACHED_SHADERS
1608e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var callFormatter = CallFormatter.forResource(this);
1609e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var shaders = gl.getAttachedShaders(program) || [];
1610e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var shaderDescriptors = [];
1611e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, n = shaders.length; i < n; ++i) {
1612e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var shaderResource = Resource.forObject(shaders[i]);
1613e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var pname = callFormatter.enumNameForValue(shaderResource.type());
1614e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            shaderDescriptors.push({ name: pname, value: shaderResource });
1615e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
1616e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "ATTACHED_SHADERS", values: shaderDescriptors, isArray: true });
16175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1618e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        // ACTIVE_UNIFORMS
1619e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var uniformDescriptors = [];
1620e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var uniforms = this._activeUniforms(true);
1621e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, n = uniforms.length; i < n; ++i) {
1622e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var pname = "" + i;
1623e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var values = [];
1624e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            convertToStateDescriptors(uniforms[i], values);
1625e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            uniformDescriptors.push({ name: pname, values: values });
1626e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
1627e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "ACTIVE_UNIFORMS", values: uniformDescriptors, isArray: true });
1628e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1629e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        // ACTIVE_ATTRIBUTES
1630e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var attributesCount = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES));
1631e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var attributeDescriptors = [];
1632e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0; i < attributesCount; ++i) {
1633e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var activeInfo = gl.getActiveAttrib(program, i);
1634e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (!activeInfo)
1635e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                continue;
1636e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var pname = "" + i;
1637e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var values = [];
1638e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            convertToStateDescriptors(activeInfo, values);
1639e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            attributeDescriptors.push({ name: pname, values: values });
1640e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
1641e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "ACTIVE_ATTRIBUTES", values: attributeDescriptors, isArray: true });
16425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1643e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
1644e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1645e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1646e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1647e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {boolean=} includeAllInfo
1648e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {!Array.<{name:string, type:number, value:*, size:(number|undefined)}>}
1649e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1650e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _activeUniforms: function(includeAllInfo)
1651e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
16525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var uniforms = [];
1653e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var program = this.wrappedObject();
1654e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!program)
1655e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return uniforms;
1656e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1657e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = WebGLRenderingContextResource.forObject(this).wrappedObject();
1658926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var uniformsCount = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS));
16595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < uniformsCount; ++i) {
16605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var activeInfo = gl.getActiveUniform(program, i);
16615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!activeInfo)
16625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
16635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var uniformLocation = gl.getUniformLocation(program, activeInfo.name);
16645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!uniformLocation)
16655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
16665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var value = gl.getUniform(program, uniformLocation);
1667e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var item = Object.create(null);
1668e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            item.name = activeInfo.name;
1669e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            item.type = activeInfo.type;
1670e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            item.value = value;
1671e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (includeAllInfo)
1672e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                item.size = activeInfo.size;
1673e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            uniforms.push(item);
16745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1675e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return uniforms;
1676e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
16775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1678e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1679e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
1680e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Object} data
1681f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
1682e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1683e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _populateReplayableData: function(data, cache)
1684e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1685e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(this);
1686e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var originalErrors = glResource.getAllErrors();
1687e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        data.uniforms = this._activeUniforms();
16885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        glResource.restoreErrors(originalErrors);
16895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
16905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
16915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
16925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1693926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
1694f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
16955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
16965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _doReplayCalls: function(data, cache)
16975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
16985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Resource.prototype._doReplayCalls.call(this, data, cache);
16995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = WebGLRenderingContextResource.forObject(this).wrappedObject();
17005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var program = this.wrappedObject();
17015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1702f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var originalProgram = /** @type {!WebGLProgram} */ (gl.getParameter(gl.CURRENT_PROGRAM));
17035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var currentProgram = originalProgram;
1704197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
17055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        data.uniforms.forEach(function(uniform) {
17065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var uniformLocation = gl.getUniformLocation(program, uniform.name);
17075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!uniformLocation)
17085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
17095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (currentProgram !== program) {
17105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                currentProgram = program;
17115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.useProgram(program);
17125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
17135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var methodName = this._uniformMethodNameByType(gl, uniform.type);
17145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (methodName.indexOf("Matrix") === -1)
17155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl[methodName].call(gl, uniformLocation, uniform.value);
17165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
17175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl[methodName].call(gl, uniformLocation, false, uniform.value);
17185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }.bind(this));
17195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (currentProgram !== originalProgram)
17215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gl.useProgram(originalProgram);
17225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
17235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1725f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!WebGLRenderingContext} gl
17265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} type
17275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {string}
17285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
17295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _uniformMethodNameByType: function(gl, type)
17305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
17315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var uniformMethodNames = WebGLProgramResource._uniformMethodNames;
17325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!uniformMethodNames) {
17335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames = {};
17345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT] = "uniform1f";
17355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT_VEC2] = "uniform2fv";
17365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT_VEC3] = "uniform3fv";
17375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT_VEC4] = "uniform4fv";
17385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.INT] = "uniform1i";
17395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.BOOL] = "uniform1i";
17405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.SAMPLER_2D] = "uniform1i";
17415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.SAMPLER_CUBE] = "uniform1i";
17425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.INT_VEC2] = "uniform2iv";
17435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.BOOL_VEC2] = "uniform2iv";
17445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.INT_VEC3] = "uniform3iv";
17455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.BOOL_VEC3] = "uniform3iv";
17465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.INT_VEC4] = "uniform4iv";
17475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.BOOL_VEC4] = "uniform4iv";
17485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT_MAT2] = "uniformMatrix2fv";
17495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT_MAT3] = "uniformMatrix3fv";
17505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            uniformMethodNames[gl.FLOAT_MAT4] = "uniformMatrix4fv";
17515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            WebGLProgramResource._uniformMethodNames = uniformMethodNames;
17525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
17535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(uniformMethodNames[type], "Unknown uniform type " + type);
17545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return uniformMethodNames[type];
17555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
17565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
17585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1759926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
17605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
17615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall: function(call)
17625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
17635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: remove any older calls that no longer contribute to the resource state.
17645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: handle multiple attachShader && detachShader.
17655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Resource.prototype.pushCall.call(this, call);
17665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
17675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: Resource.prototype
17695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
17725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
17735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {Resource}
1774926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1775926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
17765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1777926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLShaderResource(wrappedObject, name)
17785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1779926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    Resource.call(this, wrappedObject, name);
17805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
17815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLShaderResource.prototype = {
17835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1784e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override (overrides @return type)
1785f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLShader}
1786e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1787e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    wrappedObject: function()
1788e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1789e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return this._wrappedObject;
1790e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1791e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1792e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1793926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {number}
1794926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
1795926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    type: function()
1796926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
1797926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var call = this._calls[0];
1798926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (call && call.functionName() === "createShader")
1799926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return call.args()[0];
1800926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        console.error("ASSERT_NOT_REACHED: Failed to restore shader type from the log.", call);
1801926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return 0;
1802926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
1803926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
1804926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
18055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
1806f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
1807e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1808e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
1809e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1810e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
1811e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var shader = this.wrappedObject();
1812e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!shader)
1813e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1814e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(this);
1815e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = glResource.wrappedObject();
1816e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var shaderParameters = ["SHADER_TYPE", "DELETE_STATUS", "COMPILE_STATUS"];
1817e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        glResource.queryStateValues(gl.getShaderParameter, shader, shaderParameters, result);
1818e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "getShaderInfoLog", value: gl.getShaderInfoLog(shader) });
1819e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "getShaderSource", value: gl.getShaderSource(shader) });
1820e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "isShader", value: gl.isShader(shader) });
1821e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
1822e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1823e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        // getShaderPrecisionFormat
1824e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var shaderType = this.type();
1825e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var precisionValues = [];
1826e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var precisionParameters = ["LOW_FLOAT", "MEDIUM_FLOAT", "HIGH_FLOAT", "LOW_INT", "MEDIUM_INT", "HIGH_INT"];
1827e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, pname; pname = precisionParameters[i]; ++i)
1828e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            precisionValues.push({ name: pname, value: gl.getShaderPrecisionFormat(shaderType, gl[pname]) });
1829e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "getShaderPrecisionFormat", values: precisionValues });
1830e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1831e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
1832e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1833e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1834e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1835e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
1836926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
18375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
18385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall: function(call)
18395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
18405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: remove any older calls that no longer contribute to the resource state.
18415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: handle multiple shaderSource calls.
18425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Resource.prototype.pushCall.call(this, call);
18435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
18445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: Resource.prototype
18465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
18475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
18495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
18505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {WebGLBoundResource}
1851926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
1852926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
18535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1854926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLBufferResource(wrappedObject, name)
18555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1856926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WebGLBoundResource.call(this, wrappedObject, name);
18575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
18585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
18595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLBufferResource.prototype = {
18605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1861e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override (overrides @return type)
1862f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLBuffer}
1863e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1864e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    wrappedObject: function()
1865e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1866e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return this._wrappedObject;
1867e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1868e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1869e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1870d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)     * @return {?ArrayBufferView}
1871d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)     */
1872d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    cachedBufferData: function()
1873d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    {
1874d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        /**
1875d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)         * Creates a view to a given buffer, does NOT copy the buffer.
1876d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)         * @param {!ArrayBuffer|!ArrayBufferView} buffer
1877d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)         * @return {!Uint8Array}
1878d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)         */
1879d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        function createUint8ArrayBufferView(buffer)
1880d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        {
1881d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
1882d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
1883d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1884d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (!this._cachedBufferData) {
1885d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            for (var i = this._calls.length - 1; i >= 0; --i) {
1886d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                var call = this._calls[i];
1887d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                if (call.functionName() === "bufferData") {
1888f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                    var sizeOrData = /** @type {number|!ArrayBuffer|!ArrayBufferView} */ (call.args()[1]);
1889d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    if (typeof sizeOrData === "number")
1890d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                        this._cachedBufferData = new ArrayBuffer(sizeOrData);
1891d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    else
1892d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                        this._cachedBufferData = sizeOrData;
1893d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    this._lastBufferSubDataIndex = i + 1;
1894d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    break;
1895d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                }
1896d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            }
1897d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!this._cachedBufferData)
1898d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                return null;
1899d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
1900d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1901d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        // Apply any "bufferSubData" calls that have not been applied yet.
1902d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        var bufferDataView;
1903d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        while (this._lastBufferSubDataIndex < this._calls.length) {
1904d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            var call = this._calls[this._lastBufferSubDataIndex++];
1905d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (call.functionName() !== "bufferSubData")
1906d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                continue;
1907d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            var offset = /** @type {number} */ (call.args()[1]);
1908d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            var data = /** @type {!ArrayBuffer|!ArrayBufferView} */ (call.args()[2]);
1909d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            var view = createUint8ArrayBufferView(data);
1910d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!bufferDataView)
1911d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                bufferDataView = createUint8ArrayBufferView(this._cachedBufferData);
1912d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            bufferDataView.set(view, offset);
1913d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1914d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            var isFullReplacement = (offset === 0 && bufferDataView.length === view.length);
1915d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (this._cachedBufferData instanceof ArrayBuffer) {
1916d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                // The buffer data has no type yet. Try to guess from the "bufferSubData" call.
1917d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                var typedArrayClass = TypeUtils.typedArrayClass(data);
1918d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                if (typedArrayClass)
1919d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    this._cachedBufferData = new typedArrayClass(this._cachedBufferData); // Does not copy the buffer.
1920d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            } else if (isFullReplacement) {
1921d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                var typedArrayClass = TypeUtils.typedArrayClass(data);
1922d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                if (typedArrayClass) {
1923d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    var typedArrayData = /** @type {!ArrayBufferView} */ (data);
1924d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                    this._cachedBufferData = new typedArrayClass(this._cachedBufferData.buffer, this._cachedBufferData.byteOffset, typedArrayData.length); // Does not copy the buffer.
1925d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                }
1926d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            }
1927d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
1928d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1929d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (this._cachedBufferData instanceof ArrayBuffer) {
1930d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            // If we failed to guess the data type yet, use Uint8Array.
1931d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            return new Uint8Array(this._cachedBufferData);
1932d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
1933d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return this._cachedBufferData;
1934d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    },
1935d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1936d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    /**
1937e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
1938f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
1939e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
1940e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
1941e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
1942e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
1943e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(this);
1944e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = glResource.wrappedObject();
1945e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var buffer = this.wrappedObject();
1946e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!gl || !buffer)
1947e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1948e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "isBuffer", value: gl.isBuffer(buffer) });
1949e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
1950e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1951e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var target = this._state.bindTarget;
1952e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof target !== "number")
1953e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1954e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1955e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var bindingParameter;
1956e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        switch (target) {
1957e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case gl.ARRAY_BUFFER:
1958e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            bindingParameter = gl.ARRAY_BUFFER_BINDING;
1959e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            break;
1960e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case gl.ELEMENT_ARRAY_BUFFER:
1961e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            bindingParameter = gl.ELEMENT_ARRAY_BUFFER_BINDING;
1962e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            break;
1963e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        default:
1964e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            console.error("ASSERT_NOT_REACHED: unknown buffer target " + target);
1965e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
1966e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
1967e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "target", value: target, valueIsEnum: true });
1968e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1969f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var oldBuffer = /** @type {!WebGLBuffer} */ (gl.getParameter(bindingParameter));
1970e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldBuffer !== buffer)
1971e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindBuffer(target, buffer);
1972e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1973e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var bufferParameters = ["BUFFER_SIZE", "BUFFER_USAGE"];
1974e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        glResource.queryStateValues(gl.getBufferParameter, target, bufferParameters, result);
1975e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1976e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldBuffer !== buffer)
1977e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindBuffer(target, oldBuffer);
1978d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1979d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        try {
1980d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            var data = this.cachedBufferData();
1981d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (data)
1982d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                result.push({ name: "bufferData", value: data });
1983d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        } catch (e) {
1984d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            console.error("Exception while restoring bufferData", e);
1985d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        }
1986d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1987e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
1988e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
1989e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
1990e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
1991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
19925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1993d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    pushCall_bufferData: function(call)
19945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
19955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: remove any older calls that no longer contribute to the resource state.
1996d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        delete this._cachedBufferData;
1997d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        delete this._lastBufferSubDataIndex;
1998d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        WebGLBoundResource.prototype.pushCall.call(this, call);
1999d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    },
2000d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
2001d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    /**
2002d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)     * @param {!Call} call
2003d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)     */
2004d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    pushCall_bufferSubData: function(call)
2005d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    {
20065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: Optimize memory for bufferSubData.
20075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLBoundResource.prototype.pushCall.call(this, call);
20085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
20095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: WebGLBoundResource.prototype
20115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
20145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
20155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {WebGLBoundResource}
2016926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
2017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
20185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2019926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLFramebufferResource(wrappedObject, name)
20205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WebGLBoundResource.call(this, wrappedObject, name);
20225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLFramebufferResource.prototype = {
20255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2026e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override (overrides @return type)
2027f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLFramebuffer}
2028e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2029e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    wrappedObject: function()
2030e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2031e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return this._wrappedObject;
2032e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2033e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2034e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2035e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
2036f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
2037e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2038e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
2039e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2040e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
2041e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var framebuffer = this.wrappedObject();
2042e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!framebuffer)
2043e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
2044e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = WebGLRenderingContextResource.forObject(this).wrappedObject();
2045e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2046f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var oldFramebuffer = /** @type {!WebGLFramebuffer} */ (gl.getParameter(gl.FRAMEBUFFER_BINDING));
2047e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldFramebuffer !== framebuffer)
2048e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
2049e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2050e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var attachmentParameters = ["COLOR_ATTACHMENT0", "DEPTH_ATTACHMENT", "STENCIL_ATTACHMENT"];
2051e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var framebufferParameters = ["FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE", "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME", "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL", "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE"];
2052e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, attachment; attachment = attachmentParameters[i]; ++i) {
2053e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var values = [];
2054e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            for (var j = 0, pname; pname = framebufferParameters[j]; ++j) {
2055e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                var value = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl[attachment], gl[pname]);
2056e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                value = Resource.forObject(value) || value;
2057e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                values.push({ name: pname, value: value, valueIsEnum: WebGLRenderingContextResource.GetResultIsEnum[pname] });
2058e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
2059e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.push({ name: attachment, values: values });
2060e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2061e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "isFramebuffer", value: gl.isFramebuffer(framebuffer) });
2062e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
2063e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2064e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldFramebuffer !== framebuffer)
2065e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindFramebuffer(gl.FRAMEBUFFER, oldFramebuffer);
2066e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
2067e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2068e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2069e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
20705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
2071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
20725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
20735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall: function(call)
20745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
20755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: remove any older calls that no longer contribute to the resource state.
20765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLBoundResource.prototype.pushCall.call(this, call);
20775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
20785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: WebGLBoundResource.prototype
20805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
20835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
20845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @extends {WebGLBoundResource}
2085926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object} wrappedObject
2086926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} name
20875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLRenderbufferResource(wrappedObject, name)
20895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2090926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WebGLBoundResource.call(this, wrappedObject, name);
20915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
20925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
20935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLRenderbufferResource.prototype = {
20945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2095e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override (overrides @return type)
2096f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLRenderbuffer}
2097e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2098e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    wrappedObject: function()
2099e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2100e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return this._wrappedObject;
2101e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2102e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2103e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2104e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
2105f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
2106e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2107e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
2108e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2109e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
2110e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var renderbuffer = this.wrappedObject();
2111e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!renderbuffer)
2112e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
2113e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var glResource = WebGLRenderingContextResource.forObject(this);
2114e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = glResource.wrappedObject();
2115e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2116f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var oldRenderbuffer = /** @type {!WebGLRenderbuffer} */ (gl.getParameter(gl.RENDERBUFFER_BINDING));
2117e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldRenderbuffer !== renderbuffer)
2118e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
2119e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2120e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var renderbufferParameters = ["RENDERBUFFER_WIDTH", "RENDERBUFFER_HEIGHT", "RENDERBUFFER_INTERNAL_FORMAT", "RENDERBUFFER_RED_SIZE", "RENDERBUFFER_GREEN_SIZE", "RENDERBUFFER_BLUE_SIZE", "RENDERBUFFER_ALPHA_SIZE", "RENDERBUFFER_DEPTH_SIZE", "RENDERBUFFER_STENCIL_SIZE"];
2121e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        glResource.queryStateValues(gl.getRenderbufferParameter, gl.RENDERBUFFER, renderbufferParameters, result);
2122e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "isRenderbuffer", value: gl.isRenderbuffer(renderbuffer) });
2123e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
2124e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2125e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (oldRenderbuffer !== renderbuffer)
2126e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.bindRenderbuffer(gl.RENDERBUFFER, oldRenderbuffer);
2127e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
2128e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2129e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2130e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
21315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
2132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
21335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
21345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall: function(call)
21355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
21365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // FIXME: remove any older calls that no longer contribute to the resource state.
21375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLBoundResource.prototype.pushCall.call(this, call);
21385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
21395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    __proto__: WebGLBoundResource.prototype
21415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
21425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
21445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
2145e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * @extends {Resource}
2146e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * @param {!Object} wrappedObject
2147e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * @param {string} name
2148e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) */
2149e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)function WebGLUniformLocationResource(wrappedObject, name)
2150e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
2151e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    Resource.call(this, wrappedObject, name);
2152e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
2153e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2154e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)WebGLUniformLocationResource.prototype = {
2155e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2156e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override (overrides @return type)
2157f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLUniformLocation}
2158e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2159e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    wrappedObject: function()
2160e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2161e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return this._wrappedObject;
2162e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2163e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2164e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2165f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?WebGLProgramResource}
2166e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2167e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    program: function()
2168e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2169e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var call = this._calls[0];
2170e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (call && call.functionName() === "getUniformLocation")
2171f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            return /** @type {!WebGLProgramResource} */ (Resource.forObject(call.args()[0]));
2172e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        console.error("ASSERT_NOT_REACHED: Failed to restore WebGLUniformLocation from the log.", call);
2173e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return null;
2174e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2175e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2176e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2177e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {string}
2178e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2179e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    name: function()
2180e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2181e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var call = this._calls[0];
2182e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (call && call.functionName() === "getUniformLocation")
2183e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return call.args()[1];
2184e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        console.error("ASSERT_NOT_REACHED: Failed to restore WebGLUniformLocation from the log.", call);
2185e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return "";
2186e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2187e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2188e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2189e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
2190f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
2191e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2192e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    currentState: function()
2193e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2194e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = [];
2195e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var location = this.wrappedObject();
2196e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!location)
2197e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
2198e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var programResource = this.program();
2199e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var program = programResource && programResource.wrappedObject();
2200e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!program)
2201e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return result;
2202e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = WebGLRenderingContextResource.forObject(this).wrappedObject();
2203e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var uniformValue = gl.getUniform(program, location);
2204e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var name = this.name();
2205e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "name", value: name });
2206e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "program", value: programResource });
2207e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "value", value: uniformValue });
2208e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
2209e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2210e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof this._type !== "number") {
2211e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var altName = name + "[0]";
2212e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var uniformsCount = /** @type {number} */ (gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS));
2213e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            for (var i = 0; i < uniformsCount; ++i) {
2214e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                var activeInfo = gl.getActiveUniform(program, i);
2215e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (!activeInfo)
2216e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    continue;
2217e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (activeInfo.name === name || activeInfo.name === altName) {
2218e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    this._type = activeInfo.type;
2219e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    this._size = activeInfo.size;
2220e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    if (activeInfo.name === name)
2221e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                        break;
2222e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                }
2223e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
2224e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2225e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof this._type === "number")
2226e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.push({ name: "type", value: this._type, valueIsEnum: true });
2227e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof this._size === "number")
2228e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.push({ name: "size", value: this._size });
2229e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2230e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return result;
2231e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2232e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2233e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2234e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
2235e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Object} data
2236f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
2237e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2238e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _populateReplayableData: function(data, cache)
2239e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2240e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        data.type = this._type;
2241e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        data.size = this._size;
2242e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2243e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2244e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2245e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
2246e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Object} data
2247f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
2248e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2249e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _doReplayCalls: function(data, cache)
2250e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2251e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        this._type = data.type;
2252e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        this._size = data.size;
2253e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        Resource.prototype._doReplayCalls.call(this, data, cache);
2254e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2255e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2256e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    __proto__: Resource.prototype
2257e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
2258e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2259e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)/**
2260e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * @constructor
2261926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends {ContextResource}
22625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!WebGLRenderingContext} glContext
22635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function WebGLRenderingContextResource(glContext)
22655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ContextResource.call(this, glContext, "WebGLRenderingContext");
2267f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {?Object.<number, boolean>} */
22685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._customErrors = null;
2269e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /** @type {!Object.<string, string>} */
2270926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._extensions = {};
2271e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /** @type {!Object.<string, number>} */
2272e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    this._extensionEnums = {};
22735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
22745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
22765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
22775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {!Array.<string>}
22785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
22795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLRenderingContextResource.GLCapabilities = [
22805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND",
22815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "CULL_FACE",
22825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "DEPTH_TEST",
22835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "DITHER",
22845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "POLYGON_OFFSET_FILL",
22855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "SAMPLE_ALPHA_TO_COVERAGE",
22865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "SAMPLE_COVERAGE",
22875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "SCISSOR_TEST",
22885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_TEST"
22895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)];
22905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
22915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
22925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
22935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {!Array.<string>}
22945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
22955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLRenderingContextResource.PixelStoreParameters = [
22965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "PACK_ALIGNMENT",
22975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_ALIGNMENT",
22985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_COLORSPACE_CONVERSION_WEBGL",
22995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_FLIP_Y_WEBGL",
23005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_PREMULTIPLY_ALPHA_WEBGL"
23015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)];
23025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
23045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
23055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {!Array.<string>}
23065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
23075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLRenderingContextResource.StateParameters = [
23085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "ACTIVE_TEXTURE",
23095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "ARRAY_BUFFER_BINDING",
23105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_COLOR",
23115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_DST_ALPHA",
23125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_DST_RGB",
23135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_EQUATION_ALPHA",
23145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_EQUATION_RGB",
23155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_SRC_ALPHA",
23165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "BLEND_SRC_RGB",
23175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "COLOR_CLEAR_VALUE",
23185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "COLOR_WRITEMASK",
23195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "CULL_FACE_MODE",
23205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "CURRENT_PROGRAM",
23215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "DEPTH_CLEAR_VALUE",
23225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "DEPTH_FUNC",
23235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "DEPTH_RANGE",
23245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "DEPTH_WRITEMASK",
23255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "ELEMENT_ARRAY_BUFFER_BINDING",
2326e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "FRAGMENT_SHADER_DERIVATIVE_HINT_OES", // OES_standard_derivatives extension
23275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "FRAMEBUFFER_BINDING",
23285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "FRONT_FACE",
23295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "GENERATE_MIPMAP_HINT",
23305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "LINE_WIDTH",
23315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "PACK_ALIGNMENT",
23325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "POLYGON_OFFSET_FACTOR",
23335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "POLYGON_OFFSET_UNITS",
23345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "RENDERBUFFER_BINDING",
23355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "SAMPLE_COVERAGE_INVERT",
23365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "SAMPLE_COVERAGE_VALUE",
23375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "SCISSOR_BOX",
23385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_FAIL",
23395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_FUNC",
23405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_PASS_DEPTH_FAIL",
23415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_PASS_DEPTH_PASS",
23425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_REF",
23435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_VALUE_MASK",
23445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_BACK_WRITEMASK",
23455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_CLEAR_VALUE",
23465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_FAIL",
23475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_FUNC",
23485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_PASS_DEPTH_FAIL",
23495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_PASS_DEPTH_PASS",
23505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_REF",
23515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_VALUE_MASK",
23525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "STENCIL_WRITEMASK",
23535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_ALIGNMENT",
23545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_COLORSPACE_CONVERSION_WEBGL",
23555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_FLIP_Y_WEBGL",
23565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "UNPACK_PREMULTIPLY_ALPHA_WEBGL",
2357e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "VERTEX_ARRAY_BINDING_OES", // OES_vertex_array_object extension
23585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "VIEWPORT"
23595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)];
23605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
23615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
2362e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * True for those enums that return also an enum via a getter API method (e.g. getParameter, getShaderParameter, etc.).
2363e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * @const
2364e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) * @type {!Object.<string, boolean>}
2365e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles) */
2366e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)WebGLRenderingContextResource.GetResultIsEnum = TypeUtils.createPrefixedPropertyNamesSet([
2367e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getParameter()
2368e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "ACTIVE_TEXTURE",
2369e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BLEND_DST_ALPHA",
2370e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BLEND_DST_RGB",
2371e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BLEND_EQUATION_ALPHA",
2372e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BLEND_EQUATION_RGB",
2373e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BLEND_SRC_ALPHA",
2374e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BLEND_SRC_RGB",
2375e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "CULL_FACE_MODE",
2376e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "DEPTH_FUNC",
2377e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "FRONT_FACE",
2378e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "GENERATE_MIPMAP_HINT",
2379e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "FRAGMENT_SHADER_DERIVATIVE_HINT_OES",
2380e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_BACK_FAIL",
2381e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_BACK_FUNC",
2382e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_BACK_PASS_DEPTH_FAIL",
2383e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_BACK_PASS_DEPTH_PASS",
2384e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_FAIL",
2385e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_FUNC",
2386e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_PASS_DEPTH_FAIL",
2387e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "STENCIL_PASS_DEPTH_PASS",
2388e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "UNPACK_COLORSPACE_CONVERSION_WEBGL",
2389e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getBufferParameter()
2390e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "BUFFER_USAGE",
2391e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getFramebufferAttachmentParameter()
2392e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",
2393e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getRenderbufferParameter()
2394e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "RENDERBUFFER_INTERNAL_FORMAT",
2395e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getTexParameter()
2396e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "TEXTURE_MAG_FILTER",
2397e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "TEXTURE_MIN_FILTER",
2398e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "TEXTURE_WRAP_S",
2399e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "TEXTURE_WRAP_T",
2400e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getShaderParameter()
2401e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "SHADER_TYPE",
2402e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    // gl.getVertexAttrib()
2403e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    "VERTEX_ATTRIB_ARRAY_TYPE"
2404e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)]);
2405e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2406e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)/**
2407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
2408926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {!Object.<string, boolean>}
2409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
2410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebGLRenderingContextResource.DrawingMethods = TypeUtils.createPrefixedPropertyNamesSet([
2411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "clear",
2412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "drawArrays",
2413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "drawElements"
2414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)]);
2415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
24175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {*} obj
2418f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @return {?WebGLRenderingContextResource}
24195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
24205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLRenderingContextResource.forObject = function(obj)
24215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
24225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var resource = Resource.forObject(obj);
2423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!resource)
24245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
2425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    resource = resource.contextResource();
24265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return (resource instanceof WebGLRenderingContextResource) ? resource : null;
24275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
24285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebGLRenderingContextResource.prototype = {
24305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2431926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @override (overrides @return type)
2432f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!WebGLRenderingContext}
2433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    wrappedObject: function()
2435926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
2436926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._wrappedObject;
2437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
2438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2440926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @override
2441926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {string}
2442926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2443926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    toDataURL: function()
2444926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
2445926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this.wrappedObject().canvas.toDataURL();
2446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
2447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
2449f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<number>}
24505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
24515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    getAllErrors: function()
24525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
24535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var errors = [];
24545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = this.wrappedObject();
24555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (gl) {
24565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (true) {
24575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var error = gl.getError();
24585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (error === gl.NO_ERROR)
24595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    break;
24605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this.clearError(error);
24615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                errors.push(error);
24625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
24635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
24645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._customErrors) {
24655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var key in this._customErrors) {
24665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var error = Number(key);
24675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                errors.push(error);
24685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
24695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete this._customErrors;
24705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
24715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return errors;
24725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
24735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2475f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<number>} errors
24765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
24775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    restoreErrors: function(errors)
24785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
24795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = this.wrappedObject();
24805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (gl) {
24815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var wasError = false;
24825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (gl.getError() !== gl.NO_ERROR)
24835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                wasError = true;
24845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            console.assert(!wasError, "Error(s) while capturing current WebGL state.");
24855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
24865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!errors.length)
24875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete this._customErrors;
24885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else {
24895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._customErrors = {};
24905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var i = 0, n = errors.length; i < n; ++i)
24915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this._customErrors[errors[i]] = true;
24925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
24935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
24945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
24965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} error
24975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
24985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearError: function(error)
24995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
25005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._customErrors)
25015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            delete this._customErrors[error];
25025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
25035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
25055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
25065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
25075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    nextError: function()
25085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
25095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._customErrors) {
25105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var key in this._customErrors) {
25115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var error = Number(key);
25125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                delete this._customErrors[error];
25135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return error;
25145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
25155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
25165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete this._customErrors;
25175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = this.wrappedObject();
25185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return gl ? gl.NO_ERROR : 0;
25195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
25205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
25215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2522926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {string} name
2523f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Object} obj
2524926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
2525e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    registerWebGLExtension: function(name, obj)
2526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
2527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // FIXME: Wrap OES_vertex_array_object extension.
2528e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var lowerName = name.toLowerCase();
2529e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (obj && !this._extensions[lowerName]) {
2530e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            this._extensions[lowerName] = name;
2531e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            for (var property in obj) {
2532e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (TypeUtils.isEnumPropertyName(property, obj))
2533e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    this._extensionEnums[property] = /** @type {number} */ (obj[property]);
2534e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
2535e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2536e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2537e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2538e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2539e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string} name
2540e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {number|undefined}
2541e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2542e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _enumValueForName: function(name)
2543e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2544e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof this._extensionEnums[name] === "number")
2545e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return this._extensionEnums[name];
2546e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = this.wrappedObject();
2547e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return (typeof gl[name] === "number" ? gl[name] : undefined);
2548e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2549e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2550e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2551e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {function(this:WebGLRenderingContext, T, number):*} func
2552e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {T} targetOrWebGLObject
2553e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Array.<string>} pnames
2554f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<!TypeUtils.InternalResourceStateDescriptor>} output
2555e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @template T
2556e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2557e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    queryStateValues: function(func, targetOrWebGLObject, pnames, output)
2558e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2559e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = this.wrappedObject();
2560e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, pname; pname = pnames[i]; ++i) {
2561e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var enumValue = this._enumValueForName(pname);
2562e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (typeof enumValue !== "number")
2563e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                continue;
2564e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var value = func.call(gl, targetOrWebGLObject, enumValue);
2565e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            value = Resource.forObject(value) || value;
2566e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            output.push({ name: pname, value: value, valueIsEnum: WebGLRenderingContextResource.GetResultIsEnum[pname] });
2567e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2568926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
2569926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
25715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
2572f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
25735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
25747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    currentState: function()
25755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
25767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        /**
25777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch         * @param {!Object} obj
2578f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @param {!Array.<!TypeUtils.InternalResourceStateDescriptor>} output
25797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch         */
25807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        function convertToStateDescriptors(obj, output)
25817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        {
25827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            for (var pname in obj)
2583e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                output.push({ name: pname, value: obj[pname], valueIsEnum: WebGLRenderingContextResource.GetResultIsEnum[pname] });
25847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
25857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2586e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var gl = this.wrappedObject();
25877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var glState = this._internalCurrentState(null);
25887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
25897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        // VERTEX_ATTRIB_ARRAYS
25907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var vertexAttribStates = [];
25917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        for (var i = 0, n = glState.VERTEX_ATTRIB_ARRAYS.length; i < n; ++i) {
25927757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var pname = "" + i;
25937757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var values = [];
25947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            convertToStateDescriptors(glState.VERTEX_ATTRIB_ARRAYS[i], values);
25957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            vertexAttribStates.push({ name: pname, values: values });
25967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
25977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        delete glState.VERTEX_ATTRIB_ARRAYS;
25987757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
25997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        // TEXTURE_UNITS
26007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var textureUnits = [];
26017757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        for (var i = 0, n = glState.TEXTURE_UNITS.length; i < n; ++i) {
26027757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var pname = "TEXTURE" + i;
26037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var values = [];
26047757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            convertToStateDescriptors(glState.TEXTURE_UNITS[i], values);
26057757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            textureUnits.push({ name: pname, values: values });
26067757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
26077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        delete glState.TEXTURE_UNITS;
26087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
26097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var result = [];
26107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        convertToStateDescriptors(glState, result);
2611e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "VERTEX_ATTRIB_ARRAYS", values: vertexAttribStates, isArray: true });
2612e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "TEXTURE_UNITS", values: textureUnits, isArray: true });
2613e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2614e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var textureBindingParameters = ["TEXTURE_BINDING_2D", "TEXTURE_BINDING_CUBE_MAP"];
2615e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, pname; pname = textureBindingParameters[i]; ++i) {
2616e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var value = gl.getParameter(gl[pname]);
2617e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            value = Resource.forObject(value) || value;
2618e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.push({ name: pname, value: value });
2619e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2620e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2621e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        // ENABLED_EXTENSIONS
2622e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var enabledExtensions = [];
2623e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var lowerName in this._extensions) {
2624e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var pname = this._extensions[lowerName];
2625e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var value = gl.getExtension(pname);
2626e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            value = Resource.forObject(value) || value;
2627e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            enabledExtensions.push({ name: pname, value: value });
2628e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2629e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "ENABLED_EXTENSIONS", values: enabledExtensions, isArray: true });
2630e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
26317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return result;
26327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
26337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
26347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
2635f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Cache.<!ReplayableResource>} cache
26367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {!Object.<string, *>}
26377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
26387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _internalCurrentState: function(cache)
26397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
26407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        /**
2641f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @param {!Resource|*} obj
2642f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @return {!Resource|!ReplayableResource|*}
26437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch         */
26447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        function maybeToReplayable(obj)
26457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        {
26467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return cache ? Resource.toReplayable(obj, cache) : (Resource.forObject(obj) || obj);
26477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
26485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var gl = this.wrappedObject();
26505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var originalErrors = this.getAllErrors();
26515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Take a full GL state snapshot.
26537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var glState = Object.create(null);
26545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLRenderingContextResource.GLCapabilities.forEach(function(parameter) {
26555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            glState[parameter] = gl.isEnabled(gl[parameter]);
26565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
2657e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, pname; pname = WebGLRenderingContextResource.StateParameters[i]; ++i) {
2658e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var enumValue = this._enumValueForName(pname);
2659e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (typeof enumValue === "number")
2660e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                glState[pname] = maybeToReplayable(gl.getParameter(enumValue));
2661e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
26625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // VERTEX_ATTRIB_ARRAYS
2664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var maxVertexAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
2665e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var vertexAttribParameters = [
2666e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",
2667e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_ENABLED",
2668e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_SIZE",
2669e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_STRIDE",
2670e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_TYPE",
2671e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_NORMALIZED",
2672e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "CURRENT_VERTEX_ATTRIB",
2673e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            "VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE" // ANGLE_instanced_arrays extension
2674e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        ];
26755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var vertexAttribStates = [];
2676e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var index = 0; index < maxVertexAttribs; ++index) {
26777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var state = Object.create(null);
2678e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            for (var i = 0, pname; pname = vertexAttribParameters[i]; ++i) {
2679e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                var enumValue = this._enumValueForName(pname);
2680e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (typeof enumValue === "number")
2681e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    state[pname] = maybeToReplayable(gl.getVertexAttrib(index, enumValue));
2682e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
2683e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            state.VERTEX_ATTRIB_ARRAY_POINTER = gl.getVertexAttribOffset(index, gl.VERTEX_ATTRIB_ARRAY_POINTER);
26845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            vertexAttribStates.push(state);
26855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
26867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        glState.VERTEX_ATTRIB_ARRAYS = vertexAttribStates;
26875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
26887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        // TEXTURE_UNITS
26897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var savedActiveTexture = /** @type {number} */ (gl.getParameter(gl.ACTIVE_TEXTURE));
2690926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var maxTextureImageUnits = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
26917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var textureUnits = [];
26925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < maxTextureImageUnits; ++i) {
26935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gl.activeTexture(gl.TEXTURE0 + i);
26947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var state = Object.create(null);
26957757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            state.TEXTURE_2D = maybeToReplayable(gl.getParameter(gl.TEXTURE_BINDING_2D));
26967757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            state.TEXTURE_CUBE_MAP = maybeToReplayable(gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP));
26977757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            textureUnits.push(state);
26985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
26997757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        glState.TEXTURE_UNITS = textureUnits;
27007757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        gl.activeTexture(savedActiveTexture);
27015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.restoreErrors(originalErrors);
27037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return glState;
27045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
27055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
27075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
2708926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
2709f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
27107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
27117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _populateReplayableData: function(data, cache)
27127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
27137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var gl = this.wrappedObject();
27147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        data.originalCanvas = gl.canvas;
27157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        data.originalContextAttributes = gl.getContextAttributes();
27167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        data.extensions = TypeUtils.cloneObject(this._extensions);
2717e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        data.extensionEnums = TypeUtils.cloneObject(this._extensionEnums);
27187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        data.glState = this._internalCurrentState(cache);
27197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
27207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
27217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
27227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @override
27237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @param {!Object} data
2724f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
27255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
27265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _doReplayCalls: function(data, cache)
27275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
27285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._customErrors = null;
2729926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._extensions = TypeUtils.cloneObject(data.extensions) || {};
2730e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        this._extensionEnums = TypeUtils.cloneObject(data.extensionEnums) || {};
2731926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2732926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var canvas = data.originalCanvas.cloneNode(true);
2733926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var replayContext = null;
2734926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var contextIds = ["experimental-webgl", "webkit-3d", "3d"];
2735926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var i = 0, contextId; contextId = contextIds[i]; ++i) {
2736926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            replayContext = canvas.getContext(contextId, data.originalContextAttributes);
2737926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (replayContext)
2738926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                break;
2739926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
2740926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2741926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        console.assert(replayContext, "Failed to create a WebGLRenderingContext for the replay.");
27425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2743926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var gl = /** @type {!WebGLRenderingContext} */ (Resource.wrappedObject(replayContext));
27445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.setWrappedObject(gl);
27455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2746926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Enable corresponding WebGL extensions.
2747926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var name in this._extensions)
2748926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            gl.getExtension(name);
2749926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
27505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var glState = data.glState;
2751f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        gl.bindFramebuffer(gl.FRAMEBUFFER, /** @type {!WebGLFramebuffer} */ (ReplayableResource.replay(glState.FRAMEBUFFER_BINDING, cache)));
2752f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        gl.bindRenderbuffer(gl.RENDERBUFFER, /** @type {!WebGLRenderbuffer} */ (ReplayableResource.replay(glState.RENDERBUFFER_BINDING, cache)));
27535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Enable or disable server-side GL capabilities.
27555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLRenderingContextResource.GLCapabilities.forEach(function(parameter) {
27565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            console.assert(parameter in glState);
27575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (glState[parameter])
27585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.enable(gl[parameter]);
27595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
27605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.disable(gl[parameter]);
27615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
27625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.blendColor(glState.BLEND_COLOR[0], glState.BLEND_COLOR[1], glState.BLEND_COLOR[2], glState.BLEND_COLOR[3]);
27645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.blendEquationSeparate(glState.BLEND_EQUATION_RGB, glState.BLEND_EQUATION_ALPHA);
27655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.blendFuncSeparate(glState.BLEND_SRC_RGB, glState.BLEND_DST_RGB, glState.BLEND_SRC_ALPHA, glState.BLEND_DST_ALPHA);
27665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.clearColor(glState.COLOR_CLEAR_VALUE[0], glState.COLOR_CLEAR_VALUE[1], glState.COLOR_CLEAR_VALUE[2], glState.COLOR_CLEAR_VALUE[3]);
27675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.clearDepth(glState.DEPTH_CLEAR_VALUE);
27685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.clearStencil(glState.STENCIL_CLEAR_VALUE);
27695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.colorMask(glState.COLOR_WRITEMASK[0], glState.COLOR_WRITEMASK[1], glState.COLOR_WRITEMASK[2], glState.COLOR_WRITEMASK[3]);
27705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.cullFace(glState.CULL_FACE_MODE);
27715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.depthFunc(glState.DEPTH_FUNC);
27725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.depthMask(glState.DEPTH_WRITEMASK);
27735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.depthRange(glState.DEPTH_RANGE[0], glState.DEPTH_RANGE[1]);
27745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.frontFace(glState.FRONT_FACE);
27755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.hint(gl.GENERATE_MIPMAP_HINT, glState.GENERATE_MIPMAP_HINT);
27765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.lineWidth(glState.LINE_WIDTH);
27775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2778e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var enumValue = this._enumValueForName("FRAGMENT_SHADER_DERIVATIVE_HINT_OES");
2779e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (typeof enumValue === "number")
2780e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            gl.hint(enumValue, glState.FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
2781e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
27825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) {
27835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gl.pixelStorei(gl[parameter], glState[parameter]);
27845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
27855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.polygonOffset(glState.POLYGON_OFFSET_FACTOR, glState.POLYGON_OFFSET_UNITS);
27875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.sampleCoverage(glState.SAMPLE_COVERAGE_VALUE, glState.SAMPLE_COVERAGE_INVERT);
27885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.stencilFuncSeparate(gl.FRONT, glState.STENCIL_FUNC, glState.STENCIL_REF, glState.STENCIL_VALUE_MASK);
27895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.stencilFuncSeparate(gl.BACK, glState.STENCIL_BACK_FUNC, glState.STENCIL_BACK_REF, glState.STENCIL_BACK_VALUE_MASK);
27905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.stencilOpSeparate(gl.FRONT, glState.STENCIL_FAIL, glState.STENCIL_PASS_DEPTH_FAIL, glState.STENCIL_PASS_DEPTH_PASS);
27915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.stencilOpSeparate(gl.BACK, glState.STENCIL_BACK_FAIL, glState.STENCIL_BACK_PASS_DEPTH_FAIL, glState.STENCIL_BACK_PASS_DEPTH_PASS);
27925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.stencilMaskSeparate(gl.FRONT, glState.STENCIL_WRITEMASK);
27935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.stencilMaskSeparate(gl.BACK, glState.STENCIL_BACK_WRITEMASK);
27945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.scissor(glState.SCISSOR_BOX[0], glState.SCISSOR_BOX[1], glState.SCISSOR_BOX[2], glState.SCISSOR_BOX[3]);
27965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.viewport(glState.VIEWPORT[0], glState.VIEWPORT[1], glState.VIEWPORT[2], glState.VIEWPORT[3]);
27975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2798f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        gl.useProgram(/** @type {!WebGLProgram} */ (ReplayableResource.replay(glState.CURRENT_PROGRAM, cache)));
27995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // VERTEX_ATTRIB_ARRAYS
28015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var maxVertexAttribs = /** @type {number} */ (gl.getParameter(gl.MAX_VERTEX_ATTRIBS));
28025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < maxVertexAttribs; ++i) {
28037757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var state = glState.VERTEX_ATTRIB_ARRAYS[i] || {};
28045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (state.VERTEX_ATTRIB_ARRAY_ENABLED)
28055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.enableVertexAttribArray(i);
28065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
28075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.disableVertexAttribArray(i);
28085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (state.CURRENT_VERTEX_ATTRIB)
28095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.vertexAttrib4fv(i, state.CURRENT_VERTEX_ATTRIB);
2810f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            var buffer = /** @type {!WebGLBuffer} */ (ReplayableResource.replay(state.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, cache));
28115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (buffer) {
28125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
28135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                gl.vertexAttribPointer(i, state.VERTEX_ATTRIB_ARRAY_SIZE, state.VERTEX_ATTRIB_ARRAY_TYPE, state.VERTEX_ATTRIB_ARRAY_NORMALIZED, state.VERTEX_ATTRIB_ARRAY_STRIDE, state.VERTEX_ATTRIB_ARRAY_POINTER);
28145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
28155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2816f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        gl.bindBuffer(gl.ARRAY_BUFFER, /** @type {!WebGLBuffer} */ (ReplayableResource.replay(glState.ARRAY_BUFFER_BINDING, cache)));
2817f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, /** @type {!WebGLBuffer} */ (ReplayableResource.replay(glState.ELEMENT_ARRAY_BUFFER_BINDING, cache)));
28185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        // TEXTURE_UNITS
28205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var maxTextureImageUnits = /** @type {number} */ (gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS));
28215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < maxTextureImageUnits; ++i) {
28225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            gl.activeTexture(gl.TEXTURE0 + i);
28237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var state = glState.TEXTURE_UNITS[i] || {};
2824f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            gl.bindTexture(gl.TEXTURE_2D, /** @type {!WebGLTexture} */ (ReplayableResource.replay(state.TEXTURE_2D, cache)));
2825f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            gl.bindTexture(gl.TEXTURE_CUBE_MAP, /** @type {!WebGLTexture} */ (ReplayableResource.replay(state.TEXTURE_CUBE_MAP, cache)));
28265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
28275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        gl.activeTexture(glState.ACTIVE_TEXTURE);
28285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2829926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ContextResource.prototype._doReplayCalls.call(this, data, cache);
28305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
28315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2833f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Object|number} target
2834f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Resource}
28355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
28365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    currentBinding: function(target)
28375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
28385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var resource = Resource.forObject(target);
28395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (resource)
28405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return resource;
28415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var gl = this.wrappedObject();
28425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var bindingParameter;
28435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var bindMethodName;
284451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        target = +target; // Explicitly convert to a number.
28455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var bindMethodTarget = target;
28465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        switch (target) {
28475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.ARRAY_BUFFER:
28485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindingParameter = gl.ARRAY_BUFFER_BINDING;
28495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodName = "bindBuffer";
28505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
28515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.ELEMENT_ARRAY_BUFFER:
28525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindingParameter = gl.ELEMENT_ARRAY_BUFFER_BINDING;
28535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodName = "bindBuffer";
28545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
28555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_2D:
28565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindingParameter = gl.TEXTURE_BINDING_2D;
28575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodName = "bindTexture";
28585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
28595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP:
28605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP_POSITIVE_X:
28615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP_NEGATIVE_X:
28625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP_POSITIVE_Y:
28635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y:
28645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP_POSITIVE_Z:
28655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z:
28665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindingParameter = gl.TEXTURE_BINDING_CUBE_MAP;
28675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodTarget = gl.TEXTURE_CUBE_MAP;
28685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodName = "bindTexture";
28695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
28705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.FRAMEBUFFER:
28715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindingParameter = gl.FRAMEBUFFER_BINDING;
28725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodName = "bindFramebuffer";
28735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
28745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        case gl.RENDERBUFFER:
28755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindingParameter = gl.RENDERBUFFER_BINDING;
28765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            bindMethodName = "bindRenderbuffer";
28775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
28785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        default:
28795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            console.error("ASSERT_NOT_REACHED: unknown binding target " + target);
28805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return null;
28815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
28825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resource = Resource.forObject(gl.getParameter(bindingParameter));
28835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (resource)
28845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            resource.pushBinding(bindMethodTarget, bindMethodName);
28855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return resource;
28865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
28875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
28885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
28895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
2890e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {!Call} call
2891e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
2892e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    onCallReplayed: function(call)
2893e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
2894e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var functionName = call.functionName();
2895e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var args = call.args();
2896e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        switch (functionName) {
2897e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case "bindBuffer":
2898e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case "bindFramebuffer":
2899e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case "bindRenderbuffer":
2900e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case "bindTexture":
2901e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            // Update BINDING state for Resources in the replay world.
2902e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var resource = Resource.forObject(args[1]);
2903e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (resource)
2904e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                resource.pushBinding(args[0], functionName);
2905e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            break;
2906e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        case "getExtension":
2907f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            this.registerWebGLExtension(args[0], /** @type {!Object} */ (call.result()));
2908e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            break;
2909d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        case "bufferData":
2910f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            var resource = /** @type {!WebGLBufferResource} */ (this.currentBinding(args[0]));
2911d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (resource)
2912d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                resource.pushCall_bufferData(call);
2913d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
2914d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        case "bufferSubData":
2915f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            var resource = /** @type {!WebGLBufferResource} */ (this.currentBinding(args[0]));
2916d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (resource)
2917d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                resource.pushCall_bufferSubData(call);
2918d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            break;
2919e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
2920e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
2921e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
2922e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
2923e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
2924f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object.<string, !Function>}
29255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
29265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _customWrapFunctions: function()
29275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
29285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var wrapFunctions = WebGLRenderingContextResource._wrapFunctions;
29295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!wrapFunctions) {
29305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            wrapFunctions = Object.create(null);
29315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2932926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createBuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLBufferResource, "WebGLBuffer");
2933926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createShader"] = Resource.WrapFunction.resourceFactoryMethod(WebGLShaderResource, "WebGLShader");
2934926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createProgram"] = Resource.WrapFunction.resourceFactoryMethod(WebGLProgramResource, "WebGLProgram");
2935926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createTexture"] = Resource.WrapFunction.resourceFactoryMethod(WebGLTextureResource, "WebGLTexture");
2936926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createFramebuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLFramebufferResource, "WebGLFramebuffer");
2937926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createRenderbuffer"] = Resource.WrapFunction.resourceFactoryMethod(WebGLRenderbufferResource, "WebGLRenderbuffer");
2938e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            wrapFunctions["getUniformLocation"] = Resource.WrapFunction.resourceFactoryMethod(WebGLUniformLocationResource, "WebGLUniformLocation");
29395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2940926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("bindAttribLocation");
2941926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("compileShader");
2942926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("detachShader");
2943926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("linkProgram");
2944926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("shaderSource");
2945d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            stateModifyingWrapFunction("bufferData", WebGLBufferResource.prototype.pushCall_bufferData);
2946d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            stateModifyingWrapFunction("bufferSubData", WebGLBufferResource.prototype.pushCall_bufferSubData);
2947926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("compressedTexImage2D");
2948926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("compressedTexSubImage2D");
2949926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("copyTexImage2D", WebGLTextureResource.prototype.pushCall_copyTexImage2D);
2950926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("copyTexSubImage2D", WebGLTextureResource.prototype.pushCall_copyTexImage2D);
2951926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("generateMipmap");
2952926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("texImage2D");
2953926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("texSubImage2D");
2954926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("texParameterf", WebGLTextureResource.prototype.pushCall_texParameter);
2955926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("texParameteri", WebGLTextureResource.prototype.pushCall_texParameter);
2956926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            stateModifyingWrapFunction("renderbufferStorage");
29575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2958f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            /** @this {Resource.WrapFunction} */
29595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            wrapFunctions["getError"] = function()
29605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
2961f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                var gl = /** @type {!WebGLRenderingContext} */ (this._originalObject);
29625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var error = this.result();
29635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (error !== gl.NO_ERROR)
29645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    this._resource.clearError(error);
29655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else {
29665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    error = this._resource.nextError();
29675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (error !== gl.NO_ERROR)
29685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        this.overrideResult(error);
29695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
29705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
29715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2972926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
2973926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {string} name
2974f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
2975926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
2976926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["getExtension"] = function(name)
2977926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
2978e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                this._resource.registerWebGLExtension(name, this.result());
2979926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
2980926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2981926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            //
2982926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            // Register bound WebGL resources.
2983926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            //
2984926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2985926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
2986f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @param {!WebGLProgram} program
2987f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @param {!WebGLShader} shader
2988f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
2989926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
2990926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["attachShader"] = function(program, shader)
2991926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
2992926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                var resource = this._resource.currentBinding(program);
2993926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if (resource) {
2994926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    resource.pushCall(this.call());
2995f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                    var shaderResource = /** @type {!WebGLShaderResource} */ (Resource.forObject(shader));
2996926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    if (shaderResource) {
2997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        var shaderType = shaderResource.type();
2998926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                        resource._registerBoundResource("__attachShader_" + shaderType, shaderResource);
2999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    }
3000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
3001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
3002926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
3003926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {number} target
3004926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {number} attachment
3005926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {number} objectTarget
3006f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @param {!WebGLRenderbuffer|!WebGLTexture} obj
3007f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
3008926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
3009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["framebufferRenderbuffer"] = wrapFunctions["framebufferTexture2D"] = function(target, attachment, objectTarget, obj)
3010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
3011926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                var resource = this._resource.currentBinding(target);
3012926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if (resource) {
3013926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    resource.pushCall(this.call());
3014926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    resource._registerBoundResource("__framebufferAttachmentObjectName", obj);
3015926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                }
3016926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
3017926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
3018926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {number} target
3019f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @param {!Object} obj
3020f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
3021926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
3022926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["bindBuffer"] = wrapFunctions["bindFramebuffer"] = wrapFunctions["bindRenderbuffer"] = function(target, obj)
3023926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
3024e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                this._resource.currentBinding(target); // To call WebGLBoundResource.prototype.pushBinding().
3025926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                this._resource._registerBoundResource("__bindBuffer_" + target, obj);
3026926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
3027926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
3028926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {number} target
3029f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @param {!WebGLTexture} obj
3030f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
3031926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
3032926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["bindTexture"] = function(target, obj)
3033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
3034e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                this._resource.currentBinding(target); // To call WebGLBoundResource.prototype.pushBinding().
3035f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                var gl = /** @type {!WebGLRenderingContext} */ (this._originalObject);
3036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                var currentTextureBinding = /** @type {number} */ (gl.getParameter(gl.ACTIVE_TEXTURE));
3037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                this._resource._registerBoundResource("__bindTexture_" + target + "_" + currentTextureBinding, obj);
3038926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
3039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
3040f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @param {!WebGLProgram} program
3041f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
3042926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
3043926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["useProgram"] = function(program)
3044926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
3045926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                this._resource._registerBoundResource("__useProgram", program);
3046926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
3047926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            /**
3048926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             * @param {number} index
3049f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)             * @this {Resource.WrapFunction}
3050926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)             */
3051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["vertexAttribPointer"] = function(index)
3052926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            {
3053f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                var gl = /** @type {!WebGLRenderingContext} */ (this._originalObject);
3054926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                this._resource._registerBoundResource("__vertexAttribPointer_" + index, gl.getParameter(gl.ARRAY_BUFFER_BINDING));
3055926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
3056926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
30575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            WebGLRenderingContextResource._wrapFunctions = wrapFunctions;
30585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3059a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
3060a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        /**
3061a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         * @param {string} methodName
3062a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         * @param {function(this:Resource, !Call)=} pushCallFunc
3063a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         */
3064a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        function stateModifyingWrapFunction(methodName, pushCallFunc)
3065a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        {
3066a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (pushCallFunc) {
3067a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                /**
3068f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                 * @param {!Object|number} target
3069f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                 * @this {Resource.WrapFunction}
3070a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                 */
3071a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                wrapFunctions[methodName] = function(target)
3072a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                {
3073a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                    var resource = this._resource.currentBinding(target);
3074a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                    if (resource)
3075a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                        pushCallFunc.call(resource, this.call());
3076a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                }
3077a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            } else {
3078a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                /**
3079f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                 * @param {!Object|number} target
3080f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                 * @this {Resource.WrapFunction}
3081a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                 */
3082a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                wrapFunctions[methodName] = function(target)
3083a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                {
3084a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                    var resource = this._resource.currentBinding(target);
3085a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                    if (resource)
3086a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                        resource.pushCall(this.call());
3087a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                }
3088a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            }
3089a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
3090a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
30915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return wrapFunctions;
30925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
30935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    __proto__: ContextResource.prototype
30955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
30965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
30975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
30985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 2D Canvas
30995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
31005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
31025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
3103926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @extends {ContextResource}
31045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {!CanvasRenderingContext2D} context
31055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
3106926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CanvasRenderingContext2DResource(context)
31075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3108926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ContextResource.call(this, context, "CanvasRenderingContext2D");
31095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
31105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
31125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
31135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {!Array.<string>}
31145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
31155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CanvasRenderingContext2DResource.AttributeProperties = [
31165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "strokeStyle",
31175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "fillStyle",
31185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "globalAlpha",
31195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "lineWidth",
31205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "lineCap",
31215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "lineJoin",
31225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "miterLimit",
31235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "shadowOffsetX",
31245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "shadowOffsetY",
31255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "shadowBlur",
31265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "shadowColor",
31275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "globalCompositeOperation",
31285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "font",
31295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "textAlign",
31305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "textBaseline",
31315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "lineDashOffset",
31327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    "imageSmoothingEnabled",
31335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "webkitLineDash",
31345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "webkitLineDashOffset"
31355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)];
31365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
31385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
31395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {!Array.<string>}
31405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
31415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CanvasRenderingContext2DResource.PathMethods = [
31425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "beginPath",
31435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "moveTo",
31445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "closePath",
31455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "lineTo",
31465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "quadraticCurveTo",
31475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "bezierCurveTo",
31485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "arcTo",
31495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "arc",
31505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "rect"
31515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)];
31525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
31545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @const
31555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @type {!Array.<string>}
31565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
31575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CanvasRenderingContext2DResource.TransformationMatrixMethods = [
31585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "scale",
31595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "rotate",
31605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "translate",
31615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "transform",
31625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    "setTransform"
31635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)];
31645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3165926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
3167926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {!Object.<string, boolean>}
3168926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3169926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CanvasRenderingContext2DResource.DrawingMethods = TypeUtils.createPrefixedPropertyNamesSet([
3170926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "clearRect",
3171926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "drawImage",
3172926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "drawImageFromRect",
3173926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "drawCustomFocusRing",
317407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    "drawFocusIfNeeded",
3175926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "fill",
3176926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "fillRect",
3177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "fillText",
3178926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "putImageData",
3179926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "putImageDataHD",
3180926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "stroke",
3181926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "strokeRect",
3182926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    "strokeText"
3183926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)]);
3184926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
31855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)CanvasRenderingContext2DResource.prototype = {
31865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3187926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @override (overrides @return type)
3188f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!CanvasRenderingContext2D}
3189926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    wrappedObject: function()
3191926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
3192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._wrappedObject;
3193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3194926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3195926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
31965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
3197926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {string}
3198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    toDataURL: function()
3200926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
3201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this.wrappedObject().canvas.toDataURL();
3202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3203926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3204926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3205926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @override
3206f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Array.<!TypeUtils.InternalResourceStateDescriptor>}
32077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
32087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    currentState: function()
32097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
32107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var result = [];
32117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var state = this._internalCurrentState(null);
32127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        for (var pname in state)
32137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            result.push({ name: pname, value: state[pname] });
3214e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        result.push({ name: "context", value: this.contextResource() });
32157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return result;
32167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
32177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
32187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
3219f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Cache.<!ReplayableResource>} cache
32207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {!Object.<string, *>}
32217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
32227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _internalCurrentState: function(cache)
32237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
32247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        /**
3225f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @param {!Resource|*} obj
3226f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @return {!Resource|!ReplayableResource|*}
32277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch         */
32287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        function maybeToReplayable(obj)
32297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        {
32307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return cache ? Resource.toReplayable(obj, cache) : (Resource.forObject(obj) || obj);
32317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
32327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
32337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var ctx = this.wrappedObject();
32347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var state = Object.create(null);
32357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        CanvasRenderingContext2DResource.AttributeProperties.forEach(function(attribute) {
32367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (attribute in ctx)
32377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                state[attribute] = maybeToReplayable(ctx[attribute]);
32387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        });
32397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (ctx.getLineDash)
32407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            state.lineDash = ctx.getLineDash();
32417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return state;
32427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
32437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
32447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
3245f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Object.<string, *>} state
3246f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
32477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
32487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _applyAttributesState: function(state, cache)
32497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
32507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (!state)
32517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            return;
32527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var ctx = this.wrappedObject();
32537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        for (var attribute in state) {
32547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (attribute === "lineDash") {
32557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                if (ctx.setLineDash)
3256f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                    ctx.setLineDash(/** @type {!Array.<number>} */ (state[attribute]));
32577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            } else
32587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                ctx[attribute] = ReplayableResource.replay(state[attribute], cache);
32597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
32607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
32617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
32627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
32637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @override
3264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
3265f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!ReplayableResource>} cache
32665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
32675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _populateReplayableData: function(data, cache)
32685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
32695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var ctx = this.wrappedObject();
32707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        // FIXME: Convert resources in the state (CanvasGradient, CanvasPattern) to Replayable.
32717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        data.currentAttributes = this._internalCurrentState(null);
3272f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        data.originalCanvasCloned = TypeUtils.cloneIntoCanvas(/** @type {!HTMLCanvasElement} */ (ctx.canvas));
32735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (ctx.getContextAttributes)
32745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            data.originalContextAttributes = ctx.getContextAttributes();
32755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
32765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
32785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
3279926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Object} data
3280f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Cache.<!Resource>} cache
32815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
32825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _doReplayCalls: function(data, cache)
32835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3284926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var canvas = TypeUtils.cloneIntoCanvas(data.originalCanvasCloned);
32855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        var ctx = /** @type {!CanvasRenderingContext2D} */ (Resource.wrappedObject(canvas.getContext("2d", data.originalContextAttributes)));
32865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.setWrappedObject(ctx);
32875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = data.calls.length; i < n; ++i) {
3289f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            var replayableCall = /** @type {!ReplayableCall} */ (data.calls[i]);
32905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (replayableCall.functionName() === "save")
32917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                this._applyAttributesState(replayableCall.attachment("canvas2dAttributesState"), cache);
32925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._calls.push(replayableCall.replay(cache));
32935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
32947757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        this._applyAttributesState(data.currentAttributes, cache);
32955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
32965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3298926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
32995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
33005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall_setTransform: function(call)
33015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
33025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var saveCallIndex = this._lastIndexOfMatchingSaveCall();
33035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var index = this._lastIndexOfAnyCall(CanvasRenderingContext2DResource.PathMethods);
33045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        index = Math.max(index, saveCallIndex);
33055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._removeCallsFromLog(CanvasRenderingContext2DResource.TransformationMatrixMethods, index + 1))
33065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._removeAllObsoleteCallsFromLog();
33075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.pushCall(call);
33085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
33095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
33125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
33135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall_beginPath: function(call)
33145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
33155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var index = this._lastIndexOfAnyCall(["clip"]);
33165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._removeCallsFromLog(CanvasRenderingContext2DResource.PathMethods, index + 1))
33175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._removeAllObsoleteCallsFromLog();
33185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.pushCall(call);
33195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
33205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3322926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
33235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
33245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall_save: function(call)
33255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
33267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        // FIXME: Convert resources in the state (CanvasGradient, CanvasPattern) to Replayable.
33277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        call.setAttachment("canvas2dAttributesState", this._internalCurrentState(null));
33285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.pushCall(call);
33295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
33305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
3332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
33335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
33345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pushCall_restore: function(call)
33355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
33365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lastIndexOfSave = this._lastIndexOfMatchingSaveCall();
33375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (lastIndexOfSave === -1)
33385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
33395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._calls[lastIndexOfSave].setAttachment("canvas2dAttributesState", null); // No longer needed, free memory.
33405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var modified = false;
33425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._removeCallsFromLog(["clip"], lastIndexOfSave + 1))
33435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            modified = true;
33445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lastIndexOfAnyPathMethod = this._lastIndexOfAnyCall(CanvasRenderingContext2DResource.PathMethods);
33465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var index = Math.max(lastIndexOfSave, lastIndexOfAnyPathMethod);
33475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._removeCallsFromLog(CanvasRenderingContext2DResource.TransformationMatrixMethods, index + 1))
33485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            modified = true;
33495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (modified)
33515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._removeAllObsoleteCallsFromLog();
33525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lastCall = this._calls[this._calls.length - 1];
33545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (lastCall && lastCall.functionName() === "save")
33555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._calls.pop();
33565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
33575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this.pushCall(call);
33585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
33595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
33615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number=} fromIndex
33625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
33635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
33645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _lastIndexOfMatchingSaveCall: function(fromIndex)
33655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
33665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (typeof fromIndex !== "number")
33675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fromIndex = this._calls.length - 1;
33685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
33695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fromIndex = Math.min(fromIndex, this._calls.length - 1);
33705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var stackDepth = 1;
33715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = fromIndex; i >= 0; --i) {
33725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var functionName = this._calls[i].functionName();
33735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (functionName === "restore")
33745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ++stackDepth;
33755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else if (functionName === "save") {
33765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                --stackDepth;
33775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!stackDepth)
33785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return i;
33795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
33805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
33815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return -1;
33825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
33835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
33855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {!Array.<string>} functionNames
33865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number=} fromIndex
33875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
33885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
33895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _lastIndexOfAnyCall: function(functionNames, fromIndex)
33905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
33915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (typeof fromIndex !== "number")
33925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fromIndex = this._calls.length - 1;
33935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
33945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fromIndex = Math.min(fromIndex, this._calls.length - 1);
33955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = fromIndex; i >= 0; --i) {
33965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (functionNames.indexOf(this._calls[i].functionName()) !== -1)
33975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return i;
33985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
33995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return -1;
34005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _removeAllObsoleteCallsFromLog: function()
34035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
34045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove all PATH methods between clip() and beginPath() calls.
34055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lastIndexOfBeginPath = this._lastIndexOfAnyCall(["beginPath"]);
34065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (lastIndexOfBeginPath !== -1) {
34075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var index = this._lastIndexOfAnyCall(["clip"], lastIndexOfBeginPath - 1);
34085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._removeCallsFromLog(CanvasRenderingContext2DResource.PathMethods, index + 1, lastIndexOfBeginPath);
34095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            lastIndexOfBeginPath = this._lastIndexOfAnyCall(["beginPath"], index - 1);
34105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
34115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove all TRASFORMATION MATRIX methods before restore() or setTransform() but after any PATH or corresponding save() method.
34135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var lastRestore = this._lastIndexOfAnyCall(["restore", "setTransform"]);
34145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (lastRestore !== -1) {
34155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var saveCallIndex = this._lastIndexOfMatchingSaveCall(lastRestore - 1);
34165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var index = this._lastIndexOfAnyCall(CanvasRenderingContext2DResource.PathMethods, lastRestore - 1);
34175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            index = Math.max(index, saveCallIndex);
34185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._removeCallsFromLog(CanvasRenderingContext2DResource.TransformationMatrixMethods, index + 1, lastRestore);
34195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            lastRestore = this._lastIndexOfAnyCall(["restore", "setTransform"], index - 1);
34205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
34215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove all save-restore consecutive pairs.
34235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var restoreCalls = 0;
34245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = this._calls.length - 1; i >= 0; --i) {
34255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var functionName = this._calls[i].functionName();
34265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (functionName === "restore") {
34275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ++restoreCalls;
34285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
34295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
34305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (functionName === "save" && restoreCalls > 0) {
34315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var saveCallIndex = i;
34325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (var j = i - 1; j >= 0 && i - j < restoreCalls; --j) {
34335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    if (this._calls[j].functionName() === "save")
34345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        saveCallIndex = j;
34355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    else
34365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        break;
34375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
34385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this._calls.splice(saveCallIndex, (i - saveCallIndex + 1) * 2);
34395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                i = saveCallIndex;
34405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
34415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            restoreCalls = 0;
34425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
34435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
34465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {!Array.<string>} functionNames
34475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} fromIndex
34485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number=} toIndex
34495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {boolean}
34505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
34515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _removeCallsFromLog: function(functionNames, fromIndex, toIndex)
34525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
34535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var oldLength = this._calls.length;
34545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (typeof toIndex !== "number")
34555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            toIndex = oldLength;
34565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
34575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            toIndex = Math.min(toIndex, oldLength);
34585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var newIndex = Math.min(fromIndex, oldLength);
34595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = newIndex; i < toIndex; ++i) {
34605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var call = this._calls[i];
34615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (functionNames.indexOf(call.functionName()) === -1)
34625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this._calls[newIndex++] = call;
34635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
34645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (newIndex >= toIndex)
34655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return false;
34665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._calls.splice(newIndex, toIndex - newIndex);
34675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
34685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
34695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
34715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @override
3472f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object.<string, !Function>}
34735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
34745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _customWrapFunctions: function()
34755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
34765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var wrapFunctions = CanvasRenderingContext2DResource._wrapFunctions;
34775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!wrapFunctions) {
34785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            wrapFunctions = Object.create(null);
34795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3480926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createLinearGradient"] = Resource.WrapFunction.resourceFactoryMethod(LogEverythingResource, "CanvasGradient");
3481926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createRadialGradient"] = Resource.WrapFunction.resourceFactoryMethod(LogEverythingResource, "CanvasGradient");
3482926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            wrapFunctions["createPattern"] = Resource.WrapFunction.resourceFactoryMethod(LogEverythingResource, "CanvasPattern");
34835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var i = 0, methodName; methodName = CanvasRenderingContext2DResource.TransformationMatrixMethods[i]; ++i)
3485926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                stateModifyingWrapFunction(methodName, methodName === "setTransform" ? this.pushCall_setTransform : undefined);
34865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var i = 0, methodName; methodName = CanvasRenderingContext2DResource.PathMethods[i]; ++i)
3487926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                stateModifyingWrapFunction(methodName, methodName === "beginPath" ? this.pushCall_beginPath : undefined);
34885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            stateModifyingWrapFunction("save", this.pushCall_save);
34905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            stateModifyingWrapFunction("restore", this.pushCall_restore);
34915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            stateModifyingWrapFunction("clip");
34925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            CanvasRenderingContext2DResource._wrapFunctions = wrapFunctions;
34945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3495a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
3496a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        /**
3497a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         * @param {string} methodName
3498a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         * @param {function(this:Resource, !Call)=} func
3499a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         */
3500a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        function stateModifyingWrapFunction(methodName, func)
3501a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        {
3502a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (func) {
3503f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                /** @this {Resource.WrapFunction} */
3504a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                wrapFunctions[methodName] = function()
3505a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                {
3506a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                    func.call(this._resource, this.call());
3507a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                }
3508a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            } else {
3509f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                /** @this {Resource.WrapFunction} */
3510a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                wrapFunctions[methodName] = function()
3511a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                {
3512a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                    this._resource.pushCall(this.call());
3513a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                }
3514a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            }
3515a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
3516a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
35175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return wrapFunctions;
35185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
35195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3520926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    __proto__: ContextResource.prototype
35215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
35225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
35245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
3525926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!Object.<string, boolean>=} drawingMethodNames
3526926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3527926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)function CallFormatter(drawingMethodNames)
3528926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
3529926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._drawingMethodNames = drawingMethodNames || Object.create(null);
3530926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3531926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3532926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CallFormatter.prototype = {
3533926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3534926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!ReplayableCall} replayableCall
3535e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string=} objectGroup
3536926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!Object}
3537926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3538e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    formatCall: function(replayableCall, objectGroup)
3539926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
3540926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var result = {};
3541926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var functionName = replayableCall.functionName();
3542926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (functionName) {
3543926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            result.functionName = functionName;
3544e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.arguments = [];
3545e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var args = replayableCall.args();
3546e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            for (var i = 0, n = args.length; i < n; ++i)
3547e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                result.arguments.push(this.formatValue(args[i], objectGroup));
3548926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (replayableCall.result() !== undefined)
3549e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                result.result = this.formatValue(replayableCall.result(), objectGroup);
3550926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (this._drawingMethodNames[functionName])
3551926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                result.isDrawingCall = true;
3552926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        } else {
3553591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            result.property = replayableCall.propertyName();
3554e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.value = this.formatValue(replayableCall.propertyValue(), objectGroup);
3555926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
3556926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return result;
3557926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
3558926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3559926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
3560926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {*} value
3561e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string=} objectGroup
3562521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     * @return {!CanvasAgent.CallArgument}
3563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
3564e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    formatValue: function(value, objectGroup)
3565926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
35667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (value instanceof Resource || value instanceof ReplayableResource) {
3567591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return {
3568591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                description: value.description(),
3569591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                resourceId: CallFormatter.makeStringResourceId(value.id())
3570591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            };
3571591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
3572591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
3573e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var remoteObject = injectedScript.wrapObject(value, objectGroup || "", true, false);
3574e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var description = remoteObject.description || ("" + value);
3575e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
3576591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var result = {
3577e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            description: description,
3578f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            type: /** @type {!CanvasAgent.CallArgumentType} */ (remoteObject.type)
3579591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        };
3580591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (remoteObject.subtype)
3581f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            result.subtype = /** @type {!CanvasAgent.CallArgumentSubtype} */ (remoteObject.subtype);
3582e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (remoteObject.objectId) {
3583e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (objectGroup)
3584e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                result.remoteObject = remoteObject;
3585e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            else
3586e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                injectedScript.releaseObject(remoteObject.objectId);
3587e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
3588591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return result;
35897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    },
35907757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
35917757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    /**
3592e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string} name
3593e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {?string}
3594e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
3595e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    enumValueForName: function(name)
3596e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
3597e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return null;
3598e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
3599e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
3600e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
3601e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {number} value
3602f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<string>=} options
3603e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {?string}
3604e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
3605e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    enumNameForValue: function(value, options)
3606e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
3607e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return null;
3608e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
3609e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
3610e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
3611f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<!TypeUtils.InternalResourceStateDescriptor>} descriptors
3612e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string=} objectGroup
36137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {!Array.<!CanvasAgent.ResourceStateDescriptor>}
36147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     */
3615e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    formatResourceStateDescriptors: function(descriptors, objectGroup)
36167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    {
36177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var result = [];
36187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        for (var i = 0, n = descriptors.length; i < n; ++i) {
36197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var d = descriptors[i];
3620e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var item;
36217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            if (d.values)
3622e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                item = { name: d.name, values: this.formatResourceStateDescriptors(d.values, objectGroup) };
3623e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            else {
3624e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                item = { name: d.name, value: this.formatValue(d.value, objectGroup) };
3625e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (d.valueIsEnum && typeof d.value === "number") {
3626e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    var enumName = this.enumNameForValue(d.value);
3627e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                    if (enumName)
3628e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                        item.value.enumName = enumName;
3629e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                }
3630e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
3631e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            var enumValue = this.enumValueForName(d.name);
3632e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (enumValue)
3633e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                item.enumValueForName = enumValue;
3634e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (d.isArray)
3635e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                item.isArray = true;
3636e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.push(item);
36377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
36387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return result;
3639926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3640926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3641926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3642926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3643926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @const
3644926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @type {!Object.<string, !CallFormatter>}
3645926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3646926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CallFormatter._formatters = {};
3647926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3648926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
3649926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} resourceName
3650926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!CallFormatter} callFormatter
3651926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
3652926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CallFormatter.register = function(resourceName, callFormatter)
3653926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
3654926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    CallFormatter._formatters[resourceName] = callFormatter;
3655926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3656926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3657926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
36587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch * @param {!Resource|!ReplayableResource} resource
3659e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch * @return {!CallFormatter}
3660926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
36617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCallFormatter.forResource = function(resource)
3662926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
3663926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var formatter = CallFormatter._formatters[resource.name()];
3664926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (!formatter) {
36657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var contextResource = resource.contextResource();
36667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        formatter = (contextResource && CallFormatter._formatters[contextResource.name()]) || new CallFormatter();
3667926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
3668e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    return formatter;
3669926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3670926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3671521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)/**
3672591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * @param {number} resourceId
3673f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) * @return {!CanvasAgent.ResourceId}
3674591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch */
3675591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochCallFormatter.makeStringResourceId = function(resourceId)
3676591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
3677591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return "{\"injectedScriptId\":" + injectedScriptId + ",\"resourceId\":" + resourceId + "}";
3678591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
3679591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
3680591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch/**
3681521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * @constructor
3682521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * @extends {CallFormatter}
3683521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * @param {!Object.<string, boolean>} drawingMethodNames
3684521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) */
3685521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)function WebGLCallFormatter(drawingMethodNames)
3686521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
3687521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    CallFormatter.call(this, drawingMethodNames);
3688521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
3689521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3690521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)/**
3691521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * NOTE: The code below is generated from the IDL file by the script:
3692521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * /devtools/scripts/check_injected_webgl_calls_info.py
3693521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) *
3694521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) * @type {!Array.<{aname: string, enum: (!Array.<number>|undefined), bitfield: (!Array.<number>|undefined), returnType: string, hints: (!Array.<string>|undefined)}>}
3695521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) */
3696521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)WebGLCallFormatter.EnumsInfo = [
3697521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "activeTexture", "enum": [0]},
3698521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "bindBuffer", "enum": [0]},
3699521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "bindFramebuffer", "enum": [0]},
3700521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "bindRenderbuffer", "enum": [0]},
3701521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "bindTexture", "enum": [0]},
3702521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "blendEquation", "enum": [0]},
3703521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "blendEquationSeparate", "enum": [0, 1]},
3704521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "blendFunc", "enum": [0, 1], "hints": ["ZERO", "ONE"]},
3705521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "blendFuncSeparate", "enum": [0, 1, 2, 3], "hints": ["ZERO", "ONE"]},
3706521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "bufferData", "enum": [0, 2]},
3707521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "bufferSubData", "enum": [0]},
3708521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "checkFramebufferStatus", "enum": [0], "returnType": "enum"},
3709521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "clear", "bitfield": [0]},
3710521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "compressedTexImage2D", "enum": [0, 2]},
3711521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "compressedTexSubImage2D", "enum": [0, 6]},
3712521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "copyTexImage2D", "enum": [0, 2]},
3713521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "copyTexSubImage2D", "enum": [0]},
3714521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "createShader", "enum": [0]},
3715521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "cullFace", "enum": [0]},
3716521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "depthFunc", "enum": [0]},
3717521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "disable", "enum": [0]},
3718521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "drawArrays", "enum": [0], "hints": ["POINTS", "LINES"]},
3719521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "drawElements", "enum": [0, 2], "hints": ["POINTS", "LINES"]},
3720521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "enable", "enum": [0]},
3721521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "framebufferRenderbuffer", "enum": [0, 1, 2]},
3722521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "framebufferTexture2D", "enum": [0, 1, 2]},
3723521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "frontFace", "enum": [0]},
3724521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "generateMipmap", "enum": [0]},
3725521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getBufferParameter", "enum": [0, 1]},
3726521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getError", "hints": ["NO_ERROR"], "returnType": "enum"},
3727521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getFramebufferAttachmentParameter", "enum": [0, 1, 2]},
3728591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {"aname": "getParameter", "enum": [0]},
3729521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getProgramParameter", "enum": [1]},
3730521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getRenderbufferParameter", "enum": [0, 1]},
3731521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getShaderParameter", "enum": [1]},
3732521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getShaderPrecisionFormat", "enum": [0, 1]},
3733591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {"aname": "getTexParameter", "enum": [0, 1], "returnType": "enum"},
3734521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getVertexAttrib", "enum": [1]},
3735521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "getVertexAttribOffset", "enum": [1]},
3736521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "hint", "enum": [0, 1]},
3737521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "isEnabled", "enum": [0]},
3738521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "pixelStorei", "enum": [0]},
3739521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "readPixels", "enum": [4, 5]},
3740521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "renderbufferStorage", "enum": [0, 1]},
3741521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "stencilFunc", "enum": [0]},
3742521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "stencilFuncSeparate", "enum": [0, 1]},
3743521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "stencilMaskSeparate", "enum": [0]},
3744521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "stencilOp", "enum": [0, 1, 2], "hints": ["ZERO", "ONE"]},
3745521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "stencilOpSeparate", "enum": [0, 1, 2, 3], "hints": ["ZERO", "ONE"]},
3746521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "texParameterf", "enum": [0, 1, 2]},
3747521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "texParameteri", "enum": [0, 1, 2]},
3748521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "texImage2D", "enum": [0, 2, 6, 7]},
3749521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "texImage2D", "enum": [0, 2, 3, 4]},
3750521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "texSubImage2D", "enum": [0, 6, 7]},
3751521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "texSubImage2D", "enum": [0, 4, 5]},
3752521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {"aname": "vertexAttribPointer", "enum": [2]}
3753521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)];
3754521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3755521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)WebGLCallFormatter.prototype = {
3756521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    /**
3757521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     * @override
3758521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     * @param {!ReplayableCall} replayableCall
3759e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string=} objectGroup
3760521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     * @return {!Object}
3761521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     */
3762e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    formatCall: function(replayableCall, objectGroup)
3763521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {
3764e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var result = CallFormatter.prototype.formatCall.call(this, replayableCall, objectGroup);
3765521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (!result.functionName)
3766521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            return result;
3767521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var enumsInfo = this._findEnumsInfo(replayableCall);
3768521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (!enumsInfo)
3769521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            return result;
3770521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var enumArgsIndexes = enumsInfo["enum"] || [];
3771521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var i = 0, n = enumArgsIndexes.length; i < n; ++i) {
3772521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var index = enumArgsIndexes[i];
3773521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var callArgument = result.arguments[index];
3774e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            this._formatEnumValue(callArgument, enumsInfo["hints"]);
3775521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3776521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var bitfieldArgsIndexes = enumsInfo["bitfield"] || [];
3777521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var i = 0, n = bitfieldArgsIndexes.length; i < n; ++i) {
3778521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var index = bitfieldArgsIndexes[i];
3779521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var callArgument = result.arguments[index];
3780e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            this._formatEnumBitmaskValue(callArgument, enumsInfo["hints"]);
3781521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3782e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (enumsInfo.returnType === "enum")
3783e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            this._formatEnumValue(result.result, enumsInfo["hints"]);
3784e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        else if (enumsInfo.returnType === "bitfield")
3785e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            this._formatEnumBitmaskValue(result.result, enumsInfo["hints"]);
3786521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return result;
3787521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    },
3788521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3789521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    /**
3790e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
3791e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {string} name
3792e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {?string}
3793e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
3794e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    enumValueForName: function(name)
3795e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
3796e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        this._initialize();
3797e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (name in this._enumNameToValue)
3798e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return "" + this._enumNameToValue[name];
3799e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return null;
3800e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
3801e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
3802e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
3803e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @override
3804e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {number} value
3805f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<string>=} options
3806e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @return {?string}
3807e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     */
3808e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    enumNameForValue: function(value, options)
3809e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    {
3810e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        this._initialize();
3811e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        options = options || [];
3812e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (var i = 0, n = options.length; i < n; ++i) {
3813e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            if (this._enumNameToValue[options[i]] === value)
3814e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                return options[i];
3815e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
3816e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var names = this._enumValueToNames[value];
3817e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!names || names.length !== 1)
3818e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return null;
3819e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return names[0];
3820e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    },
3821e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
3822e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    /**
3823521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     * @param {!ReplayableCall} replayableCall
3824f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?Object}
3825521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     */
3826521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    _findEnumsInfo: function(replayableCall)
3827521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {
3828521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        function findMaxArgumentIndex(enumsInfo)
3829521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        {
3830521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var result = -1;
3831521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var enumArgsIndexes = enumsInfo["enum"] || [];
3832521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            for (var i = 0, n = enumArgsIndexes.length; i < n; ++i)
3833521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                result = Math.max(result, enumArgsIndexes[i]);
3834521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var bitfieldArgsIndexes = enumsInfo["bitfield"] || [];
3835521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            for (var i = 0, n = bitfieldArgsIndexes.length; i < n; ++i)
3836521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                result = Math.max(result, bitfieldArgsIndexes[i]);
3837521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            return result;
3838521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3839521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3840521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var result = null;
3841521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var i = 0, enumsInfo; enumsInfo = WebGLCallFormatter.EnumsInfo[i]; ++i) {
3842521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (enumsInfo["aname"] !== replayableCall.functionName())
3843521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                continue;
3844521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var argsCount = replayableCall.args().length;
3845521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var maxArgumentIndex = findMaxArgumentIndex(enumsInfo);
3846521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (maxArgumentIndex >= argsCount)
3847521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                continue;
3848521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            // To resolve ambiguity (see texImage2D, texSubImage2D) choose description with max argument indexes.
3849521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (!result || findMaxArgumentIndex(result) < maxArgumentIndex)
3850521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                result = enumsInfo;
3851521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3852521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return result;
3853521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    },
3854521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3855521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    /**
3856e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {?CanvasAgent.CallArgument|undefined} callArgument
3857f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<string>=} options
3858521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     */
3859e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _formatEnumValue: function(callArgument, options)
3860521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {
3861e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!callArgument || isNaN(callArgument.description))
3862e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return;
3863521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        this._initialize();
3864e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var value = +callArgument.description;
3865e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var enumName = this.enumNameForValue(value, options);
3866e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (enumName)
3867e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            callArgument.enumName = enumName;
3868521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    },
3869521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3870521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    /**
3871e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)     * @param {?CanvasAgent.CallArgument|undefined} callArgument
3872f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array.<string>=} options
3873521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     */
3874e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    _formatEnumBitmaskValue: function(callArgument, options)
3875521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {
3876e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (!callArgument || isNaN(callArgument.description))
3877e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return;
3878521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        this._initialize();
3879e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        var value = +callArgument.description;
3880521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        options = options || [];
3881521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        /** @type {!Array.<string>} */
3882521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var result = [];
3883521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var i = 0, n = options.length; i < n; ++i) {
3884521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var bitValue = this._enumNameToValue[options[i]] || 0;
3885521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (value & bitValue) {
3886521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                result.push(options[i]);
3887521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                value &= ~bitValue;
3888521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            }
3889521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3890521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        while (value) {
3891521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var nextValue = value & (value - 1);
3892521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var bitValue = value ^ nextValue;
3893521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var names = this._enumValueToNames[bitValue];
3894521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (!names || names.length !== 1) {
3895521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                console.warn("Ambiguous WebGL enum names for value " + bitValue + ": " + names);
3896e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                return;
3897521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            }
3898521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            result.push(names[0]);
3899521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            value = nextValue;
3900521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3901521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        result.sort();
3902e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        callArgument.enumName = result.join(" | ");
3903521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    },
3904521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3905521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    _initialize: function()
3906521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {
3907521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        if (this._enumNameToValue)
3908521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            return;
3909521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3910521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        /** @type {!Object.<string, number>} */
3911521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        this._enumNameToValue = Object.create(null);
3912521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        /** @type {!Object.<number, !Array.<string>>} */
3913521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        this._enumValueToNames = Object.create(null);
3914521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3915521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        /**
3916f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @param {?Object} obj
3917521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)         * @this WebGLCallFormatter
3918521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)         */
3919521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        function iterateWebGLEnums(obj)
3920521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        {
3921521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (!obj)
3922521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                return;
3923521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            for (var property in obj) {
3924e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (TypeUtils.isEnumPropertyName(property, obj)) {
3925521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    var value = /** @type {number} */ (obj[property]);
3926521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    this._enumNameToValue[property] = value;
3927521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    var names = this._enumValueToNames[value];
3928521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    if (names) {
3929521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                        if (names.indexOf(property) === -1)
3930521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                            names.push(property);
3931521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    } else
3932521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                        this._enumValueToNames[value] = [property];
3933521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                }
3934521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            }
3935521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3936521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3937521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        /**
3938521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)         * @param {!Array.<string>} values
3939521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)         * @return {string}
3940521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)         */
3941521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        function commonSubstring(values)
3942521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        {
3943521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var length = values.length;
3944521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            for (var i = 0; i < length; ++i) {
3945521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                for (var j = 0; j < length; ++j) {
3946521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    if (values[j].indexOf(values[i]) === -1)
3947521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                        break;
3948521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                }
3949521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                if (j === length)
3950521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    return values[i];
3951521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            }
3952521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            return "";
3953521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3954521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3955521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var gl = this._createUninstrumentedWebGLRenderingContext();
3956521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        iterateWebGLEnums.call(this, gl);
3957521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3958521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var extensions = gl.getSupportedExtensions() || [];
3959521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var i = 0, n = extensions.length; i < n; ++i)
3960521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            iterateWebGLEnums.call(this, gl.getExtension(extensions[i]));
3961521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3962521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        // Sort to get rid of ambiguity.
3963521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var value in this._enumValueToNames) {
39645d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            var numericValue = Number(value);
39655d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            var names = this._enumValueToNames[numericValue];
3966521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (names.length > 1) {
3967521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                // Choose one enum name if possible. For example:
3968521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                //   [BLEND_EQUATION, BLEND_EQUATION_RGB] => BLEND_EQUATION
3969521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                //   [COLOR_ATTACHMENT0, COLOR_ATTACHMENT0_WEBGL] => COLOR_ATTACHMENT0
3970521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                var common = commonSubstring(names);
3971521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                if (common)
39725d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                    this._enumValueToNames[numericValue] = [common];
3973521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                else
39745d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)                    this._enumValueToNames[numericValue] = names.sort();
3975521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            }
3976521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3977521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    },
3978521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3979521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    /**
3980f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?WebGLRenderingContext}
3981521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)     */
3982521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    _createUninstrumentedWebGLRenderingContext: function()
3983521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    {
3984f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var canvas = /** @type {!HTMLCanvasElement} */ (inspectedWindow.document.createElement("canvas"));
3985521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        var contextIds = ["experimental-webgl", "webkit-3d", "3d"];
3986521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        for (var i = 0, contextId; contextId = contextIds[i]; ++i) {
3987521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            var context = canvas.getContext(contextId);
3988521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (context)
3989f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                return /** @type {!WebGLRenderingContext} */ (Resource.wrappedObject(context));
3990521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
3991521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return null;
3992521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    },
3993521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3994521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    __proto__: CallFormatter.prototype
3995521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
3996521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
3997926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)CallFormatter.register("CanvasRenderingContext2D", new CallFormatter(CanvasRenderingContext2DResource.DrawingMethods));
3998521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)CallFormatter.register("WebGLRenderingContext", new WebGLCallFormatter(WebGLRenderingContextResource.DrawingMethods));
3999926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4000926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
4001926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @constructor
40025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
40035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function TraceLog()
40045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4005a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    /** @type {!Array.<!ReplayableCall>} */
40065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._replayableCalls = [];
4007f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {!Cache.<!ReplayableResource>} */
40085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._replayablesCache = new Cache();
4009926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {!Object.<number, boolean>} */
4010926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._frameEndCallIndexes = {};
4011a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    /** @type {!Object.<number, boolean>} */
4012a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    this._resourcesCreatedInThisTraceLog = {};
40135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
40145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TraceLog.prototype = {
40165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
40175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
40185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
40195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size: function()
40205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
40215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._replayableCalls.length;
40225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
40235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4025a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @return {!Array.<!ReplayableCall>}
40265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
40275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    replayableCalls: function()
40285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
40295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._replayableCalls;
40305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
40315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4033926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number} id
4034f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!ReplayableResource|undefined}
4035926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4036926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    replayableResource: function(id)
4037926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
40387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return this._replayablesCache.get(id);
4039926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4040926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4041926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4042a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @param {number} resourceId
4043a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @return {boolean}
4044a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     */
4045a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    createdInThisTraceLog: function(resourceId)
4046a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    {
4047a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return !!this._resourcesCreatedInThisTraceLog[resourceId];
4048a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    },
4049a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
4050a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    /**
4051926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Resource} resource
40525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
40535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    captureResource: function(resource)
40545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
40555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resource.toReplayable(this._replayablesCache);
40565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
40575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4059926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
40605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
40615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    addCall: function(call)
40625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4063a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var resource = Resource.forObject(call.result());
4064a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        if (resource && !this._replayablesCache.has(resource.id()))
4065a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            this._resourcesCreatedInThisTraceLog[resource.id()] = true;
40665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._replayableCalls.push(call.toReplayable(this._replayablesCache));
4067926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4068926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4069926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    addFrameEndMark: function()
4070926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4071926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var index = this._replayableCalls.length - 1;
4072926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (index >= 0)
4073926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._frameEndCallIndexes[index] = true;
4074926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4075926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4076926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4077926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number} index
4078926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {boolean}
4079926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4080926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    isFrameEndCallAt: function(index)
4081926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4082926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return !!this._frameEndCallIndexes[index];
40835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
40845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
40855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
40875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
4088926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {!TraceLog} traceLog
40895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
40905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function TraceLogPlayer(traceLog)
40915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4092926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {!TraceLog} */
40935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._traceLog = traceLog;
4094926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {number} */
40955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._nextReplayStep = 0;
4096f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {!Cache.<!Resource>} */
40975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._replayWorldCache = new Cache();
40985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
40995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TraceLogPlayer.prototype = {
41015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!TraceLog}
41035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
41045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    traceLog: function()
41055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
41065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._traceLog;
41075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
41085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number} id
4111f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Resource|undefined}
4112926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    replayWorldResource: function(id)
4114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
41157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return this._replayWorldCache.get(id);
4116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4118926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
41195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {number}
41205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
41215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    nextReplayStep: function()
41225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
41235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._nextReplayStep;
41245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
41255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    reset: function()
41275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
41285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._nextReplayStep = 0;
41295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._replayWorldCache.reset();
41305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
41315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
41335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} stepNum
4134a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @return {{replayTime:number, lastCall:(!Call)}}
41355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
41365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stepTo: function(stepNum)
41375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
41385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        stepNum = Math.min(stepNum, this._traceLog.size() - 1);
41395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        console.assert(stepNum >= 0);
41405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (this._nextReplayStep > stepNum)
41415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this.reset();
4142a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
4143a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        // Replay the calls' arguments first to warm-up, before measuring the actual replay time.
4144a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        this._replayCallArguments(stepNum);
4145a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
41465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var replayableCalls = this._traceLog.replayableCalls();
4147a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var replayedCalls = [];
4148a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        replayedCalls.length = stepNum - this._nextReplayStep + 1;
4149a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
4150a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var beforeTime = TypeUtils.now();
4151a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        for (var i = 0; this._nextReplayStep <= stepNum; ++this._nextReplayStep, ++i)
4152a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            replayedCalls[i] = replayableCalls[this._nextReplayStep].replay(this._replayWorldCache);
4153a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var replayTime = Math.max(0, TypeUtils.now() - beforeTime);
4154a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
4155a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        for (var i = 0, call; call = replayedCalls[i]; ++i)
4156a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            call.resource().onCallReplayed(call);
4157a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
4158a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return {
4159a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            replayTime: replayTime,
4160a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            lastCall: replayedCalls[replayedCalls.length - 1]
4161a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        };
41625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
41635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4164926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4165a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @param {number} stepNum
4166926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4167a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    _replayCallArguments: function(stepNum)
41685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4169a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        /**
4170a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         * @param {*} obj
4171f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)         * @this {TraceLogPlayer}
4172a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)         */
4173a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        function replayIfNotCreatedInThisTraceLog(obj)
4174a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        {
4175a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (!(obj instanceof ReplayableResource))
4176a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                return;
4177a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            var replayableResource = /** @type {!ReplayableResource} */ (obj);
4178a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            if (!this._traceLog.createdInThisTraceLog(replayableResource.id()))
4179a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)                replayableResource.replay(this._replayWorldCache)
4180a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
4181a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var replayableCalls = this._traceLog.replayableCalls();
4182a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        for (var i = this._nextReplayStep; i <= stepNum; ++i) {
4183a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            replayIfNotCreatedInThisTraceLog.call(this, replayableCalls[i].replayableResource());
4184a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            replayIfNotCreatedInThisTraceLog.call(this, replayableCalls[i].result());
4185a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            replayableCalls[i].args().forEach(replayIfNotCreatedInThisTraceLog.bind(this));
4186a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        }
41875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
41885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
41895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
41905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
41915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
41925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
41935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function ResourceTrackingManager()
41945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
41955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._capturing = false;
41965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._stopCapturingOnFrameEnd = false;
41975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._lastTraceLog = null;
41985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
41995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ResourceTrackingManager.prototype = {
42015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
42025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @return {boolean}
42035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
42045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    capturing: function()
42055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._capturing;
42075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4210f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {?TraceLog}
42115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
42125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    lastTraceLog: function()
42135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this._lastTraceLog;
42155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Resource} resource
42195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
42205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    registerResource: function(resource)
42215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resource.setManager(this);
42235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    startCapturing: function()
42265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._capturing)
42285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            this._lastTraceLog = new TraceLog();
42295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._capturing = true;
42305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._stopCapturingOnFrameEnd = false;
42315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4234f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!TraceLog=} traceLog
42355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
42365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    stopCapturing: function(traceLog)
42375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (traceLog && this._lastTraceLog !== traceLog)
42395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
42405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._capturing = false;
42415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._stopCapturingOnFrameEnd = false;
4242926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this._lastTraceLog)
4243926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._lastTraceLog.addFrameEndMark();
4244926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4245926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4246926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4247926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!TraceLog} traceLog
4248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4249926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    dropTraceLog: function(traceLog)
4250926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4251926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this.stopCapturing(traceLog);
4252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this._lastTraceLog === traceLog)
4253926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._lastTraceLog = null;
42545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    captureFrame: function()
42575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._lastTraceLog = new TraceLog();
42595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._capturing = true;
42605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._stopCapturingOnFrameEnd = true;
42615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4264926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Resource} resource
4265f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!Array|!Arguments} args
42665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
42675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    captureArguments: function(resource, args)
42685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._capturing)
42705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
42715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._lastTraceLog.captureResource(resource);
42725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = args.length; i < n; ++i) {
42735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var res = Resource.forObject(args[i]);
42745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (res)
42755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this._lastTraceLog.captureResource(res);
42765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
42775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4280926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {!Call} call
42815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
42825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    captureCall: function(call)
42835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
42845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!this._capturing)
42855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
42865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._lastTraceLog.addCall(call);
42875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
42885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4289926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    markFrameEnd: function()
42905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4291926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!this._lastTraceLog)
4292926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return;
4293926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._lastTraceLog.addFrameEndMark();
4294926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (this._stopCapturingOnFrameEnd && this._lastTraceLog.size())
4295926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this.stopCapturing(this._lastTraceLog);
42965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
42975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
42985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
42995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
43005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @constructor
43015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
4302926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var InjectedCanvasModule = function()
43035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4304926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {!ResourceTrackingManager} */
43055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._manager = new ResourceTrackingManager();
4306926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /** @type {number} */
43075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._lastTraceLogId = 0;
4308f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {!Object.<string, !TraceLog>} */
43095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    this._traceLogs = {};
4310f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    /** @type {!Object.<string, !TraceLogPlayer>} */
4311926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    this._traceLogPlayers = {};
43125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
43135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4314926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)InjectedCanvasModule.prototype = {
43155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
43165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {!WebGLRenderingContext} glContext
4317f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object}
43185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
43195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    wrapWebGLContext: function(glContext)
43205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4321926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var resource = Resource.forObject(glContext) || new WebGLRenderingContextResource(glContext);
43225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._manager.registerResource(resource);
43235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return resource.proxyObject();
43245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
43255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
43265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
43275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {!CanvasRenderingContext2D} context
4328f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!Object}
43295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
43305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    wrapCanvas2DContext: function(context)
43315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4332926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var resource = Resource.forObject(context) || new CanvasRenderingContext2DResource(context);
43335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this._manager.registerResource(resource);
43345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return resource.proxyObject();
43355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
43365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4337926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4338f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!CanvasAgent.TraceLogId}
4339926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
43405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    captureFrame: function()
43415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4342926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._callStartCapturingFunction(this._manager.captureFrame);
4343926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4344926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4345926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4346f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!CanvasAgent.TraceLogId}
4347926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4348926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    startCapturing: function()
4349926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4350926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return this._callStartCapturingFunction(this._manager.startCapturing);
4351926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4352926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4353926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    markFrameEnd: function()
4354926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4355926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._manager.markFrameEnd();
4356926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4357926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4358926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4359926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {function(this:ResourceTrackingManager)} func
4360f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!CanvasAgent.TraceLogId}
4361926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4362926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _callStartCapturingFunction: function(func)
4363926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4364926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var oldTraceLog = this._manager.lastTraceLog();
4365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        func.call(this._manager);
4366f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        var traceLog = /** @type {!TraceLog} */ (this._manager.lastTraceLog());
4367926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (traceLog === oldTraceLog) {
4368926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            for (var id in this._traceLogs) {
4369926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                if (this._traceLogs[id] === traceLog)
4370926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                    return id;
4371926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
4372926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
43735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var id = this._makeTraceLogId();
4374926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._traceLogs[id] = traceLog;
43755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return id;
43765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
43775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
43785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4379f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} id
4380926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4381926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    stopCapturing: function(id)
4382926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4383926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var traceLog = this._traceLogs[id];
4384926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (traceLog)
4385926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._manager.stopCapturing(traceLog);
4386926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4387926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4388926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4389f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} id
43905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
43915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    dropTraceLog: function(id)
43925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4393926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var traceLog = this._traceLogs[id];
4394926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (traceLog)
4395926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            this._manager.dropTraceLog(traceLog);
43965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        delete this._traceLogs[id];
4397926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        delete this._traceLogPlayers[id];
4398e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        injectedScript.releaseObjectGroup(id);
43995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
44005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4402f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} id
4403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number=} startOffset
4404926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {number=} maxLength
4405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!CanvasAgent.TraceLog|string}
44065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4407926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    traceLog: function(id, startOffset, maxLength)
44085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
44095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var traceLog = this._traceLogs[id];
44105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!traceLog)
4411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return "Error: Trace log with the given ID not found.";
4412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        // Ensure last call ends a frame.
4414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        traceLog.addFrameEndMark();
4415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var replayableCalls = traceLog.replayableCalls();
4417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (typeof startOffset !== "number")
4418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            startOffset = 0;
4419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (typeof maxLength !== "number")
4420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            maxLength = replayableCalls.length;
4421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4422926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var fromIndex = Math.max(0, startOffset);
4423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var toIndex = Math.min(replayableCalls.length - 1, fromIndex + maxLength - 1);
4424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4425926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var alive = this._manager.capturing() && this._manager.lastTraceLog() === traceLog;
44265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var result = {
44275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            id: id,
4428a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            /** @type {!Array.<!CanvasAgent.Call>} */
4429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            calls: [],
4430a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            /** @type {!Array.<!CanvasAgent.CallArgument>} */
4431e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            contexts: [],
4432926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            alive: alive,
4433926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            startOffset: fromIndex,
4434926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            totalAvailableCalls: replayableCalls.length
44355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4436e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        /** @type {!Object.<string, boolean>} */
4437e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var contextIds = {};
4438926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        for (var i = fromIndex; i <= toIndex; ++i) {
4439926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            var call = replayableCalls[i];
44407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var resource = call.replayableResource();
44417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var contextResource = resource.contextResource();
44425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var stackTrace = call.stackTrace();
44435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var callFrame = stackTrace ? stackTrace.callFrame(0) || {} : {};
44447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var item = CallFormatter.forResource(resource).formatCall(call);
4445591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            item.contextId = CallFormatter.makeStringResourceId(contextResource.id());
4446926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            item.sourceURL = callFrame.sourceURL;
4447926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            item.lineNumber = callFrame.lineNumber;
4448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            item.columnNumber = callFrame.columnNumber;
4449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            item.isFrameEndCall = traceLog.isFrameEndCallAt(i);
4450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            result.calls.push(item);
4451e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            if (!contextIds[item.contextId]) {
4452e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                contextIds[item.contextId] = true;
44537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch                result.contexts.push(CallFormatter.forResource(resource).formatValue(contextResource));
4454e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            }
44555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
44565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return result;
44575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
44585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4460f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} traceLogId
44615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * @param {number} stepNo
44627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {{resourceState: !CanvasAgent.ResourceState, replayTime: number}|string}
44635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    replayTraceLog: function(traceLogId, stepNo)
44655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4466926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var traceLog = this._traceLogs[traceLogId];
44675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!traceLog)
4468926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return "Error: Trace log with the given ID not found.";
4469926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        this._traceLogPlayers[traceLogId] = this._traceLogPlayers[traceLogId] || new TraceLogPlayer(traceLog);
4470e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        injectedScript.releaseObjectGroup(traceLogId);
4471e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
4472a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var replayResult = this._traceLogPlayers[traceLogId].stepTo(stepNo);
4473a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        var resource = replayResult.lastCall.resource();
4474926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var dataURL = resource.toDataURL();
4475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!dataURL) {
4476926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            resource = resource.contextResource();
4477926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            dataURL = resource.toDataURL();
44785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
44797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return {
44807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            resourceState: this._makeResourceState(resource.id(), traceLogId, resource, dataURL),
4481a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            replayTime: replayResult.replayTime
44827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        };
44835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
44845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4486f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} traceLogId
4487f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.ResourceId} stringResourceId
4488926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!CanvasAgent.ResourceState|string}
4489926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
4490926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    resourceState: function(traceLogId, stringResourceId)
4491926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4492926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var traceLog = this._traceLogs[traceLogId];
4493926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!traceLog)
4494926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return "Error: Trace log with the given ID not found.";
4495926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4496926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var parsedStringId1 = this._parseStringId(traceLogId);
4497926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var parsedStringId2 = this._parseStringId(stringResourceId);
4498926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (parsedStringId1.injectedScriptId !== parsedStringId2.injectedScriptId)
4499926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return "Error: Both IDs must point to the same injected script.";
4500926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4501926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        var resourceId = parsedStringId2.resourceId;
4502926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (!resourceId)
4503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return "Error: Wrong resource ID: " + stringResourceId;
4504926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4505e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var traceLogPlayer = this._traceLogPlayers[traceLogId];
4506e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        var resource = traceLogPlayer && traceLogPlayer.replayWorldResource(resourceId);
45077757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return this._makeResourceState(resourceId, traceLogId, resource);
4508926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4509926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4510926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4511f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} traceLogId
4512591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {number} callIndex
4513591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {number} argumentIndex
4514591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     * @param {string} objectGroup
45157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @return {{result:(!RuntimeAgent.RemoteObject|undefined), resourceState:(!CanvasAgent.ResourceState|undefined)}|string}
45165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4517591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    evaluateTraceLogCallArgument: function(traceLogId, callIndex, argumentIndex, objectGroup)
45185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
4519591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var traceLog = this._traceLogs[traceLogId];
4520591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!traceLog)
4521591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return "Error: Trace log with the given ID not found.";
4522591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
4523591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var replayableCall = traceLog.replayableCalls()[callIndex];
4524591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!replayableCall)
4525591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return "Error: No call found at index " + callIndex;
4526591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
4527591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var value;
4528591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (replayableCall.isPropertySetter())
4529591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            value = replayableCall.propertyValue();
4530591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else if (argumentIndex === -1)
4531591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            value = replayableCall.result();
4532591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        else {
4533591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var args = replayableCall.args();
4534591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (argumentIndex < 0 || argumentIndex >= args.length)
4535591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                return "Error: No argument found at index " + argumentIndex + " for call at index " + callIndex;
4536591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            value = args[argumentIndex];
4537591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
4538591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
4539591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (value instanceof ReplayableResource) {
4540591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var traceLogPlayer = this._traceLogPlayers[traceLogId];
4541591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            var resource = traceLogPlayer && traceLogPlayer.replayWorldResource(value.id());
45427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            var resourceState = this._makeResourceState(value.id(), traceLogId, resource);
4543591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return { resourceState: resourceState };
4544591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
4545591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
4546591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        var remoteObject = injectedScript.wrapObject(value, objectGroup, true, false);
4547591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return { result: remoteObject };
45485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
45495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
4551f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @return {!CanvasAgent.TraceLogId}
45525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4553591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    _makeTraceLogId: function()
4554926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
4555591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return "{\"injectedScriptId\":" + injectedScriptId + ",\"traceLogId\":" + (++this._lastTraceLogId) + "}";
45565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    },
45575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
45597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @param {number} resourceId
4560f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {!CanvasAgent.TraceLogId} traceLogId
4561f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)     * @param {?Resource=} resource
45627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch     * @param {string=} overrideImageURL
4563926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {!CanvasAgent.ResourceState}
4564926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     */
45657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    _makeResourceState: function(resourceId, traceLogId, resource, overrideImageURL)
4566926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    {
45677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        var result = {
45687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            id: CallFormatter.makeStringResourceId(resourceId),
45697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            traceLogId: traceLogId
4570926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        };
45717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        if (resource) {
45727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch            result.imageURL = overrideImageURL || resource.toDataURL();
4573e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            result.descriptors = CallFormatter.forResource(resource).formatResourceStateDescriptors(resource.currentState(), traceLogId);
45747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        }
45757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        return result;
4576926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    },
4577926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4578926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    /**
4579926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @param {string} stringId
4580926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)     * @return {{injectedScriptId: number, traceLogId: ?number, resourceId: ?number}}
45815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
4582926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    _parseStringId: function(stringId)
45835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
45847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return /** @type {?} */ (InjectedScriptHost.eval("(" + stringId + ")"));
45855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
45865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
45875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4588926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)var injectedCanvasModule = new InjectedCanvasModule();
4589926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)return injectedCanvasModule;
45905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})
4592