Modified: trunk/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js (127242 => 127243)
--- trunk/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js 2012-08-31 09:43:27 UTC (rev 127242)
+++ trunk/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js 2012-08-31 09:56:10 UTC (rev 127243)
@@ -132,8 +132,97 @@
}
/**
+ * @interface
+ */
+function StackTrace()
+{
+}
+
+StackTrace.prototype = {
+ /**
+ * @param {number} index
+ * @return {{sourceURL: string, lineNumber: number, columnNumber: number}}
+ */
+ callFrame: function(index)
+ {
+ }
+}
+
+/**
+ * @param {number=} stackTraceLimit
+ * @param {Function=} topMostFunctionToIgnore
+ * @return {StackTrace}
+ */
+StackTrace.create = function(stackTraceLimit, topMostFunctionToIgnore)
+{
+ if (typeof Error.captureStackTrace === "function")
+ return new StackTraceV8(stackTraceLimit, topMostFunctionToIgnore || arguments.callee);
+ // FIXME: Support JSC, and maybe other browsers.
+ return null;
+}
+
+/**
* @constructor
+ * @implements {StackTrace}
+ * @param {number=} stackTraceLimit
+ * @param {Function=} topMostFunctionToIgnore
+ * @see http://code.google.com/p/v8/wiki/_javascript_StackTraceApi
*/
+function StackTraceV8(stackTraceLimit, topMostFunctionToIgnore)
+{
+ StackTrace.call(this);
+ var oldStackTraceLimit = Error.stackTraceLimit;
+ if (typeof stackTraceLimit === "number")
+ Error.stackTraceLimit = stackTraceLimit;
+
+ this._error = /** @type {{stack: Array}} */ {};
+ Error.captureStackTrace(this._error, topMostFunctionToIgnore || arguments.callee);
+
+ Error.stackTraceLimit = oldStackTraceLimit;
+}
+
+StackTraceV8.prototype = {
+ /**
+ * @override
+ * @param {number} index
+ * @return {{sourceURL: string, lineNumber: number, columnNumber: number}}
+ */
+ callFrame: function(index)
+ {
+ if (!this._stackTrace)
+ this._prepareStackTrace();
+ return this._stackTrace[index];
+ },
+
+ _prepareStackTrace: function()
+ {
+ var oldPrepareStackTrace = Error.prepareStackTrace;
+ /**
+ * @param {Object} error
+ * @param {Array.<CallSite>} structuredStackTrace
+ * @return {Array.<{sourceURL: string, lineNumber: number, columnNumber: number}>}
+ */
+ Error.prepareStackTrace = function(error, structuredStackTrace)
+ {
+ return structuredStackTrace.map(function(callSite) {
+ return {
+ sourceURL: callSite.getFileName(),
+ lineNumber: callSite.getLineNumber(),
+ columnNumber: callSite.getColumnNumber()
+ };
+ });
+ }
+ this._stackTrace = this._error.stack;
+ Error.prepareStackTrace = oldPrepareStackTrace;
+ delete this._error; // No longer needed, free memory.
+ }
+}
+
+StackTraceV8.prototype.__proto__ = StackTrace.prototype;
+
+/**
+ * @constructor
+ */
function Cache()
{
this.reset();
@@ -190,13 +279,15 @@
* @param {string} functionName
* @param {Array|Arguments} args
* @param {Resource|*=} result
+ * @param {StackTrace=} stackTrace
*/
-function Call(thisObject, functionName, args, result)
+function Call(thisObject, functionName, args, result, stackTrace)
{
this._thisObject = thisObject;
this._functionName = functionName;
this._args = Array.prototype.slice.call(args, 0);
this._result = result;
+ this._stackTrace = stackTrace || null;
}
Call.prototype = {
@@ -232,6 +323,22 @@
return this._result;
},
+ /**
+ * @return {StackTrace}
+ */
+ stackTrace: function()
+ {
+ return this._stackTrace;
+ },
+
+ /**
+ * @param {StackTrace} stackTrace
+ */
+ setStackTrace: function(stackTrace)
+ {
+ this._stackTrace = stackTrace;
+ },
+
freeze: function()
{
if (this._freezed)
@@ -256,7 +363,7 @@
var args = this._args.map(function(obj) {
return Resource.toReplayable(obj, cache);
});
- return new ReplayableCall(thisObject, this._functionName, args, result);
+ return new ReplayableCall(thisObject, this._functionName, args, result, this._stackTrace);
},
/**
@@ -283,6 +390,7 @@
this._functionName = replayableCall.functionName();
this._args = replayArgs;
this._result = replayResult;
+ this._stackTrace = replayableCall.stackTrace();
this._freezed = true;
return this;
}
@@ -294,13 +402,15 @@
* @param {string} functionName
* @param {Array.<ReplayableResource|*>} args
* @param {ReplayableResource|*} result
+ * @param {StackTrace} stackTrace
*/
-function ReplayableCall(thisObject, functionName, args, result)
+function ReplayableCall(thisObject, functionName, args, result, stackTrace)
{
this._thisObject = thisObject;
this._functionName = functionName;
this._args = args;
this._result = result;
+ this._stackTrace = stackTrace;
}
ReplayableCall.prototype = {
@@ -337,6 +447,14 @@
},
/**
+ * @return {StackTrace}
+ */
+ stackTrace: function()
+ {
+ return this._stackTrace;
+ },
+
+ /**
* @param {Cache} cache
* @return {Call}
*/
@@ -1349,8 +1467,11 @@
manager.captureArguments(resource, arguments);
var wrapFunction = new WebGLRenderingContextResource.WrapFunction(originalObject, originalFunction, functionName, arguments);
customWrapFunction.apply(wrapFunction, arguments);
- if (manager)
- manager.reportCall(wrapFunction.call());
+ if (manager && manager.capturing()) {
+ var call = wrapFunction.call();
+ call.setStackTrace(StackTrace.create(1, arguments.callee));
+ manager.reportCall(call);
+ }
return wrapFunction.result();
};
},
@@ -1371,7 +1492,8 @@
return originalFunction.apply(originalObject, arguments);
manager.captureArguments(resource, arguments);
var result = originalFunction.apply(originalObject, arguments);
- var call = new Call(resource, functionName, arguments, result);
+ var stackTrace = StackTrace.create(1, arguments.callee);
+ var call = new Call(resource, functionName, arguments, result, stackTrace);
manager.reportCall(call);
return result;
};
@@ -1776,9 +1898,21 @@
var calls = traceLog.replayableCalls();
for (var i = 0, n = calls.length; i < n; ++i) {
var call = calls[i];
- result.calls.push({
- functionName: call.functionName() + "(" + call.args().join(", ") + ") => " + call.result()
+ var args = call.args().map(function(argument) {
+ return argument + "";
});
+ var stackTrace = call.stackTrace();
+ var callFrame = stackTrace ? stackTrace.callFrame(0) || {} : {};
+ var traceLogItem = {
+ functionName: call.functionName(),
+ arguments: args,
+ sourceURL: callFrame.sourceURL,
+ lineNumber: callFrame.lineNumber,
+ columnNumber: callFrame.columnNumber
+ };
+ if (call.result())
+ traceLogItem.result = call.result() + "";
+ result.calls.push(traceLogItem);
}
return result;
},
Modified: trunk/Source/WebCore/inspector/Inspector.json (127242 => 127243)
--- trunk/Source/WebCore/inspector/Inspector.json 2012-08-31 09:43:27 UTC (rev 127242)
+++ trunk/Source/WebCore/inspector/Inspector.json 2012-08-31 09:56:10 UTC (rev 127243)
@@ -3149,7 +3149,12 @@
"id": "Call",
"type": "object",
"properties": [
- { "name": "functionName", "type": "string" }
+ { "name": "functionName", "type": "string" },
+ { "name": "arguments", "type": "array", "items": { "type": "string" } },
+ { "name": "result", "type": "string", "optional": true },
+ { "name": "sourceURL", "type": "string", "optional": true },
+ { "name": "lineNumber", "type": "integer", "optional": true },
+ { "name": "columnNumber", "type": "integer", "optional": true }
]
},
{
@@ -3157,7 +3162,7 @@
"type": "object",
"properties": [
{ "name": "id", "$ref": "TraceLogId" },
- { "name": "calls", "type": "array", "items": { "$ref": "Call" }}
+ { "name": "calls", "type": "array", "items": { "$ref": "Call" } }
]
}
],
Modified: trunk/Source/WebCore/inspector/front-end/WebGLProfileView.js (127242 => 127243)
--- trunk/Source/WebCore/inspector/front-end/WebGLProfileView.js 2012-08-31 09:43:27 UTC (rev 127242)
+++ trunk/Source/WebCore/inspector/front-end/WebGLProfileView.js 2012-08-31 09:56:10 UTC (rev 127243)
@@ -55,12 +55,15 @@
this._debugInfoElement = document.createElement("div");
replayImageContainer.appendChild(this._debugInfoElement);
+ this._linkifier = new WebInspector.Linkifier();
+
this._showTraceLog();
}
WebInspector.WebGLProfileView.prototype = {
dispose: function()
{
+ this._linkifier.reset();
WebGLAgent.dropTraceLog(this._profile.traceLogId());
},
@@ -105,7 +108,21 @@
var traceLogItem = document.createElement("div");
traceLogItem.traceLogId = traceLog.id;
traceLogItem.stepNo = i;
- traceLogItem.textContent = "(" + (i+1) + ") " + call.functionName;
+ traceLogItem.appendChild(document.createTextNode("(" + (i+1) + ") "));
+
+ if (call.sourceURL) {
+ // FIXME(62725): stack trace line/column numbers are one-based.
+ var lineNumber = Math.max(0, call.lineNumber - 1) || 0;
+ var columnNumber = Math.max(0, call.columnNumber - 1) || 0;
+ var linkElement = this._linkifier.linkifyLocation(call.sourceURL, lineNumber, columnNumber);
+ linkElement.textContent = call.functionName;
+ traceLogItem.appendChild(linkElement);
+ } else
+ traceLogItem.appendChild(document.createTextNode(call.functionName));
+
+ traceLogItem.appendChild(document.createTextNode("(" + call.arguments.join(", ") + ")"));
+ if (typeof call.result !== "undefined")
+ traceLogItem.appendChild(document.createTextNode(" => " + call.result));
this._traceLogElement.appendChild(traceLogItem);
}
}