Modified: trunk/Source/WebCore/ChangeLog (137261 => 137262)
--- trunk/Source/WebCore/ChangeLog 2012-12-11 08:32:58 UTC (rev 137261)
+++ trunk/Source/WebCore/ChangeLog 2012-12-11 08:58:03 UTC (rev 137262)
@@ -1,3 +1,17 @@
+2012-12-11 Andrey Adaikin <[email protected]>
+
+ Web Inspector: [WebGL] prevent GC from collecting WebGLObject instances currently bound to the context state
+ https://bugs.webkit.org/show_bug.cgi?id=104119
+
+ Reviewed by Pavel Feldman.
+
+ This is to prevent GC from collecting resources bound to a context (WebGL or 2D).
+ Otherwise, for example in WebGL, subsequent calls to gl.getParameter() may return a recently created
+ instance that is no longer bound to a Resource object (thus, no history to replay it later).
+
+ * inspector/InjectedScriptCanvasModuleSource.js:
+ (.):
+
2012-12-11 Zan Dobersek <[email protected]>
Unreviewed build fix after r137243.
Modified: trunk/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js (137261 => 137262)
--- trunk/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js 2012-12-11 08:32:58 UTC (rev 137261)
+++ trunk/Source/WebCore/inspector/InjectedScriptCanvasModuleSource.js 2012-12-11 08:58:03 UTC (rev 137262)
@@ -347,7 +347,7 @@
},
/**
- * @return {Array}
+ * @return {!Array}
*/
args: function()
{
@@ -584,6 +584,15 @@
this._resourceManager = null;
/** @type {!Array.<Call>} */
this._calls = [];
+ /**
+ * This is to prevent GC from collecting associated resources.
+ * Otherwise, for example in WebGL, subsequent calls to gl.getParameter()
+ * may return a recently created instance that is no longer bound to a
+ * Resource object (thus, no history to replay it later).
+ *
+ * @type {!Object.<string, Resource>}
+ */
+ this._boundResources = Object.create(null);
this.setWrappedObject(wrappedObject);
}
@@ -773,6 +782,19 @@
},
/**
+ * @param {string} key
+ * @param {*} obj
+ */
+ _registerBoundResource: function(key, obj)
+ {
+ var resource = Resource.forObject(obj);
+ if (resource)
+ this._boundResources[key] = resource;
+ else
+ delete this._boundResources[key];
+ },
+
+ /**
* @return {Object}
*/
_wrapObject: function()
@@ -881,6 +903,7 @@
{
return function(value)
{
+ resource._registerBoundResource(propertyName, value);
var manager = resource.manager();
if (!manager || !manager.capturing()) {
originalObject[propertyName] = Resource.wrappedObject(value);
@@ -1376,6 +1399,18 @@
WebGLShaderResource.prototype = {
/**
+ * @return {number}
+ */
+ type: function()
+ {
+ var call = this._calls[0];
+ if (call && call.functionName() === "createShader")
+ return call.args()[0];
+ console.error("ASSERT_NOT_REACHED: Failed to restore shader type from the log.", call);
+ return 0;
+ },
+
+ /**
* @override
* @param {!Call} call
*/
@@ -1922,7 +1957,6 @@
}
}
}
- stateModifyingWrapFunction("attachShader");
stateModifyingWrapFunction("bindAttribLocation");
stateModifyingWrapFunction("compileShader");
stateModifyingWrapFunction("detachShader");
@@ -1939,14 +1973,12 @@
stateModifyingWrapFunction("texSubImage2D");
stateModifyingWrapFunction("texParameterf", WebGLTextureResource.prototype.pushCall_texParameter);
stateModifyingWrapFunction("texParameteri", WebGLTextureResource.prototype.pushCall_texParameter);
- stateModifyingWrapFunction("framebufferRenderbuffer");
- stateModifyingWrapFunction("framebufferTexture2D");
stateModifyingWrapFunction("renderbufferStorage");
/** @this Resource.WrapFunction */
wrapFunctions["getError"] = function()
{
- var gl = this._originalObject;
+ var gl = /** @type {WebGLRenderingContext} */ (this._originalObject);
var error = this.result();
if (error !== gl.NO_ERROR)
this._resource.clearError(error);
@@ -1966,6 +1998,80 @@
this._resource.addExtension(name);
}
+ //
+ // Register bound WebGL resources.
+ //
+
+ /**
+ * @param {WebGLProgram} program
+ * @param {WebGLShader} shader
+ * @this Resource.WrapFunction
+ */
+ wrapFunctions["attachShader"] = function(program, shader)
+ {
+ var resource = this._resource.currentBinding(program);
+ if (resource) {
+ resource.pushCall(this.call());
+ var shaderResource = /** @type {WebGLShaderResource} */ (Resource.forObject(shader));
+ if (shaderResource) {
+ var shaderType = shaderResource.type();
+ resource._registerBoundResource("__attachShader_" + shaderType, shaderResource);
+ }
+ }
+ }
+ /**
+ * @param {number} target
+ * @param {number} attachment
+ * @param {number} objectTarget
+ * @param {WebGLRenderbuffer|WebGLTexture} obj
+ * @this Resource.WrapFunction
+ */
+ wrapFunctions["framebufferRenderbuffer"] = wrapFunctions["framebufferTexture2D"] = function(target, attachment, objectTarget, obj)
+ {
+ var resource = this._resource.currentBinding(target);
+ if (resource) {
+ resource.pushCall(this.call());
+ resource._registerBoundResource("__framebufferAttachmentObjectName", obj);
+ }
+ }
+ /**
+ * @param {number} target
+ * @param {Object} obj
+ * @this Resource.WrapFunction
+ */
+ wrapFunctions["bindBuffer"] = wrapFunctions["bindFramebuffer"] = wrapFunctions["bindRenderbuffer"] = function(target, obj)
+ {
+ this._resource._registerBoundResource("__bindBuffer_" + target, obj);
+ }
+ /**
+ * @param {number} target
+ * @param {WebGLTexture} obj
+ * @this Resource.WrapFunction
+ */
+ wrapFunctions["bindTexture"] = function(target, obj)
+ {
+ var gl = /** @type {WebGLRenderingContext} */ (this._originalObject);
+ var currentTextureBinding = /** @type {number} */ (gl.getParameter(gl.ACTIVE_TEXTURE));
+ this._resource._registerBoundResource("__bindTexture_" + target + "_" + currentTextureBinding, obj);
+ }
+ /**
+ * @param {WebGLProgram} program
+ * @this Resource.WrapFunction
+ */
+ wrapFunctions["useProgram"] = function(program)
+ {
+ this._resource._registerBoundResource("__useProgram", program);
+ }
+ /**
+ * @param {number} index
+ * @this Resource.WrapFunction
+ */
+ wrapFunctions["vertexAttribPointer"] = function(index)
+ {
+ var gl = /** @type {WebGLRenderingContext} */ (this._originalObject);
+ this._resource._registerBoundResource("__vertexAttribPointer_" + index, gl.getParameter(gl.ARRAY_BUFFER_BINDING));
+ }
+
WebGLRenderingContextResource._wrapFunctions = wrapFunctions;
}
return wrapFunctions;