Diff
Modified: trunk/Source/WebCore/ChangeLog (104709 => 104710)
--- trunk/Source/WebCore/ChangeLog 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/ChangeLog 2012-01-11 15:14:44 UTC (rev 104710)
@@ -1,3 +1,41 @@
+2012-01-10 Alexander Pavlov <[email protected]>
+
+ Web Inspector: introduce "source" column in the CSS profiler.
+ https://bugs.webkit.org/show_bug.cgi?id=75378
+
+ Reviewed by Pavel Feldman.
+
+ Rules are no longer merged by their selectors but are shown one per profile entry, with a link to
+ their selector in the source whenever the latter is available.
+
+ * inspector/Inspector.json:
+ * inspector/InspectorCSSAgent.cpp:
+ (WebCore::RuleMatchingStats::RuleMatchingStats):
+ (WebCore::SelectorProfile::makeKey):
+ (WebCore::SelectorProfile::startSelector):
+ (WebCore::SelectorProfile::commitSelector):
+ (WebCore::SelectorProfile::commitSelectorTime):
+ (WebCore::SelectorProfile::toInspectorObject):
+ (WebCore::InspectorCSSAgent::willMatchRule):
+ (WebCore::InspectorCSSAgent::willProcessRule):
+ (WebCore::InspectorCSSAgent::buildArrayForRuleList):
+ * inspector/InspectorStyleSheet.cpp:
+ (WebCore::InspectorStyleSheet::styleSheetURL):
+ (WebCore::InspectorStyleSheet::finalURL):
+ (WebCore::InspectorStyleSheet::setRuleSelector):
+ * inspector/InspectorStyleSheet.h:
+ * inspector/front-end/CSSSelectorProfileView.js:
+ (WebInspector.CSSSelectorDataGridNode.prototype.get rawData):
+ (WebInspector.CSSSelectorDataGridNode.prototype.createCell):
+ (WebInspector.CSSSelectorProfileView):
+ (WebInspector.CSSSelectorProfileView.prototype._createProfileNodes):
+ (WebInspector.CSSSelectorProfileView.prototype._sortProfile.sourceComparator):
+ (WebInspector.CSSSelectorProfileView.prototype._sortProfile):
+ * inspector/front-end/ProfilesPanel.js:
+ (WebInspector.ProfilesPanel.prototype.sidebarResized):
+ * inspector/front-end/dataGrid.css:
+ (.data-grid:focus tr.selected a):
+
2012-01-11 Peter Rybin <[email protected]>
Web Inspector: CodeGeneratorInspector.py: generate enum types.
Modified: trunk/Source/WebCore/inspector/Inspector.json (104709 => 104710)
--- trunk/Source/WebCore/inspector/Inspector.json 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/Inspector.json 2012-01-11 15:14:44 UTC (rev 104710)
@@ -1628,10 +1628,12 @@
"id": "SelectorProfileEntry",
"type": "object",
"properties": [
- { "name": "selector", "type": "string", "description": "CSS selector." },
- { "name": "time", "type": "number", "description": "Total time this selector handling contributed to the browser running time during profiling (in milliseconds.)" },
- { "name": "hitCount", "type": "integer", "description": "Number of times this selector was considered a candidate for matching against DOM elements." },
- { "name": "matchCount", "type": "integer", "description": "Number of times this selector actually matched a DOM element." }
+ { "name": "selector", "type": "string", "description": "CSS selector of the corresponding rule." },
+ { "name": "url", "type": "string", "description": "URL of the resource containing the corresponding rule." },
+ { "name": "lineNumber", "type": "integer", "description": "Selector line number in the resource for the corresponding rule." },
+ { "name": "time", "type": "number", "description": "Total time this rule handling contributed to the browser running time during profiling (in milliseconds.)" },
+ { "name": "hitCount", "type": "integer", "description": "Number of times this rule was considered a candidate for matching against DOM elements." },
+ { "name": "matchCount", "type": "integer", "description": "Number of times this rule actually matched a DOM element." }
],
"description": "CSS selector profile entry."
},
Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp (104709 => 104710)
--- trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp 2012-01-11 15:14:44 UTC (rev 104710)
@@ -51,6 +51,7 @@
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
#include <wtf/text/CString.h>
+#include <wtf/text/StringConcatenate.h>
namespace CSSAgentState {
static const char cssAgentEnabled[] = "cssAgentEnabled";
@@ -67,15 +68,26 @@
PseudoVisited = 1 << 3
};
+struct RuleMatchData {
+ String selector;
+ String url;
+ unsigned lineNumber;
+ double startTime;
+};
+
struct RuleMatchingStats {
RuleMatchingStats()
- : totalTime(0.0), hits(0), matches(0)
+ : lineNumber(0), totalTime(0.0), hits(0), matches(0)
{
}
- RuleMatchingStats(double totalTime, unsigned hits, unsigned matches)
- : totalTime(totalTime), hits(hits), matches(matches)
+ RuleMatchingStats(const RuleMatchData& data, double totalTime, unsigned hits, unsigned matches)
+ : selector(data.selector), url(data.url), lineNumber(data.lineNumber), totalTime(totalTime), hits(hits), matches(matches)
{
}
+
+ String selector;
+ String url;
+ unsigned lineNumber;
double totalTime;
unsigned hits;
unsigned matches;
@@ -83,7 +95,6 @@
class SelectorProfile {
public:
- // FIXME: handle different rules with the same selector differently?
SelectorProfile()
: m_totalMatchingTimeMs(0.0)
{
@@ -94,17 +105,16 @@
double totalMatchingTimeMs() const { return m_totalMatchingTimeMs; }
- void startSelector(const String&);
+ String makeKey();
+ void startSelector(const CSSStyleRule*);
void commitSelector(bool);
void commitSelectorTime();
PassRefPtr<InspectorObject> toInspectorObject() const;
private:
+
+ // Key is "selector?url:line".
typedef HashMap<String, RuleMatchingStats> RuleMatchingStatsMap;
- struct RuleMatchData {
- String selector;
- double startTime;
- };
double m_totalMatchingTimeMs;
RuleMatchingStatsMap m_ruleMatchingStats;
@@ -141,9 +151,23 @@
return result;
}
-inline void SelectorProfile::startSelector(const String& selectorText)
+inline String SelectorProfile::makeKey()
{
- m_currentMatchData.selector = selectorText;
+ return makeString(m_currentMatchData.selector, "?", m_currentMatchData.url, ":", String::number(m_currentMatchData.lineNumber));
+}
+
+inline void SelectorProfile::startSelector(const CSSStyleRule* rule)
+{
+ m_currentMatchData.selector = rule->selectorText();
+ CSSStyleSheet* styleSheet = rule->parentStyleSheet();
+ String url = ""
+ if (styleSheet) {
+ url = ""
+ if (url.isEmpty())
+ url = ""
+ }
+ m_currentMatchData.url = ""
+ m_currentMatchData.lineNumber = rule->sourceLine();
m_currentMatchData.startTime = WTF::currentTimeMS();
}
@@ -151,7 +175,8 @@
{
double matchTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
m_totalMatchingTimeMs += matchTimeMs;
- pair<RuleMatchingStatsMap::iterator, bool> result = m_ruleMatchingStats.add(m_currentMatchData.selector, RuleMatchingStats(matchTimeMs, 1, matched ? 1 : 0));
+
+ pair<RuleMatchingStatsMap::iterator, bool> result = m_ruleMatchingStats.add(makeKey(), RuleMatchingStats(m_currentMatchData, matchTimeMs, 1, matched ? 1 : 0));
if (!result.second) {
result.first->second.totalTime += matchTimeMs;
result.first->second.hits += 1;
@@ -164,41 +189,35 @@
{
double processingTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
m_totalMatchingTimeMs += processingTimeMs;
- RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(m_currentMatchData.selector);
+
+ RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(makeKey());
if (it == m_ruleMatchingStats.end())
return;
- it->second.totalTime += WTF::currentTimeMS() - m_currentMatchData.startTime;
+ it->second.totalTime += processingTimeMs;
}
PassRefPtr<InspectorObject> SelectorProfile::toInspectorObject() const
{
- RefPtr<InspectorArray> data = ""
+ RefPtr<InspectorArray> selectorProfileData = InspectorArray::create();
for (RuleMatchingStatsMap::const_iterator it = m_ruleMatchingStats.begin(); it != m_ruleMatchingStats.end(); ++it) {
- RefPtr<TypeBuilder::CSS::SelectorProfileEntry> stat = TypeBuilder::CSS::SelectorProfileEntry::create()
- .setSelector(it->first)
+ RefPtr<TypeBuilder::CSS::SelectorProfileEntry> entry = TypeBuilder::CSS::SelectorProfileEntry::create()
+ .setSelector(it->second.selector)
+ .setUrl(it->second.url)
+ .setLineNumber(it->second.lineNumber)
.setTime(it->second.totalTime)
.setHitCount(it->second.hits)
.setMatchCount(it->second.matches);
- data->pushObject(stat.release());
+ selectorProfileData->pushObject(entry.release());
}
RefPtr<TypeBuilder::CSS::SelectorProfile> result = TypeBuilder::CSS::SelectorProfile::create()
.setTotalTime(totalMatchingTimeMs())
- .setData(data);
+ .setData(selectorProfileData);
return result.release();
}
// static
-CSSStyleSheet* InspectorCSSAgent::parentStyleSheet(CSSRule* rule)
-{
- if (!rule)
- return 0;
-
- return rule->parentStyleSheet();
-}
-
-// static
CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule)
{
if (!rule->isStyleRule())
@@ -527,7 +546,7 @@
void InspectorCSSAgent::willMatchRule(const CSSStyleRule* rule)
{
- m_currentSelectorProfile->startSelector(rule->selectorText());
+ m_currentSelectorProfile->startSelector(rule);
}
void InspectorCSSAgent::didMatchRule(bool matched)
@@ -537,7 +556,7 @@
void InspectorCSSAgent::willProcessRule(const CSSStyleRule* rule)
{
- m_currentSelectorProfile->startSelector(rule->selectorText());
+ m_currentSelectorProfile->startSelector(rule);
}
void InspectorCSSAgent::didProcessRule()
@@ -685,7 +704,7 @@
if (!rule)
continue;
- InspectorStyleSheet* styleSheet = bindStyleSheet(parentStyleSheet(rule));
+ InspectorStyleSheet* styleSheet = bindStyleSheet(rule->parentStyleSheet());
if (styleSheet)
result->pushObject(styleSheet->buildObjectForRule(rule));
}
Modified: trunk/Source/WebCore/inspector/InspectorCSSAgent.h (104709 => 104710)
--- trunk/Source/WebCore/inspector/InspectorCSSAgent.h 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/InspectorCSSAgent.h 2012-01-11 15:14:44 UTC (rev 104710)
@@ -57,7 +57,6 @@
class InspectorCSSAgent : public InspectorBaseAgent<InspectorCSSAgent>, public InspectorDOMAgent::DOMListener {
WTF_MAKE_NONCOPYABLE(InspectorCSSAgent);
public:
- static CSSStyleSheet* parentStyleSheet(CSSRule*);
static CSSStyleRule* asCSSStyleRule(CSSRule*);
static PassOwnPtr<InspectorCSSAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* state, InspectorDOMAgent* domAgent)
Modified: trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp (104709 => 104710)
--- trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/InspectorStyleSheet.cpp 2012-01-11 15:14:44 UTC (rev 104710)
@@ -657,6 +657,14 @@
return adoptRef(new InspectorStyleSheet(id, pageStyleSheet, origin, documentURL));
}
+// static
+String InspectorStyleSheet::styleSheetURL(CSSStyleSheet* pageStyleSheet)
+{
+ if (pageStyleSheet && !pageStyleSheet->finalURL().isEmpty())
+ return pageStyleSheet->finalURL().string();
+ return emptyString();
+}
+
InspectorStyleSheet::InspectorStyleSheet(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL)
: m_id(id)
, m_pageStyleSheet(pageStyleSheet)
@@ -674,9 +682,8 @@
String InspectorStyleSheet::finalURL() const
{
- if (m_pageStyleSheet && !m_pageStyleSheet->finalURL().isEmpty())
- return m_pageStyleSheet->finalURL().string();
- return m_documentURL;
+ String url = ""
+ return url.isEmpty() ? m_documentURL : url;
}
void InspectorStyleSheet::reparseStyleSheet(const String& text)
@@ -704,7 +711,7 @@
CSSStyleRule* rule = ruleForId(id);
if (!rule)
return false;
- CSSStyleSheet* styleSheet = InspectorCSSAgent::parentStyleSheet(rule);
+ CSSStyleSheet* styleSheet = rule->parentStyleSheet();
if (!styleSheet || !ensureParsedDataReady())
return false;
Modified: trunk/Source/WebCore/inspector/InspectorStyleSheet.h (104709 => 104710)
--- trunk/Source/WebCore/inspector/InspectorStyleSheet.h 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/InspectorStyleSheet.h 2012-01-11 15:14:44 UTC (rev 104710)
@@ -158,6 +158,7 @@
public:
typedef HashMap<CSSStyleDeclaration*, RefPtr<InspectorStyle> > InspectorStyleMap;
static PassRefPtr<InspectorStyleSheet> create(const String& id, PassRefPtr<CSSStyleSheet> pageStyleSheet, const String& origin, const String& documentURL);
+ static String styleSheetURL(CSSStyleSheet* pageStyleSheet);
virtual ~InspectorStyleSheet();
Modified: trunk/Source/WebCore/inspector/front-end/CSSSelectorProfileView.js (104709 => 104710)
--- trunk/Source/WebCore/inspector/front-end/CSSSelectorProfileView.js 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/front-end/CSSSelectorProfileView.js 2012-01-11 15:14:44 UTC (rev 104710)
@@ -52,6 +52,27 @@
get rawData()
{
return this._data;
+ },
+
+ createCell: function(columnIdentifier)
+ {
+ var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+ if (columnIdentifier === "selector" && cell.firstChild) {
+ cell.firstChild.title = this.rawData.selector;
+ return cell;
+ }
+
+ if (columnIdentifier !== "source")
+ return cell;
+
+ cell.removeChildren();
+
+ if (this.rawData.url) {
+ var wrapperDiv = cell.createChild("div");
+ wrapperDiv.appendChild(WebInspector.linkifyResourceAsNode(this.rawData.url, this.rawData.lineNumber));
+ }
+
+ return cell;
}
}
@@ -70,11 +91,13 @@
this.showTimeAsPercent = WebInspector.settings.createSetting("selectorProfilerShowTimeAsPercent", true);
- var columns = { "selector": { title: WebInspector.UIString("Selector"), width: "650px", sortable: true },
+ var columns = { "selector": { title: WebInspector.UIString("Selector"), width: "550px", sortable: true },
+ "source": { title: WebInspector.UIString("Source"), width: "100px", sortable: true },
"time": { title: WebInspector.UIString("Total"), width: "72px", sort: "descending", sortable: true },
"matches": { title: WebInspector.UIString("Matches"), width: "72px", sortable: true } };
this.dataGrid = new WebInspector.DataGrid(columns);
+ this.dataGrid.element.addStyleClass("selector-profile-view");
this.dataGrid.addEventListener("sorting changed", this._sortProfile, this);
this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
this.dataGrid.show(this.element);
@@ -175,6 +198,16 @@
return sortAscending ? -result : result;
}
+ function sourceComparator(a, b)
+ {
+ var aRawData = a.rawData;
+ var bRawData = b.rawData;
+ var result = bRawData.url.localeCompare(aRawData.url);
+ if (!result)
+ result = bRawData.lineNumber - aRawData.lineNumber;
+ return sortAscending ? -result : result;
+ }
+
function timeComparator(a, b)
{
const result = b.rawData.time - a.rawData.time;
@@ -198,6 +231,9 @@
case "selector":
comparator = selectorComparator;
break;
+ case "source":
+ comparator = sourceComparator;
+ break;
}
this.profile.children.sort(comparator);
Modified: trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js (104709 => 104710)
--- trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/front-end/ProfilesPanel.js 2012-01-11 15:14:44 UTC (rev 104710)
@@ -814,7 +814,7 @@
{
var width = event.data;
// Min width = <number of buttons on the left> * 31
- this.profileViewStatusBarItemsContainer.style.left = Math.max(6 * 31, width) + "px";
+ this.profileViewStatusBarItemsContainer.style.left = Math.max(5 * 31, width) + "px";
},
setRecordingProfile: function(profileType, isProfiling)
Modified: trunk/Source/WebCore/inspector/front-end/dataGrid.css (104709 => 104710)
--- trunk/Source/WebCore/inspector/front-end/dataGrid.css 2012-01-11 14:58:22 UTC (rev 104709)
+++ trunk/Source/WebCore/inspector/front-end/dataGrid.css 2012-01-11 15:14:44 UTC (rev 104710)
@@ -191,6 +191,10 @@
color: white;
}
+.data-grid:focus tr.selected a {
+ color: white;
+}
+
.data-grid:focus tr.parent.selected td.disclosure::before {
content: url(Images/treeRightTriangleWhite.png);
}