Commit 32d0638d authored by mnaganov@chromium.org's avatar mnaganov@chromium.org

Web Inspector: [Chromium] Add an ability to look up and explore an object from a heap profile.

https://bugs.webkit.org/show_bug.cgi?id=61179

This is exteremely helpful when dealing with DOM wrappers, as
their properties are mostly implemented with getters and thus not
stored in heap snapshots.

Reviewed by Pavel Feldman.

* English.lproj/localizedStrings.js:
* bindings/js/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::objectByHeapObjectId):
* bindings/js/ScriptProfiler.h:
* bindings/v8/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::objectByHeapObjectId):
* bindings/v8/ScriptProfiler.h:
* inspector/Inspector.json:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::InspectorController):
* inspector/InspectorProfilerAgent.cpp:
(WebCore::InspectorProfilerAgent::create):
(WebCore::InspectorProfilerAgent::InspectorProfilerAgent):
(WebCore::InspectorProfilerAgent::getObjectByHeapObjectId):
* inspector/InspectorProfilerAgent.h:
* inspector/front-end/DetailedHeapshotGridNodes.js:
(WebInspector.HeapSnapshotGridNode.prototype.hasHoverMessage.false.queryObjectContent):
(WebInspector.HeapSnapshotGenericObjectNode):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.get data):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.queryObjectContent.else.formatResult):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.queryObjectContent):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.shortenWindowURL):
* inspector/front-end/DetailedHeapshotView.js:
(WebInspector.DetailedHeapshotView.prototype._showObjectPopover):
* inspector/front-end/HeapSnapshot.js:
(WebInspector.HeapSnapshotNode.prototype.get canBeQueried):
(WebInspector.HeapSnapshotNode.prototype.get flags):
(WebInspector.HeapSnapshotNode.prototype.get isDOMWindow):
(WebInspector.HeapSnapshot.prototype._init):
(WebInspector.HeapSnapshot.prototype.dispose):
(WebInspector.HeapSnapshot.prototype._flagsOfNode):
(WebInspector.HeapSnapshot.prototype._calculateFlags):
(WebInspector.HeapSnapshot.prototype.updateStaticData):
(WebInspector.HeapSnapshotNodesProvider.prototype._serialize):
* inspector/front-end/HeapSnapshotProxy.js:
(WebInspector.HeapSnapshotProxy.prototype.get nodeFlags):
* inspector/front-end/RemoteObject.js:
(WebInspector.RemoteObject.fromError):
* inspector/front-end/heapProfiler.css:
(.detailed-heapshot-view tr:not(.selected) td.object-column span.highlight):

