Web Inspector: [WebGL] Allow collecting calls for Resource objects affecting their...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Aug 2012 10:08:21 +0000 (10:08 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Aug 2012 10:08:21 +0000 (10:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=94686

Patch by Andrey Adaikin <aandrey@chromium.org> on 2012-08-23
Reviewed by Pavel Feldman.

Allow collecting calls for WebGL Resource objects affecting their states.
Clone Call's mutable arguments before pushing it to the log.

* inspector/InjectedScriptWebGLModuleSource.js:
(.):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@126413 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js

index 8e4b38a..ab279d1 100644 (file)
@@ -1,3 +1,16 @@
+2012-08-23  Andrey Adaikin  <aandrey@chromium.org>
+
+        Web Inspector: [WebGL] Allow collecting calls for Resource objects affecting their states
+        https://bugs.webkit.org/show_bug.cgi?id=94686
+
+        Reviewed by Pavel Feldman.
+
+        Allow collecting calls for WebGL Resource objects affecting their states.
+        Clone Call's mutable arguments before pushing it to the log.
+
+        * inspector/InjectedScriptWebGLModuleSource.js:
+        (.):
+
 2012-08-23  Robin Cao  <robin.cao@torchmobile.com.cn>
 
         [BlackBerry] draw <video> on <canvas> does not work
index 136e8c8..3ace0b2 100644 (file)
  */
 (function (InjectedScriptHost, inspectedWindow, injectedScriptId) {
 
+var TypeUtils = {
+    /**
+     * http://www.khronos.org/registry/typedarray/specs/latest/#7
+     * @type {Array.<Function>}
+     */
+    typedArrayClasses: (function(typeNames) {
+        var result = [];
+        for (var i = 0, n = typeNames.length; i < n; ++i) {
+            if (inspectedWindow[typeNames[i]])
+                result.push(inspectedWindow[typeNames[i]]);
+        }
+        return result;
+    })(["Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array", "Int32Array", "Uint32Array", "Float32Array", "Float64Array"]),
+
+    /**
+     * @param {*} array
+     * @return {Function}
+     */
+    typedArrayClass: function(array)
+    {
+        var classes = TypeUtils.typedArrayClasses;
+        for (var i = 0, n = classes.length; i < n; ++i) {
+            if (array instanceof classes[i])
+                return classes[i];
+        }
+        return null;
+    },
+
+    /**
+     * @param {*} obj
+     * @return {*}
+     * FIXME: suppress checkTypes due to outdated builtin externs for CanvasRenderingContext2D and ImageData
+     * @suppress {checkTypes}
+     */
+    clone: function(obj)
+    {
+        if (!obj)
+            return obj;
+
+        var type = typeof obj;
+        if (type !== "object" && type !== "function")
+            return obj;
+
+        // Handle Array and ArrayBuffer instances.
+        if (typeof obj.slice === "function") {
+            console.assert(obj instanceof Array || obj instanceof ArrayBuffer);
+            return obj.slice(0);
+        }
+
+        var typedArrayClass = TypeUtils.typedArrayClass(obj);
+        if (typedArrayClass)
+            return new typedArrayClass(obj);
+
+        if (obj instanceof HTMLImageElement)
+            return obj.cloneNode(true);
+
+        if (obj instanceof HTMLCanvasElement) {
+            var result = obj.cloneNode(true);
+            var context = result.getContext("2d");
+            context.drawImage(obj, 0, 0);
+            return result;
+        }
+
+        if (obj instanceof HTMLVideoElement) {
+            var result = obj.cloneNode(true);
+            // FIXME: Copy HTMLVideoElement's current image into a 2d canvas.
+            return result;
+        }
+
+        if (obj instanceof ImageData) {
+            var context = TypeUtils._dummyCanvas2dContext();
+            var result = context.createImageData(obj);
+            for (var i = 0, n = obj.data.length; i < n; ++i)
+              result.data[i] = obj.data[i];
+            return result;
+        }
+
+        console.error("ASSERT_NOT_REACHED: failed to clone object: ", obj);
+        return obj;
+    },
+
+    /**
+     * @return {CanvasRenderingContext2D}
+     */
+    _dummyCanvas2dContext: function()
+    {
+        var context = TypeUtils._dummyCanvas2dContext;
+        if (!context) {
+            var canvas = inspectedWindow.document.createElement("canvas");
+            context = canvas.getContext("2d");
+            var contextResource = Resource.forObject(context);
+            if (contextResource)
+                context = contextResource.wrappedObject();
+            TypeUtils._dummyCanvas2dContext = context;
+        }
+        return context;
+    }
+}
+
 /**
  * @constructor
  */
@@ -93,7 +192,7 @@ Cache.prototype = {
  * @param {Resource|Object} thisObject
  * @param {string} functionName
  * @param {Array|Arguments} args
- * @param {Resource|*} result
+ * @param {Resource|*=} result
  */
 function Call(thisObject, functionName, args, result)
 {
@@ -134,6 +233,18 @@ Call.prototype = {
     result: function()
     {
         return this._result;
+    },
+
+    freeze: function()
+    {
+        if (this._freezed)
+            return;
+        this._freezed = true;
+        for (var i = 0, n = this._args.length; i < n; ++i) {
+            // FIXME: freeze the Resources also!
+            if (!Resource.forObject(this._args[i]))
+                this._args[i] = TypeUtils.clone(this._args[i]);
+        }
     }
 }
 
@@ -203,18 +314,24 @@ function Resource(wrappedObject)
 {
     this._id = ++Resource._uniqueId;
     this._resourceManager = null;
+    this._calls = [];
     this.setWrappedObject(wrappedObject);
 }
 
+/**
+ * @type {number}
+ */
 Resource._uniqueId = 0;
 
 /**
- * @param {Object} obj
+ * @param {*} obj
  * @return {Resource}
  */
 Resource.forObject = function(obj)
 {
-    if (!obj || obj instanceof Resource)
+    if (!obj)
+        return null;
+    if (obj instanceof Resource)
         return obj;
     if (typeof obj === "object")
         return obj["__resourceObject"];
@@ -243,7 +360,8 @@ Resource.prototype = {
      */
     setWrappedObject: function(value)
     {
-        console.assert(value && !(value instanceof Resource), "Binding a Resource object to another Resource object?");
+        console.assert(value, "wrappedObject should not be NULL");
+        console.assert(!(value instanceof Resource), "Binding a Resource object to another Resource object?");
         this._wrappedObject = value;
         this._bindObjectToResource(value);
     },
@@ -274,6 +392,23 @@ Resource.prototype = {
     },
 
     /**
+     * @return {Array.<Call>}
+     */
+    calls: function()
+    {
+        return this._calls;
+    },
+
+    /**
+     * @param {Call} call
+     */
+    pushCall: function(call)
+    {
+        call.freeze();
+        this._calls.push(call);
+    },
+
+    /**
      * @param {Object} object
      */
     _bindObjectToResource: function(object)
@@ -391,7 +526,7 @@ WebGLRenderingContextResource.prototype.__proto__ = Resource.prototype;
  * @param {WebGLRenderingContext} originalObject
  * @param {Function} originalFunction
  * @param {string} functionName
- * @param {Array} args
+ * @param {Array|Arguments} args
  */
 WebGLRenderingContextResource.WrapFunction = function(originalObject, originalFunction, functionName, args)
 {
@@ -591,6 +726,10 @@ ResourceTrackingManager.prototype = {
         this._stopCapturingOnFrameEnd = true;
     },
 
+    /**
+     * @param {Resource} resource
+     * @param {Array|Arguments} args
+     */
     captureArguments: function(resource, args)
     {
         if (!this._capturing)