* inspector/profiler/heap-snapshot-expected.txt:
* inspector/profiler/heap-snapshot-test.js:
(initialize_HeapSnapshotTest.InspectorTest.createHeapSnapshotMockWithDOM):
(initialize_HeapSnapshotTest):
* inspector/profiler/heap-snapshot.html:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@97362 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f3ec21be
2011-10-13 Mikhail Naganov <mnaganov@chromium.org>
Web Inspector: [Chromium] Add an ability to look up and explore an object from a heap profile.
https://bugs.webkit.org/show_bug.cgi?id=61179
This is exteremely helpful when dealing with DOM wrappers, as
their properties are mostly implemented with getters and thus not
stored in heap snapshots.
Reviewed by Pavel Feldman.
* inspector/profiler/heap-snapshot-expected.txt:
* inspector/profiler/heap-snapshot-test.js:
(initialize_HeapSnapshotTest.InspectorTest.createHeapSnapshotMockWithDOM):
(initialize_HeapSnapshotTest):
* inspector/profiler/heap-snapshot.html:
2011-10-13 Kent Tamura <tkent@chromium.org> 2011-10-13 Kent Tamura <tkent@chromium.org>
[Chromium] Fix test expectations. [Chromium] Fix test expectations.
...@@ -17,6 +17,8 @@ Running: heapSnapshotRetainersTest ...@@ -17,6 +17,8 @@ Running: heapSnapshotRetainersTest
Running: heapSnapshotAggregatesTest Running: heapSnapshotAggregatesTest
Running: heapSnapshotFlagsTest
Running: heapSnapshotNodesProviderTest Running: heapSnapshotNodesProviderTest
Running: heapSnapshotEdgesProviderTest Running: heapSnapshotEdgesProviderTest
......
...@@ -66,4 +66,41 @@ InspectorTest.createHeapSnapshotMock = function() ...@@ -66,4 +66,41 @@ InspectorTest.createHeapSnapshotMock = function()
}; };
}; };
InspectorTest.createHeapSnapshotMockWithDOM = function()
{
return {
snapshot: {},
nodes: [
{ fields: ["type", "name", "id", "children_count", "children"],
types: [["hidden", "object"], "", "", "", { fields: ["type", "name_or_index", "to_node"], types: [["element", "hidden", "internal"], "", ""] }] },
// A tree with DOMWindow objects.
//
// |----->DOMWindow--->A
// | \
// |----->DOMWindow--->B--->C
// | | \
// (root) hidden --->D--internal / "native"-->N
// | \ |
// |----->E H internal
// | v
// |----->F--->G------>M
//
/* (root) */ 0, 0, 1, 4, 0, 1, 17, 0, 2, 27, 0, 3, 40, 0, 4, 44,
/* DOMWindow */ 1, 11, 2, 2, 0, 1, 51, 0, 2, 55,
/* DOMWindow */ 1, 11, 3, 3, 0, 1, 55, 0, 2, 62, 1, 3, 72,
/* E */ 1, 5, 4, 0,
/* F */ 1, 6, 5, 1, 0, 1, 76,
/* A */ 1, 1, 6, 0,
/* B */ 1, 2, 7, 1, 0, 1, 80,
/* D */ 1, 4, 8, 2, 2, 12, 84, 2, 1, 88,
/* H */ 1, 8, 9, 0,
/* G */ 1, 7, 10, 0,
/* C */ 1, 3, 11, 0,
/* N */ 1, 10, 12, 0,
/* M */ 1, 9, 13, 0
],
strings: ["", "A", "B", "C", "D", "E", "F", "G", "H", "M", "N", "DOMWindow", "native"]
};
};
}; };
...@@ -148,6 +148,30 @@ function test() ...@@ -148,6 +148,30 @@ function test()
next(); next();
}, },
function heapSnapshotFlagsTest(next)
{
var snapshot = new WebInspector.HeapSnapshot(InspectorTest.createHeapSnapshotMockWithDOM());
var expectedCanBeQueried = {
"": false,
"A": true,
"B": true,
"C": true,
"D": true,
"E": false,
"F": false,
"G": false,
"H": false,
"M": false,
"N": true,
"DOMWindow": true
};
for (var nodes = snapshot._allNodes; nodes.hasNext(); nodes.next()) {
var node = nodes.item;
InspectorTest.assertEquals(expectedCanBeQueried[node.name], node.canBeQueried, "canBeQueried of \"" + node.name + "\"");
}
next();
},
function heapSnapshotNodesProviderTest(next) function heapSnapshotNodesProviderTest(next)
{ {
var snapshot = new WebInspector.HeapSnapshot(InspectorTest.createHeapSnapshotMock()); var snapshot = new WebInspector.HeapSnapshot(InspectorTest.createHeapSnapshotMock());
......
2011-10-13 Mikhail Naganov <mnaganov@chromium.org>
Web Inspector: [Chromium] Add an ability to look up and explore an object from a heap profile.
https://bugs.webkit.org/show_bug.cgi?id=61179
This is exteremely helpful when dealing with DOM wrappers, as
their properties are mostly implemented with getters and thus not
stored in heap snapshots.
Reviewed by Pavel Feldman.
* English.lproj/localizedStrings.js:
* bindings/js/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::objectByHeapObjectId):
* bindings/js/ScriptProfiler.h:
* bindings/v8/ScriptProfiler.cpp:
(WebCore::ScriptProfiler::objectByHeapObjectId):
* bindings/v8/ScriptProfiler.h:
* inspector/Inspector.json:
* inspector/InspectorController.cpp:
(WebCore::InspectorController::InspectorController):
* inspector/InspectorProfilerAgent.cpp:
(WebCore::InspectorProfilerAgent::create):
(WebCore::InspectorProfilerAgent::InspectorProfilerAgent):
(WebCore::InspectorProfilerAgent::getObjectByHeapObjectId):
* inspector/InspectorProfilerAgent.h:
* inspector/front-end/DetailedHeapshotGridNodes.js:
(WebInspector.HeapSnapshotGridNode.prototype.hasHoverMessage.false.queryObjectContent):
(WebInspector.HeapSnapshotGenericObjectNode):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.get data):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.queryObjectContent.else.formatResult):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.queryObjectContent):
(WebInspector.HeapSnapshotGenericObjectNode.prototype.shortenWindowURL):
* inspector/front-end/DetailedHeapshotView.js:
(WebInspector.DetailedHeapshotView.prototype._showObjectPopover):
* inspector/front-end/HeapSnapshot.js:
(WebInspector.HeapSnapshotNode.prototype.get canBeQueried):
(WebInspector.HeapSnapshotNode.prototype.get flags):
(WebInspector.HeapSnapshotNode.prototype.get isDOMWindow):
(WebInspector.HeapSnapshot.prototype._init):
(WebInspector.HeapSnapshot.prototype.dispose):
(WebInspector.HeapSnapshot.prototype._flagsOfNode):
(WebInspector.HeapSnapshot.prototype._calculateFlags):
(WebInspector.HeapSnapshot.prototype.updateStaticData):
(WebInspector.HeapSnapshotNodesProvider.prototype._serialize):
* inspector/front-end/HeapSnapshotProxy.js:
(WebInspector.HeapSnapshotProxy.prototype.get nodeFlags):
* inspector/front-end/RemoteObject.js:
(WebInspector.RemoteObject.fromError):
* inspector/front-end/heapProfiler.css:
(.detailed-heapshot-view tr:not(.selected) td.object-column span.highlight):
2011-10-13 Adam Barth <abarth@webkit.org> 2011-10-13 Adam Barth <abarth@webkit.org>
script-src * should allow all URLs script-src * should allow all URLs
Bvar localizedStrings = new Object; Bvar localizedStrings = new Object;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "ScriptProfiler.h" #include "ScriptProfiler.h"
#include "GCController.h" #include "GCController.h"
#include "InspectorValues.h"
#include "JSDOMBinding.h" #include "JSDOMBinding.h"
#include <profiler/Profiler.h> #include <profiler/Profiler.h>
...@@ -41,6 +42,11 @@ void ScriptProfiler::collectGarbage() ...@@ -41,6 +42,11 @@ void ScriptProfiler::collectGarbage()
gcController().garbageCollectNow(); gcController().garbageCollectNow();
} }
PassRefPtr<InspectorValue> ScriptProfiler::objectByHeapObjectId(unsigned, InjectedScriptManager*)
{
return InspectorValue::null();
}
void ScriptProfiler::start(ScriptState* state, const String& title) void ScriptProfiler::start(ScriptState* state, const String& title)
{ {
JSC::Profiler::profiler()->startProfiling(state, stringToUString(title)); JSC::Profiler::profiler()->startProfiling(state, stringToUString(title));
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
namespace WebCore { namespace WebCore {
class InjectedScriptManager;
class InspectorValue;
class ScriptProfiler { class ScriptProfiler {
WTF_MAKE_NONCOPYABLE(ScriptProfiler); WTF_MAKE_NONCOPYABLE(ScriptProfiler);
public: public:
...@@ -48,6 +51,7 @@ public: ...@@ -48,6 +51,7 @@ public:
}; };
static void collectGarbage(); static void collectGarbage();
static PassRefPtr<InspectorValue> objectByHeapObjectId(unsigned id, InjectedScriptManager*);
static void start(ScriptState* state, const String& title); static void start(ScriptState* state, const String& title);
static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title); static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String&, HeapSnapshotProgress*) { return 0; } static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String&, HeapSnapshotProgress*) { return 0; }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "config.h" #include "config.h"
#include "ScriptProfiler.h" #include "ScriptProfiler.h"
#include "InjectedScript.h"
#include "InspectorValues.h" #include "InspectorValues.h"
#include "RetainedDOMInfo.h" #include "RetainedDOMInfo.h"
#include "V8Binding.h" #include "V8Binding.h"
...@@ -65,6 +66,34 @@ void ScriptProfiler::collectGarbage() ...@@ -65,6 +66,34 @@ void ScriptProfiler::collectGarbage()
while (!v8::V8::IdleNotification()) { } while (!v8::V8::IdleNotification()) { }
} }
PassRefPtr<InspectorValue> ScriptProfiler::objectByHeapObjectId(unsigned id, InjectedScriptManager* injectedScriptManager)
{
// As ids are unique, it doesn't matter which HeapSnapshot owns HeapGraphNode.
// We need to find first HeapSnapshot containing a node with the specified id.
const v8::HeapGraphNode* node = 0;
for (int i = 0, l = v8::HeapProfiler::GetSnapshotsCount(); i < l; ++i) {
const v8::HeapSnapshot* snapshot = v8::HeapProfiler::GetSnapshot(i);
node = snapshot->GetNodeById(id);
if (node)
break;
}
if (!node)
return InspectorValue::null();
v8::HandleScope scope;
v8::Handle<v8::Value> value = node->GetHeapValue();
if (!value->IsObject())
return InspectorValue::null();
v8::Handle<v8::Object> object(value.As<v8::Object>());
v8::Local<v8::Context> creationContext = object->CreationContext();
v8::Context::Scope creationScope(creationContext);
ScriptState* scriptState = ScriptState::forContext(creationContext);
InjectedScript injectedScript = injectedScriptManager->injectedScriptFor(scriptState);
return !injectedScript.hasNoValue() ?
RefPtr<InspectorValue>(injectedScript.wrapObject(value, "")).release() : InspectorValue::null();
}
namespace { namespace {
class ActivityControlAdapter : public v8::ActivityControl { class ActivityControlAdapter : public v8::ActivityControl {
......
...@@ -39,7 +39,8 @@ ...@@ -39,7 +39,8 @@
namespace WebCore { namespace WebCore {
class InspectorObject; class InjectedScriptManager;
class InspectorValue;
class ScriptProfiler { class ScriptProfiler {
WTF_MAKE_NONCOPYABLE(ScriptProfiler); WTF_MAKE_NONCOPYABLE(ScriptProfiler);
...@@ -54,6 +55,7 @@ public: ...@@ -54,6 +55,7 @@ public:
}; };
static void collectGarbage(); static void collectGarbage();
static PassRefPtr<InspectorValue> objectByHeapObjectId(unsigned id, InjectedScriptManager*);
static void start(ScriptState* state, const String& title); static void start(ScriptState* state, const String& title);
static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title); static PassRefPtr<ScriptProfile> stop(ScriptState* state, const String& title);
static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*); static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*);
......
...@@ -2009,6 +2009,15 @@ ...@@ -2009,6 +2009,15 @@
}, },
{ {
"name": "collectGarbage" "name": "collectGarbage"
},
{
"name": "getObjectByHeapObjectId",
"parameters": [
{ "name": "objectId", "type": "integer" }
],
"returns": [
{ "name": "result", "$ref": "Runtime.RemoteObject", "description": "Evaluation result." }
]
} }
], ],
"events": [ "events": [
......
...@@ -115,7 +115,7 @@ InspectorController::InspectorController(Page* page, InspectorClient* inspectorC ...@@ -115,7 +115,7 @@ InspectorController::InspectorController(Page* page, InspectorClient* inspectorC
#if ENABLE(JAVASCRIPT_DEBUGGER) #if ENABLE(JAVASCRIPT_DEBUGGER)
, m_debuggerAgent(PageDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), page, m_injectedScriptManager.get())) , m_debuggerAgent(PageDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), page, m_injectedScriptManager.get()))
, m_domDebuggerAgent(InspectorDOMDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent.get(), m_debuggerAgent.get(), m_inspectorAgent.get())) , m_domDebuggerAgent(InspectorDOMDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent.get(), m_debuggerAgent.get(), m_inspectorAgent.get()))
, m_profilerAgent(InspectorProfilerAgent::create(m_instrumentingAgents.get(), m_consoleAgent.get(), page, m_state.get())) , m_profilerAgent(InspectorProfilerAgent::create(m_instrumentingAgents.get(), m_consoleAgent.get(), page, m_state.get(), m_injectedScriptManager.get()))
#endif #endif
#if ENABLE(WORKERS) #if ENABLE(WORKERS)
, m_workerAgent(InspectorWorkerAgent::create(m_instrumentingAgents.get(), m_state.get())) , m_workerAgent(InspectorWorkerAgent::create(m_instrumentingAgents.get(), m_state.get()))
......
...@@ -62,16 +62,17 @@ static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-in ...@@ -62,16 +62,17 @@ static const char* const UserInitiatedProfileName = "org.webkit.profiles.user-in
static const char* const CPUProfileType = "CPU"; static const char* const CPUProfileType = "CPU";
static const char* const HeapProfileType = "HEAP"; static const char* const HeapProfileType = "HEAP";
PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorState* inspectorState) PassOwnPtr<InspectorProfilerAgent> InspectorProfilerAgent::create(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorState* inspectorState, InjectedScriptManager* injectedScriptManager)
{ {
return adoptPtr(new InspectorProfilerAgent(instrumentingAgents, consoleAgent, inspectedPage, inspectorState)); return adoptPtr(new InspectorProfilerAgent(instrumentingAgents, consoleAgent, inspectedPage, inspectorState, injectedScriptManager));
} }
InspectorProfilerAgent::InspectorProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorState* inspectorState) InspectorProfilerAgent::InspectorProfilerAgent(InstrumentingAgents* instrumentingAgents, InspectorConsoleAgent* consoleAgent, Page* inspectedPage, InspectorState* inspectorState, InjectedScriptManager* injectedScriptManager)
: m_instrumentingAgents(instrumentingAgents) : m_instrumentingAgents(instrumentingAgents)
, m_consoleAgent(consoleAgent) , m_consoleAgent(consoleAgent)
, m_inspectedPage(inspectedPage) , m_inspectedPage(inspectedPage)
, m_inspectorState(inspectorState) , m_inspectorState(inspectorState)
, m_injectedScriptManager(injectedScriptManager)
, m_frontend(0) , m_frontend(0)
, m_enabled(false) , m_enabled(false)
, m_recordingUserInitiatedProfile(false) , m_recordingUserInitiatedProfile(false)
...@@ -378,6 +379,15 @@ void InspectorProfilerAgent::toggleRecordButton(bool isProfiling) ...@@ -378,6 +379,15 @@ void InspectorProfilerAgent::toggleRecordButton(bool isProfiling)
m_frontend->setRecordingProfile(isProfiling); m_frontend->setRecordingProfile(isProfiling);
} }
void InspectorProfilerAgent::getObjectByHeapObjectId(ErrorString* error, int id, RefPtr<InspectorObject>* result)
{
RefPtr<InspectorValue> heapObject = ScriptProfiler::objectByHeapObjectId(id, m_injectedScriptManager);
if (!heapObject->isNull())
heapObject->asObject(result);
else
*error = "Object is not available.";
}
} // namespace WebCore } // namespace WebCore
#endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR) #endif // ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
namespace WebCore { namespace WebCore {
class InjectedScriptManager;
class InspectorArray; class InspectorArray;
class InspectorConsoleAgent; class InspectorConsoleAgent;
class InspectorFrontend; class InspectorFrontend;
...@@ -56,7 +57,7 @@ typedef String ErrorString; ...@@ -56,7 +57,7 @@ typedef String ErrorString;
class InspectorProfilerAgent { class InspectorProfilerAgent {
WTF_MAKE_NONCOPYABLE(InspectorProfilerAgent); WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(InspectorProfilerAgent); WTF_MAKE_FAST_ALLOCATED;
public: public:
static PassOwnPtr<InspectorProfilerAgent> create(InstrumentingAgents*, InspectorConsoleAgent*, Page*, InspectorState*); static PassOwnPtr<InspectorProfilerAgent> create(InstrumentingAgents*, InspectorConsoleAgent*, Page*, InspectorState*, InjectedScriptManager*);
virtual ~InspectorProfilerAgent(); virtual ~InspectorProfilerAgent();
void addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL); void addProfile(PassRefPtr<ScriptProfile> prpProfile, unsigned lineNumber, const String& sourceURL);
...@@ -90,6 +91,8 @@ public: ...@@ -90,6 +91,8 @@ public:
void takeHeapSnapshot(ErrorString*); void takeHeapSnapshot(ErrorString*);
void toggleRecordButton(bool isProfiling); void toggleRecordButton(bool isProfiling);
void getObjectByHeapObjectId(ErrorString*, int id, RefPtr<InspectorObject>* result);
private: private:
typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap; typedef HashMap<unsigned int, RefPtr<ScriptProfile> > ProfilesMap;
typedef HashMap<unsigned int, RefPtr<ScriptHeapSnapshot> > HeapSnapshotsMap; typedef HashMap<unsigned int, RefPtr<ScriptHeapSnapshot> > HeapSnapshotsMap;
...@@ -97,7 +100,7 @@ private: ...@@ -97,7 +100,7 @@ private:
void resetFrontendProfiles(); void resetFrontendProfiles();
void restoreEnablement(); void restoreEnablement();
InspectorProfilerAgent(InstrumentingAgents*, InspectorConsoleAgent*, Page*, InspectorState*); InspectorProfilerAgent(InstrumentingAgents*, InspectorConsoleAgent*, Page*, InspectorState*, InjectedScriptManager*);
PassRefPtr<InspectorObject> createProfileHeader(const ScriptProfile& profile); PassRefPtr<InspectorObject> createProfileHeader(const ScriptProfile& profile);
PassRefPtr<InspectorObject> createSnapshotHeader(const ScriptHeapSnapshot& snapshot); PassRefPtr<InspectorObject> createSnapshotHeader(const ScriptHeapSnapshot& snapshot);
...@@ -105,6 +108,7 @@ private: ...@@ -105,6 +108,7 @@ private:
InspectorConsoleAgent* m_consoleAgent; InspectorConsoleAgent* m_consoleAgent;
Page* m_inspectedPage; Page* m_inspectedPage;
InspectorState* m_inspectorState; InspectorState* m_inspectorState;
InjectedScriptManager* m_injectedScriptManager;
InspectorFrontend::Profiler* m_frontend; InspectorFrontend::Profiler* m_frontend;
bool m_enabled; bool m_enabled;
bool m_recordingUserInitiatedProfile; bool m_recordingUserInitiatedProfile;
......
...@@ -56,9 +56,8 @@ WebInspector.HeapSnapshotGridNode.prototype = { ...@@ -56,9 +56,8 @@ WebInspector.HeapSnapshotGridNode.prototype = {
hasHoverMessage: false, hasHoverMessage: false,
hoverMessage: function(callback) queryObjectContent: function(callback)
{ {
callback("");
}, },
_populate: function(event) _populate: function(event)
...@@ -185,11 +184,10 @@ WebInspector.HeapSnapshotGenericObjectNode = function(tree, node) ...@@ -185,11 +184,10 @@ WebInspector.HeapSnapshotGenericObjectNode = function(tree, node)
if (this._type === "string") if (this._type === "string")
this.hasHoverMessage = true; this.hasHoverMessage = true;
else if (this._type === "object" && this.isDOMWindow(this._name)) { else if (this._type === "object" && this.isDOMWindow(this._name)) {
var url = []; this._name = this.shortenWindowURL(this._name, false);
this._name = this.shortenWindowURL(this._name, false, url); this.hasHoverMessage = true;
this._url = url[0]; } else if (node.flags & tree.snapshot.nodeFlags.canBeQueried)
this.hasHoverMessage = true; this.hasHoverMessage = true;
}
}; };
WebInspector.HeapSnapshotGenericObjectNode.prototype = { WebInspector.HeapSnapshotGenericObjectNode.prototype = {
...@@ -259,6 +257,8 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = { ...@@ -259,6 +257,8 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = {
value += " []"; value += " []";
break; break;
}; };
if (this.hasHoverMessage)
valueStyle += " highlight";
data["object"] = { valueStyle: valueStyle, value: value + " @" + this.snapshotNodeId }; data["object"] = { valueStyle: valueStyle, value: value + " @" + this.snapshotNodeId };
var view = this.dataGrid.snapshotView; var view = this.dataGrid.snapshotView;
...@@ -268,12 +268,20 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = { ...@@ -268,12 +268,20 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = {
return this._enhanceData ? this._enhanceData(data) : data; return this._enhanceData ? this._enhanceData(data) : data;
}, },
hoverMessage: function(callback) queryObjectContent: function(callback)
{ {
if (this._type === "string") if (this._type === "string")
callback("\"" + this._name + "\"", "console-formatted-string"); callback(WebInspector.RemoteObject.fromPrimitiveValue(this._name));
else if (this._url) else {
callback(this._url, "console-formatted-object"); function formatResult(error, object)
{
if (!error && object.type)
callback(WebInspector.RemoteObject.fromPayload(object), !!error);
else
callback(WebInspector.RemoteObject.fromError(WebInspector.UIString("Not available")));
}
ProfilerAgent.getObjectByHeapObjectId(this.snapshotNodeId, formatResult);
}
}, },
get _retainedSizePercent() get _retainedSizePercent()
...@@ -300,14 +308,12 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = { ...@@ -300,14 +308,12 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = {
return fullName.substr(0, 9) === "DOMWindow"; return fullName.substr(0, 9) === "DOMWindow";
}, },
shortenWindowURL: function(fullName, hasObjectId, fullURLPtr) shortenWindowURL: function(fullName, hasObjectId)
{ {
var startPos = fullName.indexOf("/"); var startPos = fullName.indexOf("/");
var endPos = hasObjectId ? fullName.indexOf("@") : fullName.length; var endPos = hasObjectId ? fullName.indexOf("@") : fullName.length;
if (startPos !== -1 && endPos !== -1) { if (startPos !== -1 && endPos !== -1) {
var fullURL = fullName.substring(startPos + 1, endPos).trimLeft(); var fullURL = fullName.substring(startPos + 1, endPos).trimLeft();
if (fullURLPtr)
fullURLPtr[0] = fullURL;
var url = fullURL.trimURL(); var url = fullURL.trimURL();
if (url.length > 40) if (url.length > 40)
url = url.trimMiddle(40); url = url.trimMiddle(40);
......
...@@ -621,7 +621,7 @@ WebInspector.DetailedHeapshotView = function(parent, profile) ...@@ -621,7 +621,7 @@ WebInspector.DetailedHeapshotView = function(parent, profile)
this.helpButton = new WebInspector.StatusBarButton("", "heapshot-help-status-bar-item status-bar-item"); this.helpButton = new WebInspector.StatusBarButton("", "heapshot-help-status-bar-item status-bar-item");
this.helpButton.addEventListener("click", this._helpClicked.bind(this), false); this.helpButton.addEventListener("click", this._helpClicked.bind(this), false);
var popoverHelper = new WebInspector.PopoverHelper(this.element, this._getHoverAnchor.bind(this), this._showStringContentPopover.bind(this)); var popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, this._getHoverAnchor.bind(this), this._showObjectPopover.bind(this), null, true);
this._loadProfile(this._profileUid, profileCallback.bind(this)); this._loadProfile(this._profileUid, profileCallback.bind(this));
...@@ -1066,19 +1066,9 @@ WebInspector.DetailedHeapshotView.prototype = { ...@@ -1066,19 +1066,9 @@ WebInspector.DetailedHeapshotView.prototype = {
this.refreshShowAsPercents(); this.refreshShowAsPercents();
}, },
_showStringContentPopover: function(anchor, popover) _showObjectPopover: function(element, showCallback)
{ {