summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/inspector/front-end
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-24 11:24:40 +0100
committerBen Murdoch <benm@google.com>2011-06-02 09:53:15 +0100
commit81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch)
tree7a9e5ed86ff429fd347a25153107221543909b19 /Source/WebCore/inspector/front-end
parent94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff)
downloadexternal_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/WebCore/inspector/front-end')
-rw-r--r--Source/WebCore/inspector/front-end/AuditRules.js84
-rw-r--r--Source/WebCore/inspector/front-end/AuditsPanel.js2
-rw-r--r--Source/WebCore/inspector/front-end/BreakpointManager.js60
-rw-r--r--Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js14
-rw-r--r--Source/WebCore/inspector/front-end/CSSStyleModel.js28
-rw-r--r--Source/WebCore/inspector/front-end/CallStackSidebarPane.js43
-rw-r--r--Source/WebCore/inspector/front-end/ConsoleView.js43
-rw-r--r--Source/WebCore/inspector/front-end/CookieItemsView.js2
-rw-r--r--Source/WebCore/inspector/front-end/DOMAgent.js134
-rw-r--r--Source/WebCore/inspector/front-end/DOMStorage.js17
-rw-r--r--Source/WebCore/inspector/front-end/DataGrid.js4
-rw-r--r--Source/WebCore/inspector/front-end/Database.js12
-rw-r--r--Source/WebCore/inspector/front-end/DebuggerModel.js45
-rw-r--r--Source/WebCore/inspector/front-end/DebuggerPresentationModel.js131
-rw-r--r--Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js707
-rw-r--r--Source/WebCore/inspector/front-end/DetailedHeapshotView.js859
-rw-r--r--Source/WebCore/inspector/front-end/ElementsPanel.js32
-rw-r--r--Source/WebCore/inspector/front-end/ElementsTreeOutline.js74
-rw-r--r--Source/WebCore/inspector/front-end/ExtensionPanel.js2
-rw-r--r--Source/WebCore/inspector/front-end/ExtensionServer.js49
-rw-r--r--Source/WebCore/inspector/front-end/FontView.js69
-rw-r--r--Source/WebCore/inspector/front-end/HAREntry.js6
-rw-r--r--Source/WebCore/inspector/front-end/HeapSnapshot.js73
-rw-r--r--Source/WebCore/inspector/front-end/HeapSnapshotView.js2
-rw-r--r--Source/WebCore/inspector/front-end/Images/helpButtonGlyph.pngbin0 -> 271 bytes
-rw-r--r--Source/WebCore/inspector/front-end/MetricsSidebarPane.js2
-rw-r--r--Source/WebCore/inspector/front-end/NetworkManager.js8
-rw-r--r--Source/WebCore/inspector/front-end/NetworkPanel.js95
-rw-r--r--Source/WebCore/inspector/front-end/Panel.js34
-rw-r--r--Source/WebCore/inspector/front-end/PleaseWaitMessage.js2
-rw-r--r--Source/WebCore/inspector/front-end/Popover.js8
-rw-r--r--Source/WebCore/inspector/front-end/ProfileView.js6
-rw-r--r--Source/WebCore/inspector/front-end/ProfilesPanel.js95
-rw-r--r--Source/WebCore/inspector/front-end/PropertiesSidebarPane.js30
-rw-r--r--Source/WebCore/inspector/front-end/RemoteObject.js16
-rw-r--r--Source/WebCore/inspector/front-end/ResourceHeadersView.js2
-rw-r--r--Source/WebCore/inspector/front-end/ResourceView.js27
-rw-r--r--Source/WebCore/inspector/front-end/ResourcesPanel.js8
-rw-r--r--Source/WebCore/inspector/front-end/Script.js2
-rw-r--r--Source/WebCore/inspector/front-end/ScriptFormatter.js101
-rw-r--r--Source/WebCore/inspector/front-end/ScriptsPanel.js670
-rwxr-xr-xSource/WebCore/inspector/front-end/SearchController.js269
-rw-r--r--Source/WebCore/inspector/front-end/SourceFrame.js341
-rw-r--r--Source/WebCore/inspector/front-end/SourceFrameContent.js127
-rw-r--r--Source/WebCore/inspector/front-end/SourceTokenizer.js5
-rw-r--r--Source/WebCore/inspector/front-end/StylesSidebarPane.js29
-rw-r--r--Source/WebCore/inspector/front-end/TestController.js33
-rw-r--r--Source/WebCore/inspector/front-end/TextEditorHighlighter.js102
-rw-r--r--Source/WebCore/inspector/front-end/TextViewer.js790
-rw-r--r--Source/WebCore/inspector/front-end/TimelinePanel.js5
-rwxr-xr-xSource/WebCore/inspector/front-end/Toolbar.js220
-rw-r--r--Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js2
-rw-r--r--Source/WebCore/inspector/front-end/WebKit.qrc4
-rw-r--r--Source/WebCore/inspector/front-end/WorkersSidebarPane.js4
-rw-r--r--Source/WebCore/inspector/front-end/heapProfiler.css105
-rw-r--r--Source/WebCore/inspector/front-end/inspector.css169
-rw-r--r--Source/WebCore/inspector/front-end/inspector.html14
-rw-r--r--Source/WebCore/inspector/front-end/inspector.js379
-rw-r--r--Source/WebCore/inspector/front-end/networkPanel.css36
-rw-r--r--Source/WebCore/inspector/front-end/textViewer.css14
-rw-r--r--Source/WebCore/inspector/front-end/utilities.js119
61 files changed, 4735 insertions, 1630 deletions
diff --git a/Source/WebCore/inspector/front-end/AuditRules.js b/Source/WebCore/inspector/front-end/AuditRules.js
index c122ba4..803e9e0 100644
--- a/Source/WebCore/inspector/front-end/AuditRules.js
+++ b/Source/WebCore/inspector/front-end/AuditRules.js
@@ -65,10 +65,16 @@ WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, nee
WebInspector.AuditRules.evaluateInTargetWindow = function(func, args, callback)
{
- InspectorBackend.evaluateOnSelf(func.toString(), args, callback);
+ function mycallback(result)
+ {
+ if (result)
+ callback(JSON.parse(result.description));
+ else
+ callback(null);
+ }
+ RuntimeAgent.evaluate("JSON.stringify((" + func + ")(" + JSON.stringify(args) + "))", "", false, mycallback);
}
-
WebInspector.AuditRules.GzipRule = function()
{
WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression");
@@ -83,6 +89,8 @@ WebInspector.AuditRules.GzipRule.prototype = {
var summary = result.addChild("", true);
for (var i = 0, length = resources.length; i < length; ++i) {
var resource = resources[i];
+ if (resource.statusCode === 304)
+ continue; // Do not test 304 Not Modified resources as their contents are always empty.
if (this._shouldCompress(resource)) {
var size = resource.resourceSize;
candidateSize += size;
@@ -104,8 +112,11 @@ WebInspector.AuditRules.GzipRule.prototype = {
_isCompressed: function(resource)
{
- var encoding = resource.responseHeaders["Content-Encoding"];
- return encoding === "gzip" || encoding === "deflate";
+ var encodingHeader = resource.responseHeaders["Content-Encoding"];
+ if (!encodingHeader)
+ return false;
+
+ return /\b(?:gzip|deflate)\b/.test(encodingHeader);
},
_shouldCompress: function(resource)
@@ -383,7 +394,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = {
WebInspector.CSSStyleSheet.createForId(styleSheetIds[i], styleSheetCallback.bind(null, styleSheets, i == styleSheetIds.length - 1 ? evalCallback : null));
}
- InspectorBackend.getAllStyles(allStylesCallback);
+ CSSAgent.getAllStyles(allStylesCallback);
}
}
@@ -639,24 +650,23 @@ WebInspector.AuditRules.ImageDimensionsRule = function()
WebInspector.AuditRules.ImageDimensionsRule.prototype = {
doRun: function(resources, result, callback)
{
- function doneCallback(context)
+ var urlToNoDimensionCount = {};
+
+ function doneCallback()
{
- var map = context.urlToNoDimensionCount;
- for (var url in map) {
+ for (var url in urlToNoDimensionCount) {
var entry = entry || result.addChild("A width and height should be specified for all images in order to speed up page display. The following image(s) are missing a width and/or height:", true);
var value = WebInspector.AuditRuleResult.linkifyDisplayName(url);
- if (map[url] > 1)
- value += String.sprintf(" (%d uses)", map[url]);
+ if (urlToNoDimensionCount[url] > 1)
+ value += String.sprintf(" (%d uses)", urlToNoDimensionCount[url]);
entry.addChild(value);
result.violationCount++;
}
callback(entry ? result : null);
}
- function imageStylesReady(imageId, context, styles)
+ function imageStylesReady(imageId, lastCall, styles)
{
- --context.imagesLeft;
-
const node = WebInspector.domAgent.nodeForId(imageId);
var src = node.getAttribute("src");
if (!src.asParsedURL()) {
@@ -672,14 +682,22 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = {
const computedStyle = styles.computedStyle;
if (computedStyle.getPropertyValue("position") === "absolute") {
- if (!context.imagesLeft)
- doneCallback(context);
+ if (lastCall)
+ doneCallback();
return;
}
var widthFound = "width" in styles.styleAttributes;
var heightFound = "height" in styles.styleAttributes;
+ var inlineStyle = styles.inlineStyle;
+ if (inlineStyle) {
+ if (inlineStyle.getPropertyValue("width") !== "")
+ widthFound = true;
+ if (inlineStyle.getPropertyValue("height") !== "")
+ heightFound = true;
+ }
+
for (var i = styles.matchedCSSRules.length - 1; i >= 0 && !(widthFound && heightFound); --i) {
var style = styles.matchedCSSRules[i].style;
if (style.getPropertyValue("width") !== "")
@@ -687,41 +705,25 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = {
if (style.getPropertyValue("height") !== "")
heightFound = true;
}
-
+
if (!widthFound || !heightFound) {
- if (src in context.urlToNoDimensionCount)
- ++context.urlToNoDimensionCount[src];
+ if (src in urlToNoDimensionCount)
+ ++urlToNoDimensionCount[src];
else
- context.urlToNoDimensionCount[src] = 1;
+ urlToNoDimensionCount[src] = 1;
}
- if (!context.imagesLeft)
- doneCallback(context);
+ if (lastCall)
+ doneCallback();
}
- function receivedImages(imageIds)
+ function getStyles(nodeIds)
{
- if (!imageIds || !imageIds.length)
- return callback(null);
- var context = {imagesLeft: imageIds.length, urlToNoDimensionCount: {}};
- for (var i = imageIds.length - 1; i >= 0; --i)
- WebInspector.cssModel.getStylesAsync(imageIds[i], imageStylesReady.bind(this, imageIds[i], context));
- }
-
- function pushImageNodes()
- {
- const nodeIds = [];
- var nodes = document.getElementsByTagName("img");
- for (var i = 0; i < nodes.length; ++i) {
- if (!nodes[i].src)
- continue;
- var nodeId = this.getNodeId(nodes[i]);
- nodeIds.push(nodeId);
- }
- return nodeIds;
+ for (var i = 0; i < nodeIds.length; ++i)
+ WebInspector.cssModel.getStylesAsync(nodeIds[i], imageStylesReady.bind(this, nodeIds[i], i === nodeIds.length - 1));
}
- WebInspector.AuditRules.evaluateInTargetWindow(pushImageNodes, [], receivedImages);
+ DOMAgent.querySelectorAll(0, "img[src]", true, getStyles);
}
}
diff --git a/Source/WebCore/inspector/front-end/AuditsPanel.js b/Source/WebCore/inspector/front-end/AuditsPanel.js
index 47c0b30..3144c78 100644
--- a/Source/WebCore/inspector/front-end/AuditsPanel.js
+++ b/Source/WebCore/inspector/front-end/AuditsPanel.js
@@ -192,7 +192,7 @@ WebInspector.AuditsPanel.prototype = {
_reloadResources: function(callback)
{
this._pageReloadCallback = callback;
- InspectorBackend.reloadPage(false);
+ InspectorAgent.reloadPage(false);
},
_didMainResourceLoad: function()
diff --git a/Source/WebCore/inspector/front-end/BreakpointManager.js b/Source/WebCore/inspector/front-end/BreakpointManager.js
index 94345d5..b62820e 100644
--- a/Source/WebCore/inspector/front-end/BreakpointManager.js
+++ b/Source/WebCore/inspector/front-end/BreakpointManager.js
@@ -207,7 +207,7 @@ WebInspector.BreakpointManager.prototype = {
}
if (!this._breakpointsPushedToFrontend) {
- InspectorBackend.setAllBrowserBreakpoints(this._stickyBreakpoints);
+ BrowserDebuggerAgent.setAllBrowserBreakpoints(this._stickyBreakpoints);
this._breakpointsPushedToFrontend = true;
}
},
@@ -216,6 +216,9 @@ WebInspector.BreakpointManager.prototype = {
{
function didPushNodeByPathToFrontend(path, nodeId)
{
+ if (!nodeId)
+ return;
+
pathToNodeId[path] = nodeId;
pendingCalls -= 1;
if (pendingCalls)
@@ -243,7 +246,7 @@ WebInspector.BreakpointManager.prototype = {
continue;
pathToNodeId[path] = 0;
pendingCalls += 1;
- InspectorBackend.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
+ WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
}
if (!pendingCalls)
this._domBreakpointsRestored = true;
@@ -268,7 +271,7 @@ WebInspector.BreakpointManager.prototype = {
WebInspector.settings.nativeBreakpoints = breakpoints;
this._stickyBreakpoints[WebInspector.settings.projectId] = breakpoints;
- InspectorBackend.setAllBrowserBreakpoints(this._stickyBreakpoints);
+ BrowserDebuggerAgent.setAllBrowserBreakpoints(this._stickyBreakpoints);
},
_validateBreakpoints: function(persistentBreakpoints)
@@ -331,12 +334,12 @@ WebInspector.DOMBreakpoint = function(node, type)
WebInspector.DOMBreakpoint.prototype = {
_enable: function()
{
- InspectorBackend.setDOMBreakpoint(this._nodeId, this._type);
+ BrowserDebuggerAgent.setDOMBreakpoint(this._nodeId, this._type);
},
_disable: function()
{
- InspectorBackend.removeDOMBreakpoint(this._nodeId, this._type);
+ BrowserDebuggerAgent.removeDOMBreakpoint(this._nodeId, this._type);
},
_serializeToJSON: function()
@@ -354,12 +357,12 @@ WebInspector.EventListenerBreakpoint = function(eventName)
WebInspector.EventListenerBreakpoint.prototype = {
_enable: function()
{
- InspectorBackend.setEventListenerBreakpoint(this._eventName);
+ BrowserDebuggerAgent.setEventListenerBreakpoint(this._eventName);
},
_disable: function()
{
- InspectorBackend.removeEventListenerBreakpoint(this._eventName);
+ BrowserDebuggerAgent.removeEventListenerBreakpoint(this._eventName);
},
_serializeToJSON: function()
@@ -377,12 +380,12 @@ WebInspector.XHRBreakpoint = function(url)
WebInspector.XHRBreakpoint.prototype = {
_enable: function()
{
- InspectorBackend.setXHRBreakpoint(this._url);
+ BrowserDebuggerAgent.setXHRBreakpoint(this._url);
},
_disable: function()
{
- InspectorBackend.removeXHRBreakpoint(this._url);
+ BrowserDebuggerAgent.removeXHRBreakpoint(this._url);
},
_serializeToJSON: function()
@@ -476,7 +479,34 @@ WebInspector.DOMBreakpointView.prototype = {
populateStatusMessageElement: function(element, eventData)
{
+ if (this._type === WebInspector.DOMBreakpointTypes.SubtreeModified) {
+ var targetNodeObject = WebInspector.RemoteObject.fromPayload(eventData.targetNode);
+ targetNodeObject.pushNodeToFrontend(decorateNode.bind(this));
+ function decorateNode(targetNodeId)
+ {
+ if (!targetNodeId)
+ return;
+
+ RuntimeAgent.releaseObject(eventData.targetNode);
+ var targetNode = WebInspector.panels.elements.linkifyNodeById(targetNodeId);
+ if (eventData.insertion) {
+ if (targetNodeId !== this._nodeId)
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", targetNode);
+ else
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.");
+ } else
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", targetNode);
+ }
+ } else
+ this._format(element, "Paused on a \"%s\" breakpoint set on %s.");
+ },
+
+ _format: function(element, message, extraSubstitution)
+ {
var substitutions = [WebInspector.domBreakpointTypeLabel(this._type), WebInspector.panels.elements.linkifyNodeById(this._nodeId)];
+ if (extraSubstitution)
+ substitutions.push(extraSubstitution);
+
var formatters = {
s: function(substitution)
{
@@ -489,17 +519,7 @@ WebInspector.DOMBreakpointView.prototype = {
b = document.createTextNode(b);
element.appendChild(b);
}
- if (this._type === WebInspector.DOMBreakpointTypes.SubtreeModified) {
- var targetNode = WebInspector.panels.elements.linkifyNodeById(eventData.targetNodeId);
- if (eventData.insertion) {
- if (eventData.targetNodeId !== this._nodeId)
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.", substitutions.concat(targetNode), formatters, "", append);
- else
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.", substitutions, formatters, "", append);
- } else
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.", substitutions.concat(targetNode), formatters, "", append);
- } else
- WebInspector.formatLocalized("Paused on a \"%s\" breakpoint set on %s.", substitutions, formatters, "", append);
+ WebInspector.formatLocalized(message, substitutions, formatters, "", append);
},
_onRemove: function()
diff --git a/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js
index 0a47bf8..0c46463 100644
--- a/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js
@@ -143,10 +143,10 @@ WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
_debuggerPaused: function(event)
{
- var breakpointId = this._breakpointIdForDebuggerPausedEvent(event.data);
- if (!breakpointId)
+ var breakpoint = event.data.breakpoint;
+ if (!breakpoint)
return;
- var breakpointItem = this._items[breakpointId];
+ var breakpointItem = this._items[breakpoint.id];
if (!breakpointItem)
return;
breakpointItem.element.addStyleClass("breakpoint-hit");
@@ -236,14 +236,6 @@ WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
element.addEventListener("click", clickHandler, false);
},
- _breakpointIdForDebuggerPausedEvent: function(details)
- {
- var callFrame = details.callFrames[0];
- var breakpoint = WebInspector.debuggerModel.findBreakpoint(callFrame.sourceID, callFrame.line);
- if (breakpoint)
- return breakpoint.id;
- },
-
_removeBreakpoint: function(breakpointId)
{
WebInspector.debuggerModel.removeBreakpoint(breakpointId);
diff --git a/Source/WebCore/inspector/front-end/CSSStyleModel.js b/Source/WebCore/inspector/front-end/CSSStyleModel.js
index 69bd7a9..700417e 100644
--- a/Source/WebCore/inspector/front-end/CSSStyleModel.js
+++ b/Source/WebCore/inspector/front-end/CSSStyleModel.js
@@ -83,7 +83,7 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(result);
}
- InspectorBackend.getStylesForNode(nodeId, callback.bind(null, userCallback));
+ CSSAgent.getStylesForNode(nodeId, callback.bind(null, userCallback));
},
getComputedStyleAsync: function(nodeId, userCallback)
@@ -96,7 +96,7 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
}
- InspectorBackend.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
+ CSSAgent.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
},
getInlineStyleAsync: function(nodeId, userCallback)
@@ -109,7 +109,7 @@ WebInspector.CSSStyleModel.prototype = {
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
}
- InspectorBackend.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
+ CSSAgent.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
},
setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback)
@@ -127,10 +127,10 @@ WebInspector.CSSStyleModel.prototype = {
if (!rulePayload)
failureCallback();
else
- InspectorBackend.querySelectorAll(nodeId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
+ DOMAgent.querySelectorAll(nodeId, newSelector, true, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
}
- InspectorBackend.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback));
+ CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback));
},
addRule: function(nodeId, selector, successCallback, failureCallback)
@@ -149,10 +149,10 @@ WebInspector.CSSStyleModel.prototype = {
// Invalid syntax for a selector
failureCallback();
} else
- InspectorBackend.querySelectorAll(nodeId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
+ DOMAgent.querySelectorAll(nodeId, selector, true, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
}
- InspectorBackend.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
+ CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
},
_styleSheetChanged: function(styleSheetId, majorChange)
@@ -166,7 +166,7 @@ WebInspector.CSSStyleModel.prototype = {
if (resource && resource.type === WebInspector.Resource.Type.Stylesheet)
resource.setContent(content, this._onRevert.bind(this, styleSheetId));
}
- InspectorBackend.getStyleSheetText(styleSheetId, callback.bind(this));
+ CSSAgent.getStyleSheetText(styleSheetId, callback.bind(this));
},
_onRevert: function(styleSheetId, contentToRevertTo)
@@ -176,7 +176,7 @@ WebInspector.CSSStyleModel.prototype = {
this._styleSheetChanged(styleSheetId, true);
this.dispatchEventToListeners("stylesheet changed");
}
- InspectorBackend.setStyleSheetText(styleSheetId, contentToRevertTo, callback.bind(this));
+ CSSAgent.setStyleSheetText(styleSheetId, contentToRevertTo, callback.bind(this));
}
}
@@ -348,7 +348,7 @@ WebInspector.CSSStyleDeclaration.prototype = {
}
}
- InspectorBackend.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
+ CSSAgent.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
},
appendProperty: function(name, value, userCallback)
@@ -488,7 +488,7 @@ WebInspector.CSSProperty.prototype = {
throw "No ownerStyle for property";
// An index past all the properties adds a new property to the style.
- InspectorBackend.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
+ CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
},
setValue: function(newValue, userCallback)
@@ -517,7 +517,7 @@ WebInspector.CSSProperty.prototype = {
}
}
- InspectorBackend.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
+ CSSAgent.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
}
}
@@ -548,7 +548,7 @@ WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback)
else
userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload));
}
- InspectorBackend.getStyleSheet(styleSheetId, callback.bind(this));
+ CSSAgent.getStyleSheet(styleSheetId, callback.bind(this));
}
WebInspector.CSSStyleSheet.prototype = {
@@ -569,6 +569,6 @@ WebInspector.CSSStyleSheet.prototype = {
}
}
- InspectorBackend.setStyleSheetText(this.id, newText, callback.bind(this));
+ CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this));
}
}
diff --git a/Source/WebCore/inspector/front-end/CallStackSidebarPane.js b/Source/WebCore/inspector/front-end/CallStackSidebarPane.js
index 503e5f4..e1618b2 100644
--- a/Source/WebCore/inspector/front-end/CallStackSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/CallStackSidebarPane.js
@@ -23,20 +23,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.CallStackSidebarPane = function()
+WebInspector.CallStackSidebarPane = function(model)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
+ this._model = model;
}
WebInspector.CallStackSidebarPane.prototype = {
- update: function(callFrames, eventType, eventData)
+ update: function(details)
{
this.bodyElement.removeChildren();
this.placards = [];
- delete this._selectedCallFrame;
- if (!callFrames) {
+ if (!details) {
var infoElement = document.createElement("div");
infoElement.className = "info";
infoElement.textContent = WebInspector.UIString("Not Paused");
@@ -44,6 +44,7 @@ WebInspector.CallStackSidebarPane.prototype = {
return;
}
+ var callFrames = details.callFrames;
var title;
var subtitle;
var script;
@@ -65,12 +66,10 @@ WebInspector.CallStackSidebarPane.prototype = {
else
subtitle = WebInspector.UIString("(internal script)");
- if (callFrame.line > 0) {
- if (subtitle)
- subtitle += ":" + callFrame.line;
- else
- subtitle = WebInspector.UIString("line %d", callFrame.line);
- }
+ if (subtitle)
+ subtitle += ":" + (callFrame.line + 1);
+ else
+ subtitle = WebInspector.UIString("line %d", callFrame.line + 1);
var placard = new WebInspector.Placard(title, subtitle);
placard.callFrame = callFrame;
@@ -81,30 +80,20 @@ WebInspector.CallStackSidebarPane.prototype = {
this.bodyElement.appendChild(placard.element);
}
- if (WebInspector.debuggerModel.findBreakpoint(callFrames[0].sourceID, callFrames[0].line))
+ if (details.breakpoint)
this._scriptBreakpointHit();
- else if (eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint)
- this._nativeBreakpointHit(eventData);
- },
-
- get selectedCallFrame()
- {
- return this._selectedCallFrame;
+ else if (details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint)
+ this._nativeBreakpointHit(details.eventData);
},
set selectedCallFrame(x)
{
- if (this._selectedCallFrame === x)
- return;
-
- this._selectedCallFrame = x;
+ this._model.selectedCallFrame = x;
for (var i = 0; i < this.placards.length; ++i) {
var placard = this.placards[i];
- placard.selected = (placard.callFrame === this._selectedCallFrame);
+ placard.selected = (placard.callFrame === x);
}
-
- this.dispatchEventToListeners("call frame selected");
},
handleShortcut: function(event)
@@ -143,11 +132,11 @@ WebInspector.CallStackSidebarPane.prototype = {
_selectedCallFrameIndex: function()
{
- if (!this._selectedCallFrame)
+ if (!this._model.selectedCallFrame)
return -1;
for (var i = 0; i < this.placards.length; ++i) {
var placard = this.placards[i];
- if (placard.callFrame === this._selectedCallFrame)
+ if (placard.callFrame === this._model.selectedCallFrame)
return i;
}
return -1;
diff --git a/Source/WebCore/inspector/front-end/ConsoleView.js b/Source/WebCore/inspector/front-end/ConsoleView.js
index 35d1ebf..f59d87f 100644
--- a/Source/WebCore/inspector/front-end/ConsoleView.js
+++ b/Source/WebCore/inspector/front-end/ConsoleView.js
@@ -316,7 +316,7 @@ WebInspector.ConsoleView.prototype = {
requestClearMessages: function()
{
- InspectorBackend.clearConsoleMessages();
+ ConsoleAgent.clearConsoleMessages();
},
clearMessages: function()
@@ -353,21 +353,30 @@ WebInspector.ConsoleView.prototype = {
if (!expressionString && !prefix)
return;
- var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix);
- // Collect comma separated object properties for the completion.
+ this.evalInInspectedWindow(expressionString, "completion", true, evaluated.bind(this));
- var includeCommandLineAPI = (!dotNotation && !bracketNotation);
- var injectedScriptAccess;
- if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused)
- InspectorBackend.getCompletionsOnCallFrame(WebInspector.panels.scripts.selectedCallFrameId(), expressionString, includeCommandLineAPI, reportCompletions);
- else
- InspectorBackend.getCompletions(expressionString, includeCommandLineAPI, reportCompletions);
- },
+ function evaluated(result)
+ {
+ if (!result)
+ return;
+ result.getProperties(true, false, evaluatedProperties.bind(this));
+ }
- _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) {
- if (isException)
- return;
+ function evaluatedProperties(properties)
+ {
+ RuntimeAgent.releaseObjectGroup(0, "completion");
+ var propertyNames = [];
+ for (var i = 0; properties && i < properties.length; ++i)
+ propertyNames.push(properties[i].name);
+
+ var includeCommandLineAPI = (!dotNotation && !bracketNotation);
+ if (includeCommandLineAPI)
+ propertyNames.splice(0, 0, "dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear");
+ this._reportCompletions(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, propertyNames);
+ }
+ },
+ _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, properties) {
if (bracketNotation) {
if (prefix.length && prefix[0] === "'")
var quoteUsed = "'";
@@ -376,7 +385,7 @@ WebInspector.ConsoleView.prototype = {
}
var results = [];
- var properties = Object.keys(result).sort();
+ properties.sort();
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
@@ -417,7 +426,7 @@ WebInspector.ConsoleView.prototype = {
var itemAction = function () {
WebInspector.settings.monitoringXHREnabled = !WebInspector.settings.monitoringXHREnabled;
- InspectorBackend.setMonitoringXHREnabled(WebInspector.settings.monitoringXHREnabled);
+ ConsoleAgent.setMonitoringXHREnabled(WebInspector.settings.monitoringXHREnabled);
}.bind(this);
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendCheckboxItem(WebInspector.UIString("XMLHttpRequest logging"), itemAction, WebInspector.settings.monitoringXHREnabled)
@@ -513,7 +522,7 @@ WebInspector.ConsoleView.prototype = {
evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, callback)
{
if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, objectGroup, includeCommandLineAPI, callback);
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, callback);
return;
}
@@ -526,7 +535,7 @@ WebInspector.ConsoleView.prototype = {
{
callback(WebInspector.RemoteObject.fromPayload(result));
}
- InspectorBackend.evaluate(expression, objectGroup, includeCommandLineAPI, evalCallback);
+ RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, evalCallback);
},
_enterKeyPressed: function(event)
diff --git a/Source/WebCore/inspector/front-end/CookieItemsView.js b/Source/WebCore/inspector/front-end/CookieItemsView.js
index dc76b39..c8187bb 100644
--- a/Source/WebCore/inspector/front-end/CookieItemsView.js
+++ b/Source/WebCore/inspector/front-end/CookieItemsView.js
@@ -140,7 +140,7 @@ WebInspector.CookieItemsView.prototype = {
_deleteCookie: function(cookie)
{
- InspectorBackend.deleteCookie(cookie.name, this._cookieDomain);
+ InspectorAgent.deleteCookie(cookie.name, this._cookieDomain);
this._update();
},
diff --git a/Source/WebCore/inspector/front-end/DOMAgent.js b/Source/WebCore/inspector/front-end/DOMAgent.js
index 3645bb9..cb28aba 100644
--- a/Source/WebCore/inspector/front-end/DOMAgent.js
+++ b/Source/WebCore/inspector/front-end/DOMAgent.js
@@ -223,12 +223,11 @@ WebInspector.DOMNode.prototype = {
}
}
-WebInspector.DOMDocument = function(domAgent, defaultView, payload)
+WebInspector.DOMDocument = function(domAgent, payload)
{
WebInspector.DOMNode.call(this, this, payload);
this._listeners = {};
this._domAgent = domAgent;
- this.defaultView = defaultView;
}
WebInspector.DOMDocument.prototype = {
@@ -269,44 +268,48 @@ WebInspector.DOMDocument.prototype = {
WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;
-
-WebInspector.DOMWindow = function(domAgent)
-{
- this._domAgent = domAgent;
+WebInspector.DOMAgent = function() {
+ this._idToDOMNode = null;
+ this._document = null;
+ InspectorBackend.registerDomainDispatcher("DOM", new WebInspector.DOMDispatcher(this));
}
-WebInspector.DOMWindow.prototype = {
- get document()
- {
- return this._domAgent.document;
- },
-
- get Node()
+WebInspector.DOMAgent.prototype = {
+ requestDocument: function(callback)
{
- return WebInspector.DOMNode;
+ if (this._document) {
+ if (callback)
+ callback(this._document);
+ } else
+ this._documentUpdated(callback);
},
- get Element()
+ pushNodeToFrontend: function(objectId, callback)
{
- return WebInspector.DOMNode;
+ function mycallback()
+ {
+ if (this._document)
+ DOMAgent.pushNodeToFrontend(objectId, callback);
+ else {
+ if (callback)
+ callback(0);
+ }
+ }
+ this.requestDocument(mycallback.bind(this));
},
- Object: function()
- {
- }
-}
-
-WebInspector.DOMAgent = function() {
- this._window = new WebInspector.DOMWindow(this);
- this._idToDOMNode = null;
- this.document = null;
- InspectorBackend.registerDomainDispatcher("DOM", new WebInspector.DOMDispatcher(this));
-}
-
-WebInspector.DOMAgent.prototype = {
- get domWindow()
+ pushNodeByPathToFrontend: function(path, callback)
{
- return this._window;
+ function mycallback()
+ {
+ if (this._document)
+ DOMAgent.pushNodeByPathToFrontend(path, callback);
+ else {
+ if (callback)
+ callback(0);
+ }
+ }
+ this.requestDocument(mycallback.bind(this));
},
getChildNodesAsync: function(parent, callback)
@@ -319,25 +322,25 @@ WebInspector.DOMAgent.prototype = {
function mycallback() {
callback(parent.children);
}
- InspectorBackend.getChildNodes(parent.id, mycallback);
+ DOMAgent.getChildNodes(parent.id, mycallback);
},
setAttributeAsync: function(node, name, value, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.setAttribute(node.id, name, value, mycallback);
+ DOMAgent.setAttribute(node.id, name, value, mycallback);
},
removeAttributeAsync: function(node, name, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.removeAttribute(node.id, name, mycallback);
+ DOMAgent.removeAttribute(node.id, name, mycallback);
},
setTextNodeValueAsync: function(node, text, callback)
{
var mycallback = this._didApplyDomChange.bind(this, node, callback);
- InspectorBackend.setTextNodeValue(node.id, text, mycallback);
+ DOMAgent.setTextNodeValue(node.id, text, mycallback);
},
_didApplyDomChange: function(node, callback, success)
@@ -356,7 +359,7 @@ WebInspector.DOMAgent.prototype = {
var node = this._idToDOMNode[nodeId];
node._setAttributesPayload(attrsArray);
var event = {target: node};
- this.document._fireDomEvent("DOMAttrModified", event);
+ this._document._fireDomEvent("DOMAttrModified", event);
},
_characterDataModified: function(nodeId, newValue)
@@ -365,7 +368,7 @@ WebInspector.DOMAgent.prototype = {
node._nodeValue = newValue;
node.textContent = newValue;
var event = { target : node };
- this.document._fireDomEvent("DOMCharacterDataModified", event);
+ this._document._fireDomEvent("DOMCharacterDataModified", event);
},
nodeForId: function(nodeId)
@@ -373,27 +376,43 @@ WebInspector.DOMAgent.prototype = {
return this._idToDOMNode[nodeId];
},
+ _documentUpdated: function(callback)
+ {
+ function mycallback(root)
+ {
+ this._setDocument(root);
+ if (callback)
+ callback(this._document);
+ }
+ DOMAgent.getDocument(mycallback.bind(this));
+ },
+
_setDocument: function(payload)
{
this._idToDOMNode = {};
if (payload && "id" in payload) {
- this.document = new WebInspector.DOMDocument(this, this._window, payload);
- this._idToDOMNode[payload.id] = this.document;
- this._bindNodes(this.document.children);
+ this._document = new WebInspector.DOMDocument(this, payload);
+ this._idToDOMNode[payload.id] = this._document;
+ this._bindNodes(this._document.children);
WebInspector.breakpointManager.restoreDOMBreakpoints();
} else
- this.document = null;
- WebInspector.panels.elements.setDocument(this.document);
+ this._document = null;
+ WebInspector.panels.elements.setDocument(this._document);
},
_setDetachedRoot: function(payload)
{
- var root = new WebInspector.DOMNode(this.document, payload);
+ var root = new WebInspector.DOMNode(this._document, payload);
this._idToDOMNode[payload.id] = root;
},
_setChildNodes: function(parentId, payloads)
{
+ if (!parentId && payloads.length) {
+ this._setDetachedRoot(payloads[0]);
+ return;
+ }
+
var parent = this._idToDOMNode[parentId];
parent._setChildrenPayload(payloads);
this._bindNodes(parent.children);
@@ -426,7 +445,7 @@ WebInspector.DOMAgent.prototype = {
var node = parent._insertChild(prev, payload);
this._idToDOMNode[node.id] = node;
var event = { target : node, relatedNode : parent };
- this.document._fireDomEvent("DOMNodeInserted", event);
+ this._document._fireDomEvent("DOMNodeInserted", event);
},
_childNodeRemoved: function(parentId, nodeId)
@@ -435,7 +454,7 @@ WebInspector.DOMAgent.prototype = {
var node = this._idToDOMNode[nodeId];
parent.removeChild_(node);
var event = { target : node, relatedNode : parent };
- this.document._fireDomEvent("DOMNodeRemoved", event);
+ this._document._fireDomEvent("DOMNodeRemoved", event);
delete this._idToDOMNode[nodeId];
this._removeBreakpoints(node);
},
@@ -457,9 +476,9 @@ WebInspector.DOMDispatcher = function(domAgent)
}
WebInspector.DOMDispatcher.prototype = {
- setDocument: function(payload)
+ documentUpdated: function()
{
- this._domAgent._setDocument(payload);
+ this._domAgent._documentUpdated();
},
attributesUpdated: function(nodeId, attrsArray)
@@ -477,11 +496,6 @@ WebInspector.DOMDispatcher.prototype = {
this._domAgent._setChildNodes(parentId, payloads);
},
- setDetachedRoot: function(payload)
- {
- this._domAgent._setDetachedRoot(payload);
- },
-
childNodeCountUpdated: function(nodeId, newValue)
{
this._domAgent._childNodeCountUpdated(nodeId, newValue);
@@ -495,6 +509,16 @@ WebInspector.DOMDispatcher.prototype = {
childNodeRemoved: function(parentId, nodeId)
{
this._domAgent._childNodeRemoved(parentId, nodeId);
+ },
+
+ inspectElementRequested: function(nodeId)
+ {
+ WebInspector.updateFocusedNode(nodeId);
+ },
+
+ addNodesToSearchResult: function(nodeIds)
+ {
+ WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
}
}
@@ -511,7 +535,7 @@ WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync = function(cal
callback(applicationCaches);
}
- InspectorBackend.getApplicationCaches(mycallback);
+ ApplicationCacheAgent.getApplicationCaches(mycallback);
}
WebInspector.ApplicationCacheDispatcher.prototype = {
@@ -540,7 +564,7 @@ WebInspector.Cookies.getCookiesAsync = function(callback)
callback(cookies, true);
}
- InspectorBackend.getCookies(mycallback);
+ InspectorAgent.getCookies(mycallback);
}
WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
@@ -585,5 +609,5 @@ WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callb
{
if (!node)
return;
- InspectorBackend.getEventListenersForNode(node.id, callback);
+ DOMAgent.getEventListenersForNode(node.id, callback);
}
diff --git a/Source/WebCore/inspector/front-end/DOMStorage.js b/Source/WebCore/inspector/front-end/DOMStorage.js
index d3d2226..ea24921 100644
--- a/Source/WebCore/inspector/front-end/DOMStorage.js
+++ b/Source/WebCore/inspector/front-end/DOMStorage.js
@@ -39,11 +39,6 @@ WebInspector.DOMStorage.prototype = {
return this._id;
},
- get domStorage()
- {
- return this._domStorage;
- },
-
get domain()
{
return this._domain;
@@ -56,17 +51,17 @@ WebInspector.DOMStorage.prototype = {
getEntries: function(callback)
{
- InspectorBackend.getDOMStorageEntries(this._id, callback);
+ DOMStorageAgent.getDOMStorageEntries(this._id, callback);
},
setItem: function(key, value, callback)
{
- InspectorBackend.setDOMStorageItem(this._id, key, value, callback);
+ DOMStorageAgent.setDOMStorageItem(this._id, key, value, callback);
},
removeItem: function(key, callback)
{
- InspectorBackend.removeDOMStorageItem(this._id, key, callback);
+ DOMStorageAgent.removeDOMStorageItem(this._id, key, callback);
}
}
@@ -87,12 +82,6 @@ WebInspector.DOMStorageDispatcher.prototype = {
WebInspector.panels.resources.addDOMStorage(domStorage);
},
- selectDOMStorage: function(o)
- {
- WebInspector.showPanel("resources");
- WebInspector.panels.resources.selectDOMStorage(o);
- },
-
updateDOMStorage: function(storageId)
{
WebInspector.panels.resources.updateDOMStorage(storageId);
diff --git a/Source/WebCore/inspector/front-end/DataGrid.js b/Source/WebCore/inspector/front-end/DataGrid.js
index 45f0b55..6d54941 100644
--- a/Source/WebCore/inspector/front-end/DataGrid.js
+++ b/Source/WebCore/inspector/front-end/DataGrid.js
@@ -809,14 +809,14 @@ WebInspector.DataGrid.prototype = {
dataGridNodeFromNode: function(target)
{
var rowElement = target.enclosingNodeOrSelfWithNodeName("tr");
- return rowElement._dataGridNode;
+ return rowElement && rowElement._dataGridNode;
},
dataGridNodeFromPoint: function(x, y)
{
var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
- return rowElement._dataGridNode;
+ return rowElement && rowElement._dataGridNode;
},
_clickInHeaderCell: function(event)
diff --git a/Source/WebCore/inspector/front-end/Database.js b/Source/WebCore/inspector/front-end/Database.js
index faa17fa..e4bafea 100644
--- a/Source/WebCore/inspector/front-end/Database.js
+++ b/Source/WebCore/inspector/front-end/Database.js
@@ -81,7 +81,7 @@ WebInspector.Database.prototype = {
{
callback(names.sort());
}
- InspectorBackend.getDatabaseTableNames(this._id, sortingCallback);
+ DatabaseAgent.getDatabaseTableNames(this._id, sortingCallback);
},
executeSql: function(query, onSuccess, onError)
@@ -94,7 +94,7 @@ WebInspector.Database.prototype = {
}
WebInspector.DatabaseDispatcher._callbacks[transactionId] = {"onSuccess": onSuccess, "onError": onError};
}
- InspectorBackend.executeSQL(this._id, query, callback);
+ DatabaseAgent.executeSQL(this._id, query, callback);
}
}
@@ -107,8 +107,6 @@ WebInspector.DatabaseDispatcher._callbacks = {};
WebInspector.DatabaseDispatcher.prototype = {
addDatabase: function(payload)
{
- if (!WebInspector.panels.resources)
- return;
var database = new WebInspector.Database(
payload.id,
payload.domain,
@@ -117,12 +115,6 @@ WebInspector.DatabaseDispatcher.prototype = {
WebInspector.panels.resources.addDatabase(database);
},
- selectDatabase: function(o)
- {
- WebInspector.showPanel("resources");
- WebInspector.panels.resources.selectDatabase(o);
- },
-
sqlTransactionSucceeded: function(transactionId, columnNames, values)
{
if (!WebInspector.DatabaseDispatcher._callbacks[transactionId])
diff --git a/Source/WebCore/inspector/front-end/DebuggerModel.js b/Source/WebCore/inspector/front-end/DebuggerModel.js
index 1bf1e47..d31ff24 100644
--- a/Source/WebCore/inspector/front-end/DebuggerModel.js
+++ b/Source/WebCore/inspector/front-end/DebuggerModel.js
@@ -52,7 +52,7 @@ WebInspector.DebuggerModel.Events = {
WebInspector.DebuggerModel.prototype = {
enableDebugger: function()
{
- InspectorBackend.enableDebugger();
+ DebuggerAgent.enable();
if (this._breakpointsPushedToBackend)
return;
var breakpoints = WebInspector.settings.breakpoints;
@@ -68,12 +68,12 @@ WebInspector.DebuggerModel.prototype = {
disableDebugger: function()
{
- InspectorBackend.disableDebugger();
+ DebuggerAgent.disable();
},
- continueToLine: function(sourceID, lineNumber)
+ continueToLocation: function(sourceID, lineNumber, columnNumber)
{
- InspectorBackend.continueToLocation(sourceID, lineNumber, 0);
+ DebuggerAgent.continueToLocation(sourceID, lineNumber, columnNumber);
},
setBreakpoint: function(url, lineNumber, columnNumber, condition, enabled)
@@ -89,7 +89,7 @@ WebInspector.DebuggerModel.prototype = {
this._saveBreakpoints();
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
}
- InspectorBackend.setJavaScriptBreakpoint(url, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this, this._breakpointsPushedToBackend));
+ DebuggerAgent.setJavaScriptBreakpoint(url, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this, this._breakpointsPushedToBackend));
},
setBreakpointBySourceId: function(sourceID, lineNumber, columnNumber, condition, enabled)
@@ -103,12 +103,12 @@ WebInspector.DebuggerModel.prototype = {
this._breakpoints[breakpointId] = breakpoint;
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointAdded, breakpoint);
}
- InspectorBackend.setJavaScriptBreakpointBySourceId(sourceID, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this));
+ DebuggerAgent.setJavaScriptBreakpointBySourceId(sourceID, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this));
},
removeBreakpoint: function(breakpointId)
{
- InspectorBackend.removeJavaScriptBreakpoint(breakpointId);
+ DebuggerAgent.removeJavaScriptBreakpoint(breakpointId);
var breakpoint = this._breakpoints[breakpointId];
delete this._breakpoints[breakpointId];
this._saveBreakpoints();
@@ -173,17 +173,6 @@ WebInspector.DebuggerModel.prototype = {
return breakpoints;
},
- findBreakpoint: function(sourceID, lineNumber)
- {
- for (var id in this._breakpoints) {
- var locations = this._breakpoints[id].locations;
- for (var i = 0; i < locations.length; ++i) {
- if (locations[i].sourceID == sourceID && locations[i].lineNumber + 1 === lineNumber)
- return this._breakpoints[id];
- }
- }
- },
-
reset: function()
{
this._paused = false;
@@ -230,7 +219,7 @@ WebInspector.DebuggerModel.prototype = {
} else
WebInspector.log(newBodyOrErrorMessage, WebInspector.ConsoleMessage.MessageLevel.Warning);
}
- InspectorBackend.editScriptSource(sourceID, scriptSource, didEditScriptSource.bind(this));
+ DebuggerAgent.editScriptSource(sourceID, scriptSource, didEditScriptSource.bind(this));
},
_updateScriptSource: function(sourceID, scriptSource)
@@ -286,6 +275,7 @@ WebInspector.DebuggerModel.prototype = {
{
this._paused = true;
this._callFrames = details.callFrames;
+ details.breakpoint = this._breakpointForCallFrame(details.callFrames[0]);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, details);
},
@@ -296,6 +286,23 @@ WebInspector.DebuggerModel.prototype = {
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
},
+ _breakpointForCallFrame: function(callFrame)
+ {
+ function match(location)
+ {
+ if (location.sourceID != callFrame.sourceID)
+ return false;
+ return location.lineNumber === callFrame.line && location.columnNumber === callFrame.column;
+ }
+ for (var id in this._breakpoints) {
+ var breakpoint = this._breakpoints[id];
+ for (var i = 0; i < breakpoint.locations.length; ++i) {
+ if (match(breakpoint.locations[i]))
+ return breakpoint;
+ }
+ }
+ },
+
_parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType)
{
var script = new WebInspector.Script(sourceID, sourceURL, "", lineOffset, columnOffset, length, undefined, undefined, scriptWorldType);
diff --git a/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js b/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js
new file mode 100644
index 0000000..a97db34
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DebuggerPresentationModel = function()
+{
+ this._breakpoints = {};
+ this._sourceLocationToBreakpointId = {};
+
+ WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
+ WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
+ WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
+}
+
+WebInspector.DebuggerPresentationModel.Events = {
+ BreakpointAdded: "breakpoint-added",
+ BreakpointRemoved: "breakpoint-removed"
+}
+
+WebInspector.DebuggerPresentationModel.prototype = {
+ breakpointsForSourceFileId: function(sourceFileId)
+ {
+ var breakpoints = [];
+ for (var id in this._breakpoints) {
+ var breakpoint = this._breakpoints[id];
+ if (breakpoint.sourceFileId === sourceFileId)
+ breakpoints.push(breakpoint);
+ }
+ return breakpoints;
+ },
+
+ _breakpointAdded: function(event)
+ {
+ var breakpoint = event.data;
+ var location = breakpoint.locations.length ? breakpoint.locations[0] : breakpoint;
+ var sourceLocation = this._actualLocationToSourceLocation(breakpoint.url || breakpoint.sourceID, location.lineNumber, location.columnNumber);
+
+ var encodedSourceLocation = this._encodeSourceLocation(sourceLocation.sourceFileId, sourceLocation.lineNumber);
+ if (encodedSourceLocation in this._sourceLocationToBreakpointId) {
+ // We can't show more than one breakpoint on a single source frame line. Remove newly added breakpoint.
+ WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+ return;
+ }
+
+ var presentationBreakpoint = {
+ sourceFileId: sourceLocation.sourceFileId,
+ lineNumber: sourceLocation.lineNumber,
+ url: breakpoint.url,
+ resolved: !!breakpoint.locations.length,
+ condition: breakpoint.condition,
+ enabled: breakpoint.enabled
+ };
+
+ this._sourceLocationToBreakpointId[encodedSourceLocation] = breakpoint.id;
+ this._breakpoints[breakpoint.id] = presentationBreakpoint;
+
+ this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, presentationBreakpoint);
+ },
+
+ _breakpointRemoved: function(event)
+ {
+ var breakpointId = event.data;
+ var breakpoint = this._breakpoints[breakpointId];
+ var encodedSourceLocation = this._encodeSourceLocation(breakpoint.sourceFileId, breakpoint.lineNumber);
+ delete this._breakpoints[breakpointId];
+ delete this._sourceLocationToBreakpointId[encodedSourceLocation];
+ this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint);
+ },
+
+ _breakpointResolved: function(event)
+ {
+ var breakpoint = event.data;
+ this._breakpointRemoved({ data: breakpoint.id });
+ this._breakpointAdded({ data: breakpoint });
+ },
+
+ _encodeSourceLocation: function(sourceFileId, lineNumber)
+ {
+ return sourceFileId + ":" + lineNumber;
+ },
+
+ set selectedCallFrame(callFrame)
+ {
+ this._selectedCallFrame = callFrame;
+ if (!callFrame)
+ return;
+
+ var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.sourceID);
+ callFrame.sourceLocation = this._actualLocationToSourceLocation(script.sourceURL || script.sourceID, callFrame.line, callFrame.column);
+ this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, callFrame);
+ },
+
+ get selectedCallFrame()
+ {
+ return this._selectedCallFrame;
+ },
+
+ _actualLocationToSourceLocation: function(sourceID, lineNumber, columnNumber)
+ {
+ // TODO: use source mapping to obtain source location.
+ return { sourceFileId: sourceID, lineNumber: lineNumber, columnNumber: columnNumber };
+ }
+}
+
+WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype;
diff --git a/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js b/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js
new file mode 100644
index 0000000..14ba142
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js
@@ -0,0 +1,707 @@
+/*
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.HeapSnapshotGridNode = function(tree, hasChildren, populateCount)
+{
+ WebInspector.DataGridNode.call(this, null, hasChildren);
+ this._defaultPopulateCount = populateCount;
+ this._provider = null;
+ this.addEventListener("populate", this._populate, this);
+}
+
+WebInspector.HeapSnapshotGridNode.prototype = {
+ createCell: function(columnIdentifier)
+ {
+ var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
+ if (this._searchMatched)
+ cell.addStyleClass("highlight");
+ return cell;
+ },
+
+ _populate: function(event)
+ {
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doPopulate.bind(this));
+
+ function doPopulate()
+ {
+ this._provider.sort(this.comparator());
+ this._provider.first();
+ this.populateChildren();
+ this.removeEventListener("populate", this._populate, this);
+ }
+ },
+
+ populateChildren: function(provider, howMany, atIndex)
+ {
+ if (!howMany && provider) {
+ howMany = provider.instancesCount;
+ provider.resetInstancesCount();
+ }
+ provider = provider || this._provider;
+ howMany = howMany || this._defaultPopulateCount;
+ atIndex = atIndex || this.children.length;
+ var haveSavedChildren = !!this._savedChildren;
+ if (haveSavedChildren) {
+ haveSavedChildren = false;
+ for (var c in this._savedChildren) {
+ haveSavedChildren = true;
+ break;
+ }
+ }
+ for ( ; howMany > 0 && provider.hasNext(); provider.next(), provider.incInstancesCount(), --howMany) {
+ var item = provider.item;
+ if (haveSavedChildren) {
+ var hash = this._childHashForEntity(item);
+ if (hash in this._savedChildren) {
+ this.insertChild(this._savedChildren[hash], atIndex++);
+ continue;
+ }
+ }
+ this.insertChild(this._createChildNode(provider), atIndex++);
+ }
+ if (provider.hasNext())
+ this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, provider.length), atIndex++);
+ },
+
+ _saveChildren: function()
+ {
+ this._savedChildren = {};
+ for (var i = 0, childrenCount = this.children.length; i < childrenCount; ++i) {
+ var child = this.children[i];
+ if (child.expanded)
+ this._savedChildren[this._childHashForNode(child)] = child;
+ }
+ },
+
+ sort: function()
+ {
+ var comparator = this.comparator();
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doSort.bind(this));
+
+ function doSort()
+ {
+ if (!this._provider.sort(comparator))
+ return;
+ this._saveChildren();
+ this.removeChildren();
+ this._provider.first();
+ this.populateChildren(this._provider);
+ for (var i = 0, l = this.children.length; i < l; ++i) {
+ var child = this.children[i];
+ if (child.expanded)
+ child.sort();
+ }
+ }
+ }
+};
+
+WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
+
+WebInspector.HeapSnapshotGenericObjectNode = function(tree, node, hasChildren, populateCount)
+{
+ WebInspector.HeapSnapshotGridNode.call(this, tree, hasChildren, populateCount);
+ this._name = node.name;
+ this._type = node.type;
+ this._shallowSize = node.selfSize;
+ this._retainedSize = node.retainedSize;
+ this._retainedSizeExact = this._shallowSize === this._retainedSize;
+ this.snapshotNodeId = node.id;
+ this.snapshotNodeIndex = node.nodeIndex;
+};
+
+WebInspector.HeapSnapshotGenericObjectNode.prototype = {
+ createCell: function(columnIdentifier)
+ {
+ var cell = columnIdentifier !== "object" ? WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier) : this._createObjectCell();
+ if (this._searchMatched)
+ cell.addStyleClass("highlight");
+ return cell;
+ },
+
+ _createObjectCell: function()
+ {
+ var cell = document.createElement("td");
+ cell.className = "object-column";
+ var div = document.createElement("div");
+ div.className = "source-code event-properties";
+ div.style.overflow = "hidden";
+ var data = this.data["object"];
+ if (this._prefixObjectCell)
+ this._prefixObjectCell(div, data);
+ var valueSpan = document.createElement("span");
+ valueSpan.className = "value console-formatted-" + data.valueStyle;
+ valueSpan.textContent = data.value;
+ div.appendChild(valueSpan);
+ cell.appendChild(div);
+ cell.addStyleClass("disclosure");
+ if (this.depth)
+ cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
+ return cell;
+ },
+
+ get _countPercent()
+ {
+ return this._count / this.tree.snapshot.nodesCount * 100.0;
+ },
+
+ get data()
+ {
+ var data = this._emptyData();
+
+ var value = this._name;
+ var valueStyle = "object";
+ switch (this._type) {
+ case "string":
+ value = "\"" + value + "\"";
+ valueStyle = "string";
+ break;
+ case "regexp":
+ value = "/" + value + "/";
+ valueStyle = "string";
+ break;
+ case "closure":
+ value = "function " + value + "()";
+ valueStyle = "function";
+ break;
+ case "number":
+ valueStyle = "number";
+ break;
+ case "hidden":
+ valueStyle = "null";
+ break;
+ case "array":
+ value += "[]";
+ break;
+ };
+ data["object"] = { valueStyle: valueStyle, value: value + " @" + this.snapshotNodeId };
+
+ var view = this.dataGrid.snapshotView;
+ data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize);
+ data["retainedSize"] = (this._retainedSizeExact ? "" : "\u2248") + (view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize));
+
+ return this._enhanceData ? this._enhanceData(data) : data;
+ },
+
+ set exactRetainedSize(size)
+ {
+ this._retainedSize = size;
+ this._retainedSizeExact = true;
+ this.refresh();
+ },
+
+ get _retainedSizePercent()
+ {
+ return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0;
+ },
+
+ get _shallowSizePercent()
+ {
+ return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
+ }
+}
+
+WebInspector.HeapSnapshotGenericObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;
+
+WebInspector.HeapSnapshotObjectNode = function(tree, edge)
+{
+ var node = edge.node;
+ var provider = this._createProvider(tree.snapshot, node.rawEdges);
+ WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 100);
+ this._referenceName = edge.name;
+ this._referenceType = edge.type;
+ this._provider = provider;
+}
+
+WebInspector.HeapSnapshotObjectNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item);
+ },
+
+ _createProvider: function(snapshot, rawEdges)
+ {
+ var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+ return new WebInspector.HeapSnapshotEdgesProvider(
+ snapshot,
+ rawEdges,
+ function(edge) {
+ return !edge.isInvisible
+ && (showHiddenData || (!edge.isHidden && !edge.node.isHidden));
+ });
+ },
+
+ _childHashForEntity: function(edge)
+ {
+ return edge.type + "#" + edge.name;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode._referenceType + "#" + childNode._referenceName;
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["!edgeName", sortAscending, "retainedSize", false],
+ count: ["!edgeName", true, "retainedSize", false],
+ shallowSize: ["selfSize", sortAscending, "!edgeName", true],
+ retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
+ }[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _emptyData: function()
+ {
+ return {count:"", addedCount: "", removedCount: "", countDelta:"", addedSize: "", removedSize: "", sizeDelta: ""};
+ },
+
+ _enhanceData: function(data)
+ {
+ var name = this._referenceName;
+ if (name === "") name = "(empty)";
+ var nameClass = "name";
+ switch (this._referenceType) {
+ case "context":
+ nameClass = "console-formatted-number";
+ break;
+ case "internal":
+ case "hidden":
+ nameClass = "console-formatted-null";
+ break;
+ }
+ data["object"].nameClass = nameClass;
+ data["object"].name = name;
+ return data;
+ },
+
+ _prefixObjectCell: function(div, data)
+ {
+ var nameSpan = document.createElement("span");
+ nameSpan.className = data.nameClass;
+ nameSpan.textContent = data.name;
+ var separatorSpan = document.createElement("span");
+ separatorSpan.className = "separator";
+ separatorSpan.textContent = ": ";
+ div.appendChild(nameSpan);
+ div.appendChild(separatorSpan);
+ }
+}
+
+WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;
+
+WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node)
+{
+ var provider = this._createProvider(baseSnapshot || snapshot, node.rawEdges);
+ WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 100);
+ this._isDeletedNode = !!baseSnapshot;
+ this._provider = provider;
+};
+
+WebInspector.HeapSnapshotInstanceNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item);
+ },
+
+ _createProvider: function(snapshot, rawEdges)
+ {
+ var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+ return new WebInspector.HeapSnapshotEdgesProvider(
+ snapshot,
+ rawEdges,
+ function(edge) {
+ return !edge.isInvisible
+ && (showHiddenData || (!edge.isHidden && !edge.node.isHidden));
+ });
+ },
+
+ _childHashForEntity: function(edge)
+ {
+ return edge.type + "#" + edge.name;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode._referenceType + "#" + childNode._referenceName;
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["!edgeName", sortAscending, "retainedSize", false],
+ count: ["!edgeName", true, "retainedSize", false],
+ addedSize: ["selfSize", sortAscending, "!edgeName", true],
+ removedSize: ["selfSize", sortAscending, "!edgeName", true],
+ shallowSize: ["selfSize", sortAscending, "!edgeName", true],
+ retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
+ }[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _emptyData: function()
+ {
+ return {count:"", countDelta:"", sizeDelta: ""};
+ },
+
+ _enhanceData: function(data)
+ {
+ if (this._isDeletedNode) {
+ data["addedCount"] = "";
+ data["addedSize"] = "";
+ data["removedCount"] = "\u2022";
+ data["removedSize"] = Number.bytesToString(this._shallowSize);
+ } else {
+ data["addedCount"] = "\u2022";
+ data["addedSize"] = Number.bytesToString(this._shallowSize);
+ data["removedCount"] = "";
+ data["removedSize"] = "";
+ }
+ return data;
+ }
+}
+
+WebInspector.HeapSnapshotInstanceNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;
+
+WebInspector.HeapSnapshotConstructorNode = function(tree, constructor, aggregate)
+{
+ WebInspector.HeapSnapshotGridNode.call(this, tree, aggregate.count > 0, 100);
+ this._name = constructor;
+ this._count = aggregate.count;
+ this._shallowSize = aggregate.self;
+ this._retainedSize = aggregate.maxRet;
+ this._provider = this._createNodesProvider(tree.snapshot, aggregate.type, aggregate.name);
+}
+
+WebInspector.HeapSnapshotConstructorNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, provider.item);
+ },
+
+ _createNodesProvider: function(snapshot, nodeType, nodeName)
+ {
+ return new WebInspector.HeapSnapshotNodesProvider(
+ snapshot,
+ snapshot.allNodes,
+ function (node) {
+ return node.type === nodeType
+ && (nodeName === null || node.name === nodeName);
+ });
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["id", sortAscending, "retainedSize", false],
+ count: ["id", true, "retainedSize", false],
+ shallowSize: ["selfSize", sortAscending, "id", true],
+ retainedSize: ["retainedSize", sortAscending, "id", true]
+ }[sortColumnIdentifier];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _childHashForEntity: function(node)
+ {
+ return node.id;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode.snapshotNodeId;
+ },
+
+ get data()
+ {
+ var data = {object: this._name, count: this._count};
+ var view = this.dataGrid.snapshotView;
+ data["count"] = view.showCountAsPercent ? WebInspector.UIString("%.2f%%", this._countPercent) : this._count;
+ data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize);
+ data["retainedSize"] = "> " + (view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize));
+ return data;
+ },
+
+ get _countPercent()
+ {
+ return this._count / this.dataGrid.snapshot.nodesCount * 100.0;
+ },
+
+ get _retainedSizePercent()
+ {
+ return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0;
+ },
+
+ get _shallowSizePercent()
+ {
+ return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
+ }
+};
+
+WebInspector.HeapSnapshotConstructorNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;
+
+WebInspector.HeapSnapshotIteratorsTuple = function(it1, it2)
+{
+ this._it1 = it1;
+ this._it2 = it2;
+}
+
+WebInspector.HeapSnapshotIteratorsTuple.prototype = {
+ first: function()
+ {
+ this._it1.first();
+ this._it2.first();
+ },
+
+ resetInstancesCount: function()
+ {
+ this._it1.resetInstancesCount();
+ this._it2.resetInstancesCount();
+ },
+
+ sort: function(comparator)
+ {
+ this._it1.sort(comparator);
+ this._it2.sort(comparator);
+ }
+};
+
+WebInspector.HeapSnapshotDiffNode = function(tree, constructor, baseAggregate, aggregate)
+{
+ if (!baseAggregate)
+ baseAggregate = { count: 0, self: 0, maxRet: 0, type:aggregate.type, name:aggregate.name, idxs: [] };
+ if (!aggregate)
+ aggregate = { count: 0, self: 0, maxRet: 0, type:baseAggregate.type, name:baseAggregate.name, idxs: [] };
+ WebInspector.HeapSnapshotGridNode.call(this, tree, true, 50);
+ this._name = constructor;
+ this._calculateDiff(tree.baseSnapshot, tree.snapshot, baseAggregate.idxs, aggregate.idxs);
+ this._provider = this._createNodesProvider(tree.baseSnapshot, tree.snapshot, aggregate.type, aggregate.name);
+}
+
+WebInspector.HeapSnapshotDiffNode.prototype = {
+ _calculateDiff: function(baseSnapshot, snapshot, baseIndexes, currentIndexes)
+ {
+ var i = 0, l = baseIndexes.length;
+ var j = 0, m = currentIndexes.length;
+ this._addedCount = 0;
+ this._removedCount = 0;
+ this._addedSize = 0;
+ this._removedSize = 0;
+ var nodeA = new WebInspector.HeapSnapshotNode(baseSnapshot);
+ var nodeB = new WebInspector.HeapSnapshotNode(snapshot);
+ nodeA.nodeIndex = baseIndexes[i];
+ nodeB.nodeIndex = currentIndexes[j];
+ while (i < l && j < m) {
+ if (nodeA.id < nodeB.id) {
+ this._removedCount++;
+ this._removedSize += nodeA.selfSize;
+ nodeA.nodeIndex = baseIndexes[++i];
+ } else if (nodeA.id > nodeB.id) {
+ this._addedCount++;
+ this._addedSize += nodeB.selfSize;
+ nodeB.nodeIndex = currentIndexes[++j];
+ } else {
+ nodeA.nodeIndex = baseIndexes[++i];
+ nodeB.nodeIndex = currentIndexes[++j];
+ }
+ }
+ while (i < l) {
+ this._removedCount++;
+ this._removedSize += nodeA.selfSize;
+ nodeA.nodeIndex = baseIndexes[++i];
+ }
+ while (j < m) {
+ this._addedCount++;
+ this._addedSize += nodeB.selfSize;
+ nodeB.nodeIndex = currentIndexes[++j];
+ }
+ this._countDelta = this._addedCount - this._removedCount;
+ this._sizeDelta = this._addedSize - this._removedSize;
+ },
+
+ _createChildNode: function(provider)
+ {
+ if (provider === this._provider._it1)
+ return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, provider.item);
+ else
+ return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, provider.item);
+ },
+
+ _createNodesProvider: function(baseSnapshot, snapshot, nodeType, nodeName)
+ {
+ return new WebInspector.HeapSnapshotIteratorsTuple(
+ createProvider(snapshot, baseSnapshot), createProvider(baseSnapshot, snapshot));
+
+ function createProvider(snapshot, otherSnapshot)
+ {
+ return new WebInspector.HeapSnapshotNodesProvider(
+ snapshot,
+ snapshot.allNodes,
+ function (node) {
+ return node.type === nodeType
+ && (nodeName === null || node.name === nodeName)
+ && !(node.id in otherSnapshot.idsMap);
+ });
+ }
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["id", sortAscending, "selfSize", false],
+ addedCount: ["selfSize", sortAscending, "id", true],
+ removedCount: ["selfSize", sortAscending, "id", true],
+ countDelta: ["selfSize", sortAscending, "id", true],
+ addedSize: ["selfSize", sortAscending, "id", true],
+ removedSize: ["selfSize", sortAscending, "id", true],
+ sizeDelta: ["selfSize", sortAscending, "id", true]
+ }[sortColumnIdentifier];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ populateChildren: function(provider, howMany, atIndex)
+ {
+ if (!provider && !howMany) {
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount);
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount);
+ } else if (!howMany) {
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1);
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2);
+ } else
+ WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex);
+ },
+
+ _signForDelta: function(delta)
+ {
+ if (delta === 0)
+ return "";
+ if (delta > 0)
+ return "+";
+ else
+ return "\u2212"; // Math minus sign, same width as plus.
+ },
+
+ get data()
+ {
+ var data = {object: this._name};
+
+ data["addedCount"] = this._addedCount;
+ data["removedCount"] = this._removedCount;
+ data["countDelta"] = WebInspector.UIString("%s%d", this._signForDelta(this._countDelta), Math.abs(this._countDelta));
+ data["addedSize"] = Number.bytesToString(this._addedSize);
+ data["removedSize"] = Number.bytesToString(this._removedSize);
+ data["sizeDelta"] = WebInspector.UIString("%s%s", this._signForDelta(this._sizeDelta), Number.bytesToString(Math.abs(this._sizeDelta)));
+
+ return data;
+ },
+
+ get zeroDiff()
+ {
+ return this._addedCount === 0 && this._removedCount === 0;
+ }
+};
+
+WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;
+
+WebInspector.HeapSnapshotDominatorObjectNode = function(tree, node)
+{
+ var provider = this._createProvider(tree.snapshot, node.nodeIndex);
+ WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 25);
+ this._provider = provider;
+};
+
+WebInspector.HeapSnapshotDominatorObjectNode.prototype = {
+ _createChildNode: function(provider)
+ {
+ return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, provider.item);
+ },
+
+ _createProvider: function(snapshot, nodeIndex)
+ {
+ var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
+ return new WebInspector.HeapSnapshotNodesProvider(
+ snapshot,
+ snapshot.allNodes,
+ function (node) {
+ var dominatorIndex = node.dominatorIndex();
+ return dominatorIndex === nodeIndex
+ && dominatorIndex !== node.nodeIndex
+ && (showHiddenData || !node.isHidden);
+ });
+ },
+
+ _childHashForEntity: function(node)
+ {
+ return node.id;
+ },
+
+ _childHashForNode: function(childNode)
+ {
+ return childNode.snapshotNodeId;
+ },
+
+ comparator: function()
+ {
+ var sortAscending = this.dataGrid.sortOrder === "ascending";
+ var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
+ var sortFields = {
+ object: ["id", sortAscending, "retainedSize", false],
+ shallowSize: ["selfSize", sortAscending, "id", true],
+ retainedSize: ["retainedSize", sortAscending, "id", true]
+ }[sortColumnIdentifier];
+ return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
+ },
+
+ _emptyData: function()
+ {
+ return {};
+ }
+};
+
+WebInspector.HeapSnapshotDominatorObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;
+
+function MixInSnapshotNodeFunctions(sourcePrototype, targetPrototype)
+{
+ targetPrototype._childHashForEntity = sourcePrototype._childHashForEntity;
+ targetPrototype._childHashForNode = sourcePrototype._childHashForNode;
+ targetPrototype.comparator = sourcePrototype.comparator;
+ targetPrototype._createChildNode = sourcePrototype._createChildNode;
+ targetPrototype._createProvider = sourcePrototype._createProvider;
+ targetPrototype.populateChildren = sourcePrototype.populateChildren;
+ targetPrototype._saveChildren = sourcePrototype._saveChildren;
+ targetPrototype.sort = sourcePrototype.sort;
+}
diff --git a/Source/WebCore/inspector/front-end/DetailedHeapshotView.js b/Source/WebCore/inspector/front-end/DetailedHeapshotView.js
index 5291bf2..ffce1dd 100644
--- a/Source/WebCore/inspector/front-end/DetailedHeapshotView.js
+++ b/Source/WebCore/inspector/front-end/DetailedHeapshotView.js
@@ -28,30 +28,879 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+WebInspector.HeapSnapshotContainmentDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true, sort: "ascending" },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sortable: true }
+ };
+ WebInspector.DataGrid.call(this, columns);
+ this.addEventListener("sorting changed", this.sort, this);
+ this._defaultPopulateCount = 100;
+}
+
+WebInspector.HeapSnapshotContainmentDataGrid.prototype = {
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ this.snapshotNodeIndex = this.snapshot._rootNodeIndex;
+ this._provider = this._createProvider(snapshot, snapshot.rootNode.rawEdges);
+ this.sort();
+ }
+};
+
+MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotObjectNode.prototype, WebInspector.HeapSnapshotContainmentDataGrid.prototype);
+WebInspector.HeapSnapshotContainmentDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
+
+WebInspector.HeapSnapshotSortableDataGrid = function(columns)
+{
+ WebInspector.DataGrid.call(this, columns);
+ this.addEventListener("sorting changed", this.sortingChanged, this);
+}
+
+WebInspector.HeapSnapshotSortableDataGrid.prototype = {
+ sortingChanged: function()
+ {
+ var sortAscending = this.sortOrder === "ascending";
+ var sortColumnIdentifier = this.sortColumnIdentifier;
+ var sortFields = this._sortFields(sortColumnIdentifier, sortAscending);
+
+ function SortByTwoFields(nodeA, nodeB)
+ {
+ var field1 = nodeA[sortFields[0]];
+ var field2 = nodeB[sortFields[0]];
+ var result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
+ if (!sortFields[1])
+ result = -result;
+ if (result !== 0)
+ return result;
+ field1 = nodeA[sortFields[2]];
+ field2 = nodeB[sortFields[2]];
+ result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
+ if (!sortFields[3])
+ result = -result;
+ return result;
+ }
+
+ this._performSorting(SortByTwoFields);
+ },
+
+ _performSorting: function(sortFunction)
+ {
+ var children = this.children;
+ this.removeChildren();
+ children.sort(sortFunction);
+ for (var i = 0, l = children.length; i < l; ++i) {
+ var child = children[i];
+ this.appendChild(child);
+ if (child.expanded)
+ child.sort();
+ }
+ }
+};
+
+WebInspector.HeapSnapshotSortableDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
+
+WebInspector.HeapSnapshotConstructorsDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
+ count: { title: WebInspector.UIString("#"), width: "45px", sortable: true },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true }
+ };
+ WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+}
+
+WebInspector.HeapSnapshotConstructorsDataGrid.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ object: ["_name", sortAscending, "_count", false],
+ count: ["_count", sortAscending, "_name", true],
+ shallowSize: ["_shallowSize", sortAscending, "_name", true],
+ retainedSize: ["_retainedSize", sortAscending, "_name", true]
+ }[sortColumn];
+ },
+
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ this.populateChildren();
+ this.sortingChanged();
+ },
+
+ populateChildren: function()
+ {
+ var aggregates = this.snapshot.aggregates();
+ for (var constructor in aggregates)
+ this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor]));
+ }
+};
+
+WebInspector.HeapSnapshotConstructorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;
+
+WebInspector.HeapSnapshotDiffDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
+ // \xb1 is a "plus-minus" sign.
+ addedCount: { title: WebInspector.UIString("# New"), width: "72px", sortable: true, sort: "descending" },
+ removedCount: { title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true },
+ // \u0394 is a Greek delta letter.
+ countDelta: { title: "\u0394", width: "40px", sortable: true },
+ addedSize: { title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true },
+ removedSize: { title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true },
+ sizeDelta: { title: "\u0394", width: "72px", sortable: true }
+ };
+ WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+}
+
+WebInspector.HeapSnapshotDiffDataGrid.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ object: ["_name", sortAscending, "_count", false],
+ addedCount: ["_addedCount", sortAscending, "_name", true],
+ removedCount: ["_removedCount", sortAscending, "_name", true],
+ countDelta: ["_countDelta", sortAscending, "_name", true],
+ addedSize: ["_addedSize", sortAscending, "_name", true],
+ removedSize: ["_removedSize", sortAscending, "_name", true],
+ sizeDelta: ["_sizeDelta", sortAscending, "_name", true]
+ }[sortColumn];
+ },
+
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ },
+
+ setBaseDataSource: function(baseSnapshot)
+ {
+ this.baseSnapshot = baseSnapshot;
+ this.removeChildren();
+ if (this.baseSnapshot !== this.snapshot) {
+ this.populateChildren();
+ this.sortingChanged();
+ }
+ },
+
+ populateChildren: function()
+ {
+ var baseClasses = this.baseSnapshot.aggregates(true);
+ var classes = this.snapshot.aggregates(true);
+ for (var clss in baseClasses) {
+ var node = new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss]);
+ if (!node.zeroDiff)
+ this.appendChild(node);
+ }
+ for (clss in classes) {
+ if (!(clss in baseClasses)) {
+ var node = new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss]);
+ if (!node.zeroDiff)
+ this.appendChild(node);
+ }
+ }
+ }
+};
+
+WebInspector.HeapSnapshotDiffDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;
+
+WebInspector.HeapSnapshotDominatorsDataGrid = function()
+{
+ var columns = {
+ object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
+ shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
+ retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true }
+ };
+ WebInspector.DataGrid.call(this, columns);
+ this.addEventListener("sorting changed", this.sort, this);
+ this._defaultPopulateCount = 25;
+}
+
+WebInspector.HeapSnapshotDominatorsDataGrid.prototype = {
+ setDataSource: function(snapshotView, snapshot)
+ {
+ this.snapshotView = snapshotView;
+ this.snapshot = snapshot;
+ this.snapshotNodeIndex = this.snapshot._rootNodeIndex;
+ this._provider = this._createProvider(snapshot, this.snapshotNodeIndex);
+ this.sort();
+ }
+};
+
+MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotDominatorObjectNode.prototype, WebInspector.HeapSnapshotDominatorsDataGrid.prototype);
+WebInspector.HeapSnapshotDominatorsDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;
+
+WebInspector.HeapSnapshotRetainingPathsList = function()
+{
+ var columns = {
+ path: { title: WebInspector.UIString("Retaining path"), sortable: true },
+ len: { title: WebInspector.UIString("Length"), width: "90px", sortable: true, sort: "ascending" }
+ };
+ WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
+}
+
+WebInspector.HeapSnapshotRetainingPathsList.prototype = {
+ _sortFields: function(sortColumn, sortAscending)
+ {
+ return {
+ path: ["path", sortAscending, "len", true],
+ len: ["len", sortAscending, "path", true]
+ }[sortColumn];
+ },
+
+ setDataSource: function(snapshotView, snapshot, nodeIndex, prefix)
+ {
+ this.snapshotView = snapshotView;
+ this._prefix = prefix;
+
+ if (this.pathFinder)
+ this.searchCancelled();
+
+ this.pathFinder = new WebInspector.HeapSnapshotPathFinder(snapshot, nodeIndex);
+
+ this.removeChildren();
+
+ this._counter = 0;
+ this.showNext(10);
+ },
+
+ showNext: function(pathsCount)
+ {
+ WebInspector.PleaseWaitMessage.prototype.show(this.element, this.searchCancelled.bind(this, pathsCount));
+ window.setTimeout(startSearching.bind(this), 500);
+
+ function startSearching()
+ {
+ if (this._cancel !== this.pathFinder) {
+ if (this._counter < pathsCount) {
+ var result = this.pathFinder.findNext();
+ if (result === null) {
+ WebInspector.PleaseWaitMessage.prototype.hide();
+ if (!this.children.length)
+ this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("This object is either only accessible via hidden properties, or current path search depth isn't enough."), len:""}, false));
+ return;
+ } else if (result !== false) {
+ if (this._prefix)
+ result.path = this._prefix + result.path;
+ this.appendChild(new WebInspector.DataGridNode(result, false));
+ ++this._counter;
+ }
+ window.setTimeout(startSearching.bind(this), 0);
+ return;
+ } else
+ this.searchCancelled.call(this, pathsCount);
+ }
+ this._cancel = false;
+ }
+ },
+
+ searchCancelled: function(pathsCount)
+ {
+ WebInspector.PleaseWaitMessage.prototype.hide();
+ this._counter = 0;
+ this._cancel = this.pathFinder;
+ if (pathsCount) {
+ this.appendChild(new WebInspector.ShowMoreDataGridNode(this.showNext.bind(this), pathsCount));
+ this.sortingChanged();
+ }
+ },
+
+ _performSorting: function(sortFunction)
+ {
+ function DataExtractorWrapper(nodeA, nodeB)
+ {
+ return sortFunction(nodeA.data, nodeB.data);
+ }
+
+ this.sortNodes(DataExtractorWrapper);
+ }
+};
+
+WebInspector.HeapSnapshotRetainingPathsList.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;
+
WebInspector.DetailedHeapshotView = function(parent, profile)
{
WebInspector.View.call(this);
- this.element.addStyleClass("heap-snapshot-view");
+ this.element.addStyleClass("detailed-heapshot-view");
this.parent = parent;
- this.profile = profile;
+ this.parent.addEventListener("profile added", this._updateBaseOptions, this);
+
+ this.showCountAsPercent = false;
+ this.showShallowSizeAsPercent = false;
+ this.showRetainedSizeAsPercent = false;
+
+ this.containmentView = new WebInspector.View();
+ this.containmentView.element.addStyleClass("view");
+ this.containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid();
+ this.containmentDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.containmentDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.containmentView.element.appendChild(this.containmentDataGrid.element);
+ this.element.appendChild(this.containmentView.element);
+
+ this.constructorsView = new WebInspector.View();
+ this.constructorsView.element.addStyleClass("view");
+ this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid();
+ this.constructorsDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.constructorsDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.constructorsView.element.appendChild(this.constructorsDataGrid.element);
+ this.element.appendChild(this.constructorsView.element);
+
+ this.diffView = new WebInspector.View();
+ this.diffView.element.addStyleClass("view");
+ this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid();
+ this.diffDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.diffDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.diffView.element.appendChild(this.diffDataGrid.element);
+ this.element.appendChild(this.diffView.element);
+
+ this.dominatorView = new WebInspector.View();
+ this.dominatorView.element.addStyleClass("view");
+ this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid();
+ this.dominatorDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
+ this.dominatorDataGrid.element.addEventListener("dblclick", this._dblClickInContainmentGrid.bind(this), true);
+ this.dominatorView.element.appendChild(this.dominatorDataGrid.element);
+ this.element.appendChild(this.dominatorView.element);
+
+ var retainmentView = new WebInspector.View();
+ retainmentView.element.addStyleClass("view retaining-paths-view");
+ var retainingPathsTitleDiv = document.createElement("div");
+ retainingPathsTitleDiv.className = "title";
+ var retainingPathsTitle = document.createElement("span");
+ retainingPathsTitle.textContent = WebInspector.UIString("Retaining paths of the selected object");
+ retainingPathsTitleDiv.appendChild(retainingPathsTitle);
+ retainmentView.element.appendChild(retainingPathsTitleDiv);
+ this.retainmentDataGrid = new WebInspector.HeapSnapshotRetainingPathsList();
+ retainmentView.element.appendChild(this.retainmentDataGrid.element);
+ retainmentView.visible = true;
+ this.element.appendChild(retainmentView.element);
+
+ this.dataGrid = this.constructorsDataGrid;
+ this.currentView = this.constructorsView;
+
+ this.viewSelectElement = document.createElement("select");
+ this.viewSelectElement.className = "status-bar-item";
+ this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);
+
+ var classesViewOption = document.createElement("option");
+ classesViewOption.label = WebInspector.UIString("Summary");
+ var diffViewOption = document.createElement("option");
+ diffViewOption.label = WebInspector.UIString("Comparison");
+ var containmentViewOption = document.createElement("option");
+ containmentViewOption.label = WebInspector.UIString("Containment");
+ var dominatorsViewOption = document.createElement("option");
+ dominatorsViewOption.label = WebInspector.UIString("Dominators");
+ this.viewSelectElement.appendChild(classesViewOption);
+ this.viewSelectElement.appendChild(diffViewOption);
+ this.viewSelectElement.appendChild(containmentViewOption);
+ this.viewSelectElement.appendChild(dominatorsViewOption);
+ this.views = ["Summary", "Comparison", "Containment", "Dominators"];
+ this.views.current = 0;
+
+ this._profileUid = profile.uid;
+
+ this.baseSelectElement = document.createElement("select");
+ this.baseSelectElement.className = "status-bar-item hidden";
+ this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
+ this._updateBaseOptions();
+
+ this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
+ this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
+ this.helpButton = new WebInspector.StatusBarButton("", "heapshot-help-status-bar-item status-bar-item");
+ this.helpButton.addEventListener("click", this._helpClicked.bind(this), false);
+
+ this._loadProfile(this._profileUid, profileCallback.bind(this));
+
+ function profileCallback(profile)
+ {
+ var list = this._profiles();
+ var profileIndex;
+ for (var i = 0; i < list.length; ++i)
+ if (list[i].uid === profile.uid) {
+ profileIndex = i;
+ break;
+ }
+ if (profileIndex > 0)
+ this.baseSelectElement.selectedIndex = profileIndex - 1;
+ else
+ this.baseSelectElement.selectedIndex = profileIndex;
+ this.dataGrid.setDataSource(this, this.profileWrapper);
+ this._updatePercentButton();
+ }
}
WebInspector.DetailedHeapshotView.prototype = {
+ dispose: function()
+ {
+ if (this._profileWrapper)
+ this._profileWrapper.dispose();
+ if (this._baseProfileWrapper)
+ this._baseProfileWrapper.dispose();
+ },
+
+ get statusBarItems()
+ {
+ return [this.viewSelectElement, this.baseSelectElement, this.percentButton.element, this.helpButton.element];
+ },
+
get profile()
{
- return this._profile;
+ return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._profileUid);
},
- set profile(profile)
+ get profileWrapper()
{
- this._profile = profile;
+ if (!this._profileWrapper)
+ this._profileWrapper = new WebInspector.HeapSnapshot(this.profile);
+ return this._profileWrapper;
+ },
+
+ get baseProfile()
+ {
+ return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._baseProfileUid);
+ },
+
+ get baseProfileWrapper()
+ {
+ if (!this._baseProfileWrapper) {
+ if (this.baseProfile !== this.profile)
+ this._baseProfileWrapper = new WebInspector.HeapSnapshot(this.baseProfile);
+ else
+ this._baseProfileWrapper = this.profileWrapper;
+ }
+ return this._baseProfileWrapper;
+ },
+
+ show: function(parentElement)
+ {
+ WebInspector.View.prototype.show.call(this, parentElement);
+ if (!this.profile._loaded)
+ this._loadProfile(this._profileUid, profileCallback1.bind(this));
+ else
+ profileCallback1.call(this, this.profile);
+
+ function profileCallback1(profile) {
+ this.profileWrapper.restore(profile);
+ if (this.baseProfile && !this.baseProfile._loaded)
+ this._loadProfile(this._baseProfileUid, profileCallback2.bind(this));
+ else
+ profileCallback2.call(this, this.baseProfile);
+ }
+
+ function profileCallback2(profile) {
+ if (profile)
+ this.baseProfileWrapper.restore(profile);
+ this.currentView.show();
+ this.dataGrid.updateWidths();
+ }
+ },
+
+ hide: function()
+ {
+ WebInspector.View.prototype.hide.call(this);
+ this._currentSearchResultIndex = -1;
+ },
+
+ resize: function()
+ {
+ if (this.dataGrid)
+ this.dataGrid.updateWidths();
+ },
+
+ refreshShowAsPercents: function()
+ {
+ this._updatePercentButton();
+ this.refreshVisibleData();
+ },
+
+ searchCanceled: function()
+ {
+ if (this._searchResults) {
+ for (var i = 0; i < this._searchResults.length; ++i) {
+ var node = this._searchResults[i].node;
+ delete node._searchMatched;
+ node.refresh();
+ }
+ }
+
+ delete this._searchFinishedCallback;
+ this._currentSearchResultIndex = -1;
+ this._searchResults = [];
+ },
+
+ performSearch: function(query, finishedCallback)
+ {
+ // Call searchCanceled since it will reset everything we need before doing a new search.
+ this.searchCanceled();
+
+ query = query.trim();
+
+ if (!query.length)
+ return;
+ if (this.currentView !== this.constructorsView && this.currentView !== this.diffView)
+ return;
+
+ this._searchFinishedCallback = finishedCallback;
+
+ function matchesByName(gridNode) {
+ return ("name" in gridNode) && gridNode.name.hasSubstring(query, true);
+ }
+
+ function matchesById(gridNode) {
+ return ("snapshotNodeId" in gridNode) && gridNode.snapshotNodeId === query;
+ }
+
+ var matchPredicate;
+ if (query.charAt(0) !== "@")
+ matchPredicate = matchesByName;
+ else {
+ query = parseInt(query.substring(1), 10);
+ matchPredicate = matchesById;
+ }
+
+ function matchesQuery(gridNode)
+ {
+ delete gridNode._searchMatched;
+ if (matchPredicate(gridNode)) {
+ gridNode._searchMatched = true;
+ gridNode.refresh();
+ return true;
+ }
+ return false;
+ }
+
+ var current = this.dataGrid.children[0];
+ var depth = 0;
+ var info = {};
+
+ // Restrict to type nodes and instances.
+ const maxDepth = 1;
+
+ while (current) {
+ if (matchesQuery(current))
+ this._searchResults.push({ node: current });
+ current = current.traverseNextNode(false, null, (depth >= maxDepth), info);
+ depth += info.depthChange;
+ }
+
+ finishedCallback(this, this._searchResults.length);
+ },
+
+ jumpToFirstSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToLastSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToNextSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (++this._currentSearchResultIndex >= this._searchResults.length)
+ this._currentSearchResultIndex = 0;
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ jumpToPreviousSearchResult: function()
+ {
+ if (!this._searchResults || !this._searchResults.length)
+ return;
+ if (--this._currentSearchResultIndex < 0)
+ this._currentSearchResultIndex = (this._searchResults.length - 1);
+ this._jumpToSearchResult(this._currentSearchResultIndex);
+ },
+
+ showingFirstSearchResult: function()
+ {
+ return (this._currentSearchResultIndex === 0);
+ },
+
+ showingLastSearchResult: function()
+ {
+ return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
+ },
+
+ _jumpToSearchResult: function(index)
+ {
+ var searchResult = this._searchResults[index];
+ if (!searchResult)
+ return;
+
+ var node = searchResult.node;
+ node.reveal();
+ node.select();
+ },
+
+ refreshVisibleData: function()
+ {
+ var child = this.dataGrid.children[0];
+ while (child) {
+ child.refresh();
+ child = child.traverseNextNode(false, null, true);
+ }
+ },
+
+ _changeBase: function()
+ {
+ if (this._baseProfileUid === this._profiles()[this.baseSelectElement.selectedIndex].uid)
+ return;
+
+ this._baseProfileUid = this._profiles()[this.baseSelectElement.selectedIndex].uid;
+ this._loadProfile(this._baseProfileUid, baseProfileLoaded.bind(this));
+
+ function baseProfileLoaded(profile)
+ {
+ delete this._baseProfileWrapper;
+ this.baseProfile._lastShown = Date.now();
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.currentView.element, showDiffData.bind(this));
+ }
+
+ function showDiffData()
+ {
+ this.diffDataGrid.setBaseDataSource(this.baseProfileWrapper);
+ }
+
+ if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+ return;
+
+ // The current search needs to be performed again. First negate out previous match
+ // count by calling the search finished callback with a negative number of matches.
+ // Then perform the search again with the same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ },
+
+ _profiles: function()
+ {
+ return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
+ },
+
+ _loadProfile: function(profileUid, callback)
+ {
+ WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback);
+ },
+
+ isDetailedSnapshot: function(snapshot)
+ {
+ var s = new WebInspector.HeapSnapshot(snapshot);
+ for (var iter = s.rootNode.edges; iter.hasNext(); iter.next())
+ if (iter.edge.node.name === "(GC roots)")
+ return true;
+ return false;
+ },
+
+ processLoadedSnapshot: function(profile, snapshot)
+ {
+ profile.nodes = snapshot.nodes;
+ profile.strings = snapshot.strings;
+ var s = new WebInspector.HeapSnapshot(profile);
+ profile.sideBarElement.subtitle = Number.bytesToString(s.totalSize);
+ },
+
+ _dblClickInContainmentGrid: function(event)
+ {
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || (!cell.hasStyleClass("retainedSize-column")))
+ return;
+ var nodeItem = event.target.enclosingNodeOrSelfWithNodeName("tr")._dataGridNode;
+ ProfilerAgent.getExactHeapSnapshotNodeRetainedSize(this._profileUid, nodeItem.snapshotNodeId, setExactRetainedSize);
+
+ function setExactRetainedSize(exactSize) {
+ if (exactSize && exactSize != -1)
+ nodeItem.exactRetainedSize = exactSize;
+ }
+ },
+
+ _mouseClickInContainmentGrid: function(event)
+ {
+ var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
+ if (!cell || !(cell.hasStyleClass("object-column") || cell.hasStyleClass("shallowSize-column")))
+ return;
+ var row = event.target.enclosingNodeOrSelfWithNodeName("tr");
+ if (!row)
+ return;
+ var nodeItem = row._dataGridNode;
+ if (!nodeItem || nodeItem.isEventWithinDisclosureTriangle(event) || !nodeItem.snapshotNodeIndex)
+ return;
+
+ this.retainmentDataGrid.setDataSource(this, nodeItem.isDeletedNode ? nodeItem.dataGrid.baseSnapshot : nodeItem.dataGrid.snapshot, nodeItem.snapshotNodeIndex, nodeItem.isDeletedNode ? this.baseSelectElement.childNodes[this.baseSelectElement.selectedIndex].label + " | " : "");
+ },
+
+ _changeView: function(event)
+ {
+ if (!event || !this._profileUid)
+ return;
+ if (event.target.selectedIndex === this.views.current)
+ return;
+
+ this.views.current = event.target.selectedIndex;
+ this.currentView.hide();
+ if (this.views[this.views.current] === "Containment") {
+ this.currentView = this.containmentView;
+ this.dataGrid = this.containmentDataGrid;
+ } else if (this.views[this.views.current] === "Summary") {
+ this.currentView = this.constructorsView;
+ this.dataGrid = this.constructorsDataGrid;
+ } else if (this.views[this.views.current] === "Comparison") {
+ this.currentView = this.diffView;
+ this.dataGrid = this.diffDataGrid;
+ } else if (this.views[this.views.current] === "Dominators") {
+ this.currentView = this.dominatorView;
+ this.dataGrid = this.dominatorDataGrid;
+ }
+ this.currentView.show();
+ this.refreshVisibleData();
+ if (this.currentView === this.diffView) {
+ this.baseSelectElement.removeStyleClass("hidden");
+ if (!this.dataGrid.snapshotView) {
+ this.dataGrid.setDataSource(this, this.profileWrapper);
+ this._changeBase();
+ }
+ } else {
+ this.baseSelectElement.addStyleClass("hidden");
+ if (!this.dataGrid.snapshotView)
+ WebInspector.PleaseWaitMessage.prototype.startAction(this.currentView.element, loadData.bind(this));
+ }
+
+ function loadData()
+ {
+ this.dataGrid.setDataSource(this, this.profileWrapper);
+ }
+
+ if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
+ return;
+
+ // The current search needs to be performed again. First negate out previous match
+ // count by calling the search finished callback with a negative number of matches.
+ // Then perform the search again the with same query and callback.
+ this._searchFinishedCallback(this, -this._searchResults.length);
+ this.performSearch(this.currentQuery, this._searchFinishedCallback);
+ },
+
+ get _isShowingAsPercent()
+ {
+ return this.showCountAsPercent && this.showShallowSizeAsPercent && this.showRetainedSizeAsPercent;
+ },
+
+ _percentClicked: function(event)
+ {
+ var currentState = this._isShowingAsPercent;
+ this.showCountAsPercent = !currentState;
+ this.showShallowSizeAsPercent = !currentState;
+ this.showRetainedSizeAsPercent = !currentState;
+ this.refreshShowAsPercents();
+ },
+
+ _helpClicked: function(event)
+ {
+ if (!this.helpPopover) {
+ var refTypes = ["a:", "console-formatted-name", WebInspector.UIString("property"),
+ "0:", "console-formatted-name", WebInspector.UIString("element"),
+ "a:", "console-formatted-number", WebInspector.UIString("context var"),
+ "a:", "console-formatted-null", WebInspector.UIString("system prop")];
+ var objTypes = [" a ", "console-formatted-object", "Object",
+ "\"a\"", "console-formatted-string", "String",
+ "/a/", "console-formatted-string", "RegExp",
+ "a()", "console-formatted-function", "Function",
+ "a[]", "console-formatted-object", "Array",
+ "num", "console-formatted-number", "Number",
+ " a ", "console-formatted-null", "System"];
+
+ var contentElement = document.createElement("table");
+ contentElement.className = "heapshot-help";
+ var headerRow = document.createElement("tr");
+ var propsHeader = document.createElement("th");
+ propsHeader.textContent = WebInspector.UIString("Property types:");
+ headerRow.appendChild(propsHeader);
+ var objsHeader = document.createElement("th");
+ objsHeader.textContent = WebInspector.UIString("Object types:");
+ headerRow.appendChild(objsHeader);
+ contentElement.appendChild(headerRow);
+ var len = Math.max(refTypes.length, objTypes.length);
+ for (var i = 0; i < len; i += 3) {
+ var row = document.createElement("tr");
+ var refCell = document.createElement("td");
+ if (refTypes[i])
+ appendHelp(refTypes, i, refCell);
+ row.appendChild(refCell);
+ var objCell = document.createElement("td");
+ if (objTypes[i])
+ appendHelp(objTypes, i, objCell);
+ row.appendChild(objCell);
+ contentElement.appendChild(row);
+ }
+ this.helpPopover = new WebInspector.Popover(contentElement);
+
+ function appendHelp(help, index, cell)
+ {
+ var div = document.createElement("div");
+ div.className = "source-code event-properties";
+ var name = document.createElement("span");
+ name.textContent = help[index];
+ name.className = help[index + 1];
+ div.appendChild(name);
+ var desc = document.createElement("span");
+ desc.textContent = " " + help[index + 2];
+ div.appendChild(desc);
+ cell.appendChild(div);
+ }
+ }
+ if (this.helpPopover.visible)
+ this.helpPopover.hide();
+ else
+ this.helpPopover.show(this.helpButton.element);
+ },
+
+ _updateBaseOptions: function()
+ {
+ var list = this._profiles();
+ // We're assuming that snapshots can only be added.
+ if (this.baseSelectElement.length === list.length)
+ return;
+
+ for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) {
+ var baseOption = document.createElement("option");
+ var title = list[i].title;
+ if (!title.indexOf(UserInitiatedProfileName))
+ title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
+ baseOption.label = title;
+ this.baseSelectElement.appendChild(baseOption);
+ }
+ },
+
+ _updatePercentButton: function()
+ {
+ if (this._isShowingAsPercent) {
+ this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
+ this.percentButton.toggled = true;
+ } else {
+ this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
+ this.percentButton.toggled = false;
+ }
}
};
WebInspector.DetailedHeapshotView.prototype.__proto__ = WebInspector.View.prototype;
+WebInspector.DetailedHeapshotView.prototype.showHiddenData = true;
+
WebInspector.DetailedHeapshotProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
diff --git a/Source/WebCore/inspector/front-end/ElementsPanel.js b/Source/WebCore/inspector/front-end/ElementsPanel.js
index e6af93c..246abe8 100644
--- a/Source/WebCore/inspector/front-end/ElementsPanel.js
+++ b/Source/WebCore/inspector/front-end/ElementsPanel.js
@@ -57,7 +57,7 @@ WebInspector.ElementsPanel = function()
this.panel.updateEventListeners();
if (this._focusedDOMNode) {
- InspectorBackend.addInspectedNode(this._focusedDOMNode.id);
+ DOMAgent.addInspectedNode(this._focusedDOMNode.id);
WebInspector.extensionServer.notifyObjectSelected(this.panel.name);
}
};
@@ -141,6 +141,9 @@ WebInspector.ElementsPanel.prototype = {
this.treeOutline.updateSelection();
if (this.recentlyModifiedNodes.length)
this.updateModifiedNodes();
+
+ if (!this.rootDOMNode)
+ WebInspector.domAgent.requestDocument();
},
hide: function()
@@ -211,7 +214,7 @@ WebInspector.ElementsPanel.prototype = {
}
if (this._selectedPathOnReset)
- InspectorBackend.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
+ WebInspector.domAgent.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
else
selectNode.call(this);
delete this._selectedPathOnReset;
@@ -222,11 +225,11 @@ WebInspector.ElementsPanel.prototype = {
delete this._searchQuery;
this._hideSearchHighlights();
- WebInspector.updateSearchMatchesCount(0, this);
+ WebInspector.searchController.updateSearchMatchesCount(0, this);
- this._currentSearchResultIndex = 0;
+ delete this._currentSearchResultIndex;
this._searchResults = [];
- InspectorBackend.searchCanceled();
+ DOMAgent.searchCanceled();
},
performSearch: function(query)
@@ -242,7 +245,7 @@ WebInspector.ElementsPanel.prototype = {
this._matchesCountUpdateTimeout = null;
this._searchQuery = query;
- InspectorBackend.performSearch(whitespaceTrimmedQuery, false);
+ DOMAgent.performSearch(whitespaceTrimmedQuery, false);
},
populateHrefContextMenu: function(contextMenu, event, anchorElement)
@@ -264,14 +267,14 @@ WebInspector.ElementsPanel.prototype = {
switchToAndFocus: function(node)
{
// Reset search restore.
- WebInspector.cancelSearch();
+ WebInspector.searchController.cancelSearch();
WebInspector.currentPanel = this;
this.focusedDOMNode = node;
},
_updateMatchesCount: function()
{
- WebInspector.updateSearchMatchesCount(this._searchResults.length, this);
+ WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this);
this._matchesCountUpdateTimeout = null;
this._updatedMatchCountOnce = true;
},
@@ -291,6 +294,7 @@ WebInspector.ElementsPanel.prototype = {
if (!nodeIds.length)
return;
+ var oldSearchResultIndex = this._currentSearchResultIndex;
for (var i = 0; i < nodeIds.length; ++i) {
var nodeId = nodeIds[i];
var node = WebInspector.domAgent.nodeForId(nodeId);
@@ -300,7 +304,10 @@ WebInspector.ElementsPanel.prototype = {
this._currentSearchResultIndex = 0;
this._searchResults.push(node);
}
- this._highlightCurrentSearchResult();
+
+ // Avoid invocations of highlighting for every chunk of nodeIds.
+ if (oldSearchResultIndex !== this._currentSearchResultIndex)
+ this._highlightCurrentSearchResult();
this._updateMatchesCountSoon();
},
@@ -375,6 +382,9 @@ WebInspector.ElementsPanel.prototype = {
this.recentlyModifiedNodes.push({node: event.target, updated: true});
if (this.visible)
this._updateModifiedNodesSoon();
+
+ if (!this.sidebarPanes.styles.isModifyingStyle && event.target === this.focusedDOMNode)
+ this._styleSheetChanged();
},
_characterDataModified: function(event)
@@ -1023,7 +1033,7 @@ WebInspector.ElementsPanel.prototype = {
return;
event.clipboardData.clearData();
event.preventDefault();
- InspectorBackend.copyNode(this.focusedDOMNode.id);
+ DOMAgent.copyNode(this.focusedDOMNode.id);
},
rightSidebarResizerDragStart: function(event)
@@ -1070,7 +1080,7 @@ WebInspector.ElementsPanel.prototype = {
setSearchingForNode: function(enabled)
{
- InspectorBackend.setSearchingForNode(enabled, this._setSearchingForNode.bind(this));
+ InspectorAgent.setSearchingForNode(enabled, this._setSearchingForNode.bind(this));
},
toggleSearchingForNode: function()
diff --git a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js
index 56c3e75..7b5ff2f 100644
--- a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js
+++ b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js
@@ -329,8 +329,11 @@ WebInspector.ElementsTreeElement.prototype = {
if (this._searchQuery === searchQuery)
return;
+ if (searchQuery)
+ delete this._searchHighlightedHTML; // A new search query (not clear-the-current-highlighting).
+
this._searchQuery = searchQuery;
- this.updateTitle();
+ this.updateTitle(true);
},
get hovered()
@@ -400,17 +403,35 @@ WebInspector.ElementsTreeElement.prototype = {
if (!node.nodeName || node.nodeName.toLowerCase() !== "img")
return;
- function setTooltip(properties)
+ function setTooltip(result)
{
- if (!properties)
+ if (!result || result.type !== "string")
return;
- if (properties.offsetHeight === properties.naturalHeight && properties.offsetWidth === properties.naturalWidth)
- this.tooltip = WebInspector.UIString("%d × %d pixels", properties.offsetWidth, properties.offsetHeight);
- else
- this.tooltip = WebInspector.UIString("%d × %d pixels (Natural: %d × %d pixels)", properties.offsetWidth, properties.offsetHeight, properties.naturalWidth, properties.naturalHeight);
+ try {
+ var properties = JSON.parse(result.description);
+ var offsetWidth = properties[0];
+ var offsetHeight = properties[1];
+ var naturalWidth = properties[2];
+ var naturalHeight = properties[3];
+ if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
+ this.tooltip = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight);
+ else
+ this.tooltip = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+
+ function resolvedNode(objectPayload)
+ {
+ if (!objectPayload)
+ return;
+
+ var object = WebInspector.RemoteObject.fromPayload(objectPayload);
+ object.evaluate("return '[' + this.offsetWidth + ',' + this.offsetHeight + ',' + this.naturalWidth + ',' + this.naturalHeight + ']'", setTooltip.bind(this));
}
- InspectorBackend.getNodeProperties(node.id, ["naturalHeight", "naturalWidth", "offsetHeight", "offsetWidth"], setTooltip.bind(this));
+ DOMAgent.resolveNode(node.id, "", resolvedNode.bind(this));
},
updateSelection: function()
@@ -1154,7 +1175,7 @@ WebInspector.ElementsTreeElement.prototype = {
moveToNextAttributeIfNeeded.call(newTreeItem);
}
- InspectorBackend.changeTagName(this.representedObject.id, newText, changeTagNameCallback);
+ DOMAgent.changeTagName(this.representedObject.id, newText, changeTagNameCallback);
},
_textNodeEditingCommitted: function(element, newText)
@@ -1198,14 +1219,20 @@ WebInspector.ElementsTreeElement.prototype = {
return (tags.length === 1 ? null : tags[tags.length-1]);
},
- updateTitle: function()
+ updateTitle: function(onlySearchQueryChanged)
{
// If we are editing, return early to prevent canceling the edit.
// After editing is committed updateTitle will be called.
if (this._editing)
return;
- this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
+ if (onlySearchQueryChanged && this._normalHTML)
+ this.titleHTML = this._normalHTML;
+ else {
+ delete this._normalHTML;
+ this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
+ }
+
delete this.selectionElement;
this.updateSelection();
this._preventFollowingLinksOnDoubleClick();
@@ -1381,7 +1408,7 @@ WebInspector.ElementsTreeElement.prototype = {
parentElement.adjustCollapsedRange(true);
}
- InspectorBackend.removeNode(this.representedObject.id, removeNodeCallback);
+ DOMAgent.removeNode(this.representedObject.id, removeNodeCallback);
},
_editAsHTML: function()
@@ -1408,32 +1435,41 @@ WebInspector.ElementsTreeElement.prototype = {
function commitChange(value)
{
- InspectorBackend.setOuterHTML(node.id, value, selectNode);
+ DOMAgent.setOuterHTML(node.id, value, selectNode);
}
- InspectorBackend.getOuterHTML(node.id, this._startEditingAsHTML.bind(this, commitChange));
+ DOMAgent.getOuterHTML(node.id, this._startEditingAsHTML.bind(this, commitChange));
},
_copyHTML: function()
{
- InspectorBackend.copyNode(this.representedObject.id);
+ DOMAgent.copyNode(this.representedObject.id);
},
_highlightSearchResults: function()
{
if (!this._searchQuery)
return;
+ if (this._searchHighlightedHTML) {
+ this.listItemElement.innerHTML = this._searchHighlightedHTML;
+ return;
+ }
+
+ if (!this._normalHTML)
+ this._normalHTML = this.titleHTML;
+
var text = this.listItemElement.textContent;
- var regexObject = createSearchRegex(this._searchQuery);
+ var regexObject = createSearchRegex(this._searchQuery, "g");
var offset = 0;
var match = regexObject.exec(text);
+ var matchRanges = [];
while (match) {
- highlightSearchResult(this.listItemElement, offset + match.index, match[0].length);
- offset += match.index + 1;
- text = text.substring(match.index + 1);
+ matchRanges.push({ offset: match.index, length: match[0].length });
match = regexObject.exec(text);
}
+ highlightSearchResults(this.listItemElement, matchRanges);
+ this._searchHighlightedHTML = this.listItemElement.innerHTML;
}
}
diff --git a/Source/WebCore/inspector/front-end/ExtensionPanel.js b/Source/WebCore/inspector/front-end/ExtensionPanel.js
index 144d55d..142b8c1 100644
--- a/Source/WebCore/inspector/front-end/ExtensionPanel.js
+++ b/Source/WebCore/inspector/front-end/ExtensionPanel.js
@@ -95,7 +95,7 @@ WebInspector.ExtensionWatchSidebarPane.prototype = {
setExpression: function(expression, title)
{
- InspectorBackend.evaluate(expression, "extension-watch", false, this._onEvaluate.bind(this, title));
+ RuntimeAgent.evaluate(expression, "extension-watch", false, this._onEvaluate.bind(this, title));
},
_onEvaluate: function(title, result)
diff --git a/Source/WebCore/inspector/front-end/ExtensionServer.js b/Source/WebCore/inspector/front-end/ExtensionServer.js
index 7d33b73..f9af7dc 100644
--- a/Source/WebCore/inspector/front-end/ExtensionServer.js
+++ b/Source/WebCore/inspector/front-end/ExtensionServer.js
@@ -34,6 +34,8 @@ WebInspector.ExtensionServer = function()
this._handlers = {};
this._subscribers = {};
this._extraHeaders = {};
+ this._resources = {};
+ this._lastResourceId = 0;
this._status = new WebInspector.ExtensionStatus();
this._registerHandler("addRequestHeaders", this._onAddRequestHeaders.bind(this));
@@ -108,10 +110,15 @@ WebInspector.ExtensionServer.prototype = {
delete this._clientObjects[auditRun.id];
},
+ resetResources: function()
+ {
+ this._resources = {};
+ },
+
_notifyResourceFinished: function(event)
{
var resource = event.data;
- this._postNotification("resource-finished", resource.identifier, (new WebInspector.HAREntry(resource)).build());
+ this._postNotification("resource-finished", this._resourceId(resource), (new WebInspector.HAREntry(resource)).build());
},
_postNotification: function(type, details)
@@ -166,7 +173,7 @@ WebInspector.ExtensionServer.prototype = {
allHeaders[name] = headers[name];
}
}
- InspectorBackend.setExtraHeaders(allHeaders);
+ NetworkAgent.setExtraHeaders(allHeaders);
},
_onCreatePanel: function(message, port)
@@ -176,13 +183,12 @@ WebInspector.ExtensionServer.prototype = {
// shouldn't be hit unless someone is bypassing the API.
if (id in this._clientObjects || id in WebInspector.panels)
return this._status.E_EXISTS(id);
+
var panel = new WebInspector.ExtensionPanel(id, message.title, message.icon);
this._clientObjects[id] = panel;
-
- var toolbarElement = document.getElementById("toolbar");
- var lastToolbarItem = WebInspector.panelOrder[WebInspector.panelOrder.length - 1].toolbarItem;
- WebInspector.addPanelToolbarIcon(toolbarElement, panel, lastToolbarItem);
WebInspector.panels[id] = panel;
+ WebInspector.addPanel(panel);
+
var iframe = this._createClientIframe(panel.element, message.url);
iframe.style.height = "100%";
return this._status.OK();
@@ -255,9 +261,9 @@ WebInspector.ExtensionServer.prototype = {
_onReload: function(message)
{
if (typeof message.userAgent === "string")
- InspectorBackend.setUserAgentOverride(message.userAgent);
+ InspectorAgent.setUserAgentOverride(message.userAgent);
- InspectorBackend.reloadPage(false);
+ InspectorAgent.reloadPage(false);
return this._status.OK();
},
@@ -273,7 +279,7 @@ WebInspector.ExtensionServer.prototype = {
this._dispatchCallback(message.requestId, port, result);
}
var evalExpression = "JSON.stringify(eval(unescape('" + escape(message.expression) + "')));";
- InspectorBackend.evaluate(evalExpression, "none", true, callback.bind(this));
+ RuntimeAgent.evaluate(evalExpression, "", true, callback.bind(this));
},
_onRevealAndSelect: function(message)
@@ -289,7 +295,7 @@ WebInspector.ExtensionServer.prototype = {
var id = message.id;
var resource = null;
- resource = WebInspector.networkResourceById(id) || WebInspector.resourceForURL(id);
+ resource = this._resourceById(id) || WebInspector.resourceForURL(id);
if (!resource)
return this._status.E_NOTFOUND(typeof id + ": " + id);
@@ -304,9 +310,10 @@ WebInspector.ExtensionServer.prototype = {
_onGetHAR: function(request)
{
- var harLog = new WebInspector.HARLog();
- harLog.includeResourceIds = true;
- return harLog.build();
+ var harLog = (new WebInspector.HARLog()).build();
+ for (var i = 0; i < harLog.entries.length; ++i)
+ harLog.entries[i]._resourceId = this._resourceId(WebInspector.networkResources[i]);
+ return harLog;
},
_onGetResourceContent: function(message, port)
@@ -319,12 +326,26 @@ WebInspector.ExtensionServer.prototype = {
};
this._dispatchCallback(message.requestId, port, response);
}
- var resource = WebInspector.networkResourceById(message.id);
+ var resource = this._resourceById(message.id);
if (!resource)
return this._status.E_NOTFOUND(message.id);
resource.requestContent(onContentAvailable.bind(this));
},
+ _resourceId: function(resource)
+ {
+ if (!resource._extensionResourceId) {
+ resource._extensionResourceId = ++this._lastResourceId;
+ this._resources[resource._extensionResourceId] = resource;
+ }
+ return resource._extensionResourceId;
+ },
+
+ _resourceById: function(id)
+ {
+ return this._resources[id];
+ },
+
_onAddAuditCategory: function(request)
{
var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.resultCount);
diff --git a/Source/WebCore/inspector/front-end/FontView.js b/Source/WebCore/inspector/front-end/FontView.js
index 82559ef..55110b7 100644
--- a/Source/WebCore/inspector/front-end/FontView.js
+++ b/Source/WebCore/inspector/front-end/FontView.js
@@ -33,6 +33,12 @@ WebInspector.FontView = function(resource)
this.element.addStyleClass("font");
}
+WebInspector.FontView._fontInnerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
+
+WebInspector.FontView._fontId = 0;
+
+WebInspector.FontView._measureFontSize = 50;
+
WebInspector.FontView.prototype = {
hasContent: function()
{
@@ -44,33 +50,57 @@ WebInspector.FontView.prototype = {
if (this.fontPreviewElement)
return;
- var uniqueFontName = "WebInspectorFontPreview" + this.resource.identifier;
+ var uniqueFontName = "WebInspectorFontPreview" + (++WebInspector.FontView._fontId);
this.fontStyleElement = document.createElement("style");
this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }";
document.head.appendChild(this.fontStyleElement);
this.fontPreviewElement = document.createElement("div");
- this.element.appendChild(this.fontPreviewElement);
-
+ this.fontPreviewElement.innerHTML = WebInspector.FontView._fontInnerHTML;
this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null);
- this.fontPreviewElement.innerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";
- this._lineCount = this.fontPreviewElement.getElementsByTagName("br").length + 1;
+ this.fontPreviewElement.style.setProperty("visibility", "hidden", null);
- this.updateFontPreviewSize();
+ this._dummyElement = document.createElement("div");
+ this._dummyElement.style.visibility = "hidden";
+ this._dummyElement.style.zIndex = "-1";
+ this._dummyElement.style.display = "inline";
+ this._dummyElement.style.position = "absolute";
+ this._dummyElement.style.setProperty("font-family", uniqueFontName, null);
+ this._dummyElement.style.setProperty("font-size", WebInspector.FontView._measureFontSize + "px", null);
+ this._dummyElement.innerHTML = WebInspector.FontView._fontInnerHTML;
+
+ this.element.appendChild(this.fontPreviewElement);
},
show: function(parentElement)
{
WebInspector.ResourceView.prototype.show.call(this, parentElement);
this._createContentIfNeeded();
+
this.updateFontPreviewSize();
},
resize: function()
{
- this.updateFontPreviewSize();
- WebInspector.ResourceView.prototype.resize.call(this);
+ if (this._inResize)
+ return;
+
+ this._inResize = true;
+ try {
+ this.updateFontPreviewSize();
+ } finally {
+ delete this._inResize;
+ }
+ },
+
+ _measureElement: function()
+ {
+ this.element.appendChild(this._dummyElement);
+ var result = { width: this._dummyElement.offsetWidth, height: this._dummyElement.offsetHeight };
+ this.element.removeChild(this._dummyElement);
+
+ return result;
},
updateFontPreviewSize: function()
@@ -78,31 +108,26 @@ WebInspector.FontView.prototype = {
if (!this.fontPreviewElement || !this.visible)
return;
- const measureFontSize = 50;
- this.fontPreviewElement.style.setProperty("font-size", measureFontSize + "px", null);
- this.fontPreviewElement.style.setProperty("position", "absolute", null);
- this.fontPreviewElement.style.removeProperty("height");
+ this.fontPreviewElement.style.removeProperty("visibility");
+ var dimension = this._measureElement();
- const height = this.fontPreviewElement.offsetHeight;
- const width = this.fontPreviewElement.offsetWidth;
+ const height = dimension.height;
+ const width = dimension.width;
- // Subtract some padding. This should match the padding in the CSS plus room for the scrollbar.
+ // Subtract some padding. This should match the paddings in the CSS plus room for the scrollbar.
const containerWidth = this.element.offsetWidth - 50;
+ const containerHeight = this.element.offsetHeight - 30;
- if (!height || !width || !containerWidth) {
+ if (!height || !width || !containerWidth || !containerHeight) {
this.fontPreviewElement.style.removeProperty("font-size");
- this.fontPreviewElement.style.removeProperty("position");
return;
}
- var realLineHeight = Math.floor(height / this._lineCount);
- var fontSizeLineRatio = measureFontSize / realLineHeight;
var widthRatio = containerWidth / width;
- var finalFontSize = Math.floor(realLineHeight * widthRatio * fontSizeLineRatio) - 2;
+ var heightRatio = containerHeight / height;
+ var finalFontSize = Math.floor(WebInspector.FontView._measureFontSize * Math.min(widthRatio, heightRatio)) - 2;
this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null);
- this.fontPreviewElement.style.setProperty("height", this.fontPreviewElement.offsetHeight + "px", null);
- this.fontPreviewElement.style.removeProperty("position");
}
}
diff --git a/Source/WebCore/inspector/front-end/HAREntry.js b/Source/WebCore/inspector/front-end/HAREntry.js
index 4d690b3..b5223b6 100644
--- a/Source/WebCore/inspector/front-end/HAREntry.js
+++ b/Source/WebCore/inspector/front-end/HAREntry.js
@@ -189,7 +189,6 @@ WebInspector.HAREntry._toMilliseconds = function(time)
WebInspector.HARLog = function()
{
- this.includeResourceIds = false;
}
WebInspector.HARLog.prototype = {
@@ -230,10 +229,7 @@ WebInspector.HARLog.prototype = {
_convertResource: function(resource)
{
- var entry = (new WebInspector.HAREntry(resource)).build();
- if (this.includeResourceIds)
- entry._resourceId = resource.identifier;
- return entry;
+ return (new WebInspector.HAREntry(resource)).build();
},
_pageEventTime: function(time)
diff --git a/Source/WebCore/inspector/front-end/HeapSnapshot.js b/Source/WebCore/inspector/front-end/HeapSnapshot.js
index ef450af..215f31c 100644
--- a/Source/WebCore/inspector/front-end/HeapSnapshot.js
+++ b/Source/WebCore/inspector/front-end/HeapSnapshot.js
@@ -80,6 +80,11 @@ WebInspector.HeapSnapshotEdge.prototype = {
return this._type() === this._snapshot._edgeInternalType;
},
+ get isInvisible()
+ {
+ return this._type() === this._snapshot._edgeInvisibleType;
+ },
+
get isShortcut()
{
return this._type() === this._snapshot._edgeShortcutType;
@@ -123,6 +128,7 @@ WebInspector.HeapSnapshotEdge.prototype = {
return "[" + this.name + "]";
case "internal":
case "hidden":
+ case "invisible":
return "{" + this.name + "}";
};
return "?" + this.name + "?";
@@ -377,6 +383,10 @@ WebInspector.HeapSnapshot.prototype = {
this._edgeHiddenType = this._edgeTypes.indexOf("hidden");
this._edgeInternalType = this._edgeTypes.indexOf("internal");
this._edgeShortcutType = this._edgeTypes.indexOf("shortcut");
+ this._edgeInvisibleType = this._edgeTypes.length;
+ this._edgeTypes.push("invisible");
+
+ this._markInvisibleEdges();
},
dispose: function()
@@ -549,17 +559,44 @@ WebInspector.HeapSnapshot.prototype = {
});
this._aggregatesWithIndexes = true;
+ },
+
+ _markInvisibleEdges: function()
+ {
+ // Mark hidden edges of global objects as invisible.
+ // FIXME: This is a temporary measure. Normally, we should
+ // really hide all hidden nodes.
+ for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
+ var edge = iter.edge;
+ if (!edge.isShortcut)
+ continue;
+ var node = edge.node;
+ var propNames = {};
+ for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) {
+ var globalObjEdge = innerIter.edge;
+ if (globalObjEdge.isShortcut)
+ propNames[globalObjEdge._nameOrIndex] = true;
+ }
+ for (innerIter.first(); innerIter.hasNext(); innerIter.next()) {
+ var globalObjEdge = innerIter.edge;
+ if (!globalObjEdge.isShortcut
+ && globalObjEdge.node.isHidden
+ && globalObjEdge._hasStringName
+ && (globalObjEdge._nameOrIndex in propNames))
+ this._nodes[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTypeOffset] = this._edgeInvisibleType;
+ }
+ }
}
};
-WebInspector.HeapSnapshotFilteredOrderedIterator = function(snapshot, iterator, filter)
+WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter)
{
- this._snapshot = snapshot;
this._filter = filter;
this._iterator = iterator;
this._iterationOrder = null;
this._position = 0;
this._lastComparator = null;
+ this._instancesCount = 0;
}
WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
@@ -588,6 +625,16 @@ WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
return this._position < this._iterationOrder.length;
},
+ incInstancesCount: function()
+ {
+ ++this._instancesCount;
+ },
+
+ get instancesCount()
+ {
+ return this._instancesCount;
+ },
+
get isEmpty()
{
if (this._iterationOrder)
@@ -623,6 +670,11 @@ WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
next: function()
{
++this._position;
+ },
+
+ resetInstancesCount: function()
+ {
+ this._instancesCount = 0;
}
}
@@ -633,7 +685,8 @@ WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = fu
WebInspector.HeapSnapshotEdgesProvider = function(snapshot, rawEdges, filter)
{
- WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot, new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, rawEdges)), filter);
+ this.snapshot = snapshot;
+ WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, rawEdges)), filter);
}
WebInspector.HeapSnapshotEdgesProvider.prototype = {
@@ -649,8 +702,8 @@ WebInspector.HeapSnapshotEdgesProvider.prototype = {
var edgeA = this._iterator.item.clone();
var edgeB = edgeA.clone();
- var nodeA = new WebInspector.HeapSnapshotNode(this._snapshot);
- var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot);
+ var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
+ var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
function sortByEdgeFieldName(ascending, indexA, indexB)
{
@@ -715,7 +768,8 @@ WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSn
WebInspector.HeapSnapshotNodesProvider = function(snapshot, nodes, filter)
{
- WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot, nodes, filter);
+ this.snapshot = snapshot;
+ WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, nodes, filter);
}
WebInspector.HeapSnapshotNodesProvider.prototype = {
@@ -729,8 +783,8 @@ WebInspector.HeapSnapshotNodesProvider.prototype = {
var ascending1 = comparator.ascending1;
var ascending2 = comparator.ascending2;
- var nodeA = new WebInspector.HeapSnapshotNode(this._snapshot);
- var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot);
+ var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
+ var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);
function sortByNodeField(fieldName, ascending, indexA, indexB)
{
@@ -832,7 +886,8 @@ WebInspector.HeapSnapshotPathFinder.prototype = {
_skipEdge: function(edge)
{
- return (this._skipHidden && (edge.isHidden || edge.node.isHidden))
+ return edge.isInvisible
+ || (this._skipHidden && (edge.isHidden || edge.node.isHidden))
|| this._hasInPath(edge.nodeIndex);
},
diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotView.js b/Source/WebCore/inspector/front-end/HeapSnapshotView.js
index 44b95c3..87e02f7 100644
--- a/Source/WebCore/inspector/front-end/HeapSnapshotView.js
+++ b/Source/WebCore/inspector/front-end/HeapSnapshotView.js
@@ -1010,7 +1010,7 @@ WebInspector.HeapSnapshotProfileType.prototype = {
buttonClicked: function()
{
- InspectorBackend.takeHeapSnapshot(false);
+ ProfilerAgent.takeHeapSnapshot(false);
},
get welcomeMessage()
diff --git a/Source/WebCore/inspector/front-end/Images/helpButtonGlyph.png b/Source/WebCore/inspector/front-end/Images/helpButtonGlyph.png
new file mode 100644
index 0000000..92fe59a
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/Images/helpButtonGlyph.png
Binary files differ
diff --git a/Source/WebCore/inspector/front-end/MetricsSidebarPane.js b/Source/WebCore/inspector/front-end/MetricsSidebarPane.js
index 3c0f315..14039ef 100644
--- a/Source/WebCore/inspector/front-end/MetricsSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/MetricsSidebarPane.js
@@ -40,7 +40,7 @@ WebInspector.MetricsSidebarPane.prototype = {
else
node = this.node;
- if (!node || !node.ownerDocument.defaultView || node.nodeType !== Node.ELEMENT_NODE) {
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) {
this.bodyElement.removeChildren();
return;
}
diff --git a/Source/WebCore/inspector/front-end/NetworkManager.js b/Source/WebCore/inspector/front-end/NetworkManager.js
index da043fe..246b53c 100644
--- a/Source/WebCore/inspector/front-end/NetworkManager.js
+++ b/Source/WebCore/inspector/front-end/NetworkManager.js
@@ -33,7 +33,7 @@ WebInspector.NetworkManager = function(resourceTreeModel)
WebInspector.Object.call(this);
this._resourceTreeModel = resourceTreeModel;
this._dispatcher = new WebInspector.NetworkDispatcher(resourceTreeModel, this);
- InspectorBackend.cachedResources(this._processCachedResources.bind(this));
+ NetworkAgent.enable(this._processCachedResources.bind(this));
}
WebInspector.NetworkManager.EventTypes = {
@@ -44,11 +44,11 @@ WebInspector.NetworkManager.EventTypes = {
}
WebInspector.NetworkManager.prototype = {
- reset: function()
+ frontendReused: function()
{
WebInspector.panels.network.clear();
this._resourceTreeModel.reset();
- InspectorBackend.cachedResources(this._processCachedResources.bind(this));
+ NetworkAgent.enable(this._processCachedResources.bind(this));
},
requestContent: function(resource, base64Encode, callback)
@@ -57,7 +57,7 @@ WebInspector.NetworkManager.prototype = {
{
callback(success ? content : null);
}
- InspectorBackend.resourceContent(resource.loader.frameId, resource.url, base64Encode, callbackWrapper);
+ NetworkAgent.resourceContent(resource.loader.frameId, resource.url, base64Encode, callbackWrapper);
},
_processCachedResources: function(mainFramePayload)
diff --git a/Source/WebCore/inspector/front-end/NetworkPanel.js b/Source/WebCore/inspector/front-end/NetworkPanel.js
index 085f468..06983f0 100644
--- a/Source/WebCore/inspector/front-end/NetworkPanel.js
+++ b/Source/WebCore/inspector/front-end/NetworkPanel.js
@@ -110,7 +110,7 @@ WebInspector.NetworkPanel.prototype = {
{
WebInspector.Panel.prototype.resize.call(this);
this._dataGrid.updateWidths();
- this._positionSummaryBar();
+ this._updateOffscreenRows();
},
updateSidebarWidth: function(width)
@@ -133,41 +133,6 @@ WebInspector.NetworkPanel.prototype = {
}
},
- _positionSummaryBar: function()
- {
- // Position the total bar.
-
- var fillerRow = this._dataGrid.dataTableBody.lastChild;
- if (this._summaryBarElement.parentElement !== this.element && fillerRow.offsetHeight > 0) {
- // Glue status to bottom.
- if (this._summaryBarRowNode) {
- this._dataGrid.removeChild(this._summaryBarRowNode);
- delete this._summaryBarRowNode;
- }
- this._summaryBarElement.addStyleClass("network-summary-bar-bottom");
- this.element.appendChild(this._summaryBarElement);
- this._dataGrid.element.style.bottom = "20px";
- return;
- }
-
- if (!this._summaryBarRowNode && !fillerRow.offsetHeight) {
- // Glue status to table.
- this._summaryBarRowNode = new WebInspector.NetworkTotalGridNode(this._summaryBarElement);
- this._summaryBarElement.removeStyleClass("network-summary-bar-bottom");
- this._dataGrid.appendChild(this._summaryBarRowNode);
- this._dataGrid.element.style.bottom = 0;
- this._sortItems();
- }
- this._updateOffscreenRows();
- },
-
- _resetSummaryBar: function()
- {
- delete this._summaryBarRowNode;
- this._summaryBarElement.parentElement.removeChild(this._summaryBarElement);
- this._updateSummaryBar();
- },
-
_createTimelineGrid: function()
{
this._timelineGrid = new WebInspector.TimelineGrid();
@@ -368,14 +333,17 @@ WebInspector.NetworkPanel.prototype = {
_createSummaryBar: function()
{
- this._summaryBarElement = document.createElement("div");
- this._summaryBarElement.className = "network-summary-bar";
- this.containerElement.appendChild(this._summaryBarElement);
+ var tbody = this._dataGrid.dataTableBody;
+ var tfoot = document.createElement("tfoot");
+ var tr = tfoot.createChild("tr", "revealed network-summary-bar");
+ var td = tr.createChild("td");
+ td.setAttribute("colspan", 7);
+ tbody.parentNode.insertBefore(tfoot, tbody);
+ this._summaryBarElement = td;
},
_updateSummaryBar: function()
{
- this._positionSummaryBar(); // Grid is growing.
var numRequests = this._resources.length;
if (!numRequests) {
@@ -387,7 +355,6 @@ WebInspector.NetworkPanel.prototype = {
img.src = "Images/warningIcon.png";
this._summaryBarElement.removeChildren();
this._summaryBarElement.appendChild(img);
- this._summaryBarElement.appendChild(document.createTextNode(" "));
this._summaryBarElement.appendChild(document.createTextNode(
WebInspector.UIString("No requests captured. Reload the page to see detailed information on the network activity.")));
return;
@@ -438,7 +405,6 @@ WebInspector.NetworkPanel.prototype = {
selectMultiple = true;
this._filter(e.target, selectMultiple);
- this._positionSummaryBar();
},
_filter: function(target, selectMultiple)
@@ -478,6 +444,7 @@ WebInspector.NetworkPanel.prototype = {
target.addStyleClass("selected");
this._showCategory(target.category);
+ this._updateOffscreenRows();
return;
}
@@ -655,7 +622,6 @@ WebInspector.NetworkPanel.prototype = {
this.visibleView.show(this._viewsContainerElement);
this._dataGrid.updateWidths();
- this._positionSummaryBar();
},
hide: function()
@@ -727,6 +693,7 @@ WebInspector.NetworkPanel.prototype = {
this._staleResources = [];
this._sortItems();
this._updateSummaryBar();
+ this._updateOffscreenRows();
this._dataGrid.updateWidths();
if (wasScrolledToLastRow)
@@ -756,7 +723,6 @@ WebInspector.NetworkPanel.prototype = {
this._resourceGridNodes = {};
this._dataGrid.removeChildren();
- delete this._summaryBarRowNode;
this._updateDividersIfNeeded(true);
// End reset timeline.
@@ -765,7 +731,8 @@ WebInspector.NetworkPanel.prototype = {
this._viewsContainerElement.removeChildren();
this._viewsContainerElement.appendChild(this._closeButtonElement);
- this._resetSummaryBar();
+ this._updateSummaryBar();
+ WebInspector.extensionServer.resetResources();
},
get resources()
@@ -904,7 +871,7 @@ WebInspector.NetworkPanel.prototype = {
this._timelineGrid.element.removeStyleClass("small");
this._viewsContainerElement.removeStyleClass("small");
}
- this._positionSummaryBar();
+ this._updateOffscreenRows();
},
_getPopoverAnchor: function(element)
@@ -1006,7 +973,7 @@ WebInspector.NetworkPanel.prototype = {
_contextMenu: function(event)
{
// createBlobURL is enabled conditionally, do not expose resource export if it's not available.
- if (typeof window.webkitURL.createObjectURL !== "function" || !Preferences.resourceExportEnabled)
+ if ((window.webkitURL && typeof window.webkitURL.createObjectURL !== "function") || !Preferences.resourceExportEnabled)
return;
var contextMenu = new WebInspector.ContextMenu();
@@ -1049,9 +1016,6 @@ WebInspector.NetworkPanel.prototype = {
var unfilteredRowIndex = 0;
for (var i = 0; i < recordsCount - 1; ++i) {
var row = rows[i];
- // Don't touch summaty - quit instead.
- if (this._summaryBarRowNode && row === this._summaryBarRowNode.element)
- break;
var dataGridNode = this._dataGrid.dataGridNodeFromNode(row);
if (dataGridNode.isFilteredOut()) {
@@ -1395,7 +1359,7 @@ WebInspector.NetworkDataGridNode.prototype = {
_openInNewTab: function()
{
- InspectorBackend.openInInspectedWindow(this._resource.url);
+ InspectorAgent.openInInspectedWindow(this._resource.url);
},
get selectable()
@@ -1711,32 +1675,3 @@ WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyN
}
WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
-
-WebInspector.NetworkTotalGridNode = function(element)
-{
- this._summaryBarElement = element;
- WebInspector.DataGridNode.call(this, {summaryRow: true});
-}
-
-WebInspector.NetworkTotalGridNode.prototype = {
- isFilteredOut: function()
- {
- return false;
- },
-
- get selectable()
- {
- return false;
- },
-
- createCells: function()
- {
- var td = document.createElement("td");
- td.setAttribute("colspan", 7);
- td.className = "network-summary";
- td.appendChild(this._summaryBarElement);
- this._element.appendChild(td);
- }
-}
-
-WebInspector.NetworkTotalGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
diff --git a/Source/WebCore/inspector/front-end/Panel.js b/Source/WebCore/inspector/front-end/Panel.js
index 4c42a60..1b99dd4 100644
--- a/Source/WebCore/inspector/front-end/Panel.js
+++ b/Source/WebCore/inspector/front-end/Panel.js
@@ -46,29 +46,7 @@ WebInspector.Panel.prototype = {
if (this._toolbarItem)
return this._toolbarItem;
- // Sample toolbar item as markup:
- // <button class="toolbar-item resources toggleable">
- // <div class="toolbar-icon"></div>
- // <div class="toolbar-label">Resources</div>
- // </button>
-
- this._toolbarItem = document.createElement("button");
- this._toolbarItem.className = "toolbar-item toggleable";
- this._toolbarItem.panel = this;
-
- this._toolbarItem.addStyleClass(this._panelName);
-
- var iconElement = document.createElement("div");
- iconElement.className = "toolbar-icon";
- this._toolbarItem.appendChild(iconElement);
-
- if ("toolbarItemLabel" in this) {
- var labelElement = document.createElement("div");
- labelElement.className = "toolbar-label";
- labelElement.textContent = this.toolbarItemLabel;
- this._toolbarItem.appendChild(labelElement);
- }
-
+ this._toolbarItem = WebInspector.Toolbar.createPanelToolbarItem(this);
return this._toolbarItem;
},
@@ -110,6 +88,12 @@ WebInspector.Panel.prototype = {
this._toolbarItem.removeStyleClass("toggled-on");
},
+ reset: function()
+ {
+ this.searchCanceled();
+ WebInspector.resetFocusElement();
+ },
+
get defaultFocusedElement()
{
return this.sidebarTreeElement || this.element;
@@ -132,7 +116,7 @@ WebInspector.Panel.prototype = {
}
}
- WebInspector.updateSearchMatchesCount(0, this);
+ WebInspector.searchController.updateSearchMatchesCount(0, this);
if (this._currentSearchChunkIntervalIdentifier) {
clearInterval(this._currentSearchChunkIntervalIdentifier);
@@ -161,7 +145,7 @@ WebInspector.Panel.prototype = {
function updateMatchesCount()
{
- WebInspector.updateSearchMatchesCount(this._totalSearchMatches, this);
+ WebInspector.searchController.updateSearchMatchesCount(this._totalSearchMatches, this);
matchesCountUpdateTimeout = null;
}
diff --git a/Source/WebCore/inspector/front-end/PleaseWaitMessage.js b/Source/WebCore/inspector/front-end/PleaseWaitMessage.js
index 54d805d..e1980a0 100644
--- a/Source/WebCore/inspector/front-end/PleaseWaitMessage.js
+++ b/Source/WebCore/inspector/front-end/PleaseWaitMessage.js
@@ -59,7 +59,7 @@ WebInspector.PleaseWaitMessage.prototype = {
get instance()
{
- if (!"_instance" in WebInspector.PleaseWaitMessage.prototype)
+ if (!("_instance" in WebInspector.PleaseWaitMessage.prototype))
WebInspector.PleaseWaitMessage.prototype._instance = new WebInspector.PleaseWaitMessage();
return WebInspector.PleaseWaitMessage.prototype._instance;
},
diff --git a/Source/WebCore/inspector/front-end/Popover.js b/Source/WebCore/inspector/front-end/Popover.js
index 32535e9..f20b8c6 100644
--- a/Source/WebCore/inspector/front-end/Popover.js
+++ b/Source/WebCore/inspector/front-end/Popover.js
@@ -40,6 +40,7 @@ WebInspector.Popover = function(contentElement)
this.contentElement = contentElement;
this._contentDiv = document.createElement("div");
this._contentDiv.className = "content";
+ this._visible = false;
}
WebInspector.Popover.prototype = {
@@ -60,6 +61,7 @@ WebInspector.Popover.prototype = {
this.element.appendChild(this._contentDiv);
document.body.appendChild(this.element);
this._positionElement(anchor, preferredWidth, preferredHeight);
+ this._visible = true;
},
hide: function()
@@ -68,6 +70,12 @@ WebInspector.Popover.prototype = {
delete WebInspector.Popover._popoverElement;
document.body.removeChild(this.element);
}
+ this._visible = false;
+ },
+
+ get visible()
+ {
+ return this._visible;
},
_positionElement: function(anchorElement, preferredWidth, preferredHeight)
diff --git a/Source/WebCore/inspector/front-end/ProfileView.js b/Source/WebCore/inspector/front-end/ProfileView.js
index c325bf7..335bf03 100644
--- a/Source/WebCore/inspector/front-end/ProfileView.js
+++ b/Source/WebCore/inspector/front-end/ProfileView.js
@@ -94,7 +94,7 @@ WebInspector.CPUProfileView = function(profile)
self._updatePercentButton();
}
- InspectorBackend.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
+ ProfilerAgent.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
}
WebInspector.CPUProfileView.prototype = {
@@ -593,9 +593,9 @@ WebInspector.CPUProfileType.prototype = {
this._recording = !this._recording;
if (this._recording)
- InspectorBackend.startProfiling();
+ InspectorAgent.startProfiling();
else
- InspectorBackend.stopProfiling();
+ InspectorAgent.stopProfiling();
},
get welcomeMessage()
diff --git a/Source/WebCore/inspector/front-end/ProfilesPanel.js b/Source/WebCore/inspector/front-end/ProfilesPanel.js
index b87ea7f..e5fb49e 100644
--- a/Source/WebCore/inspector/front-end/ProfilesPanel.js
+++ b/Source/WebCore/inspector/front-end/ProfilesPanel.js
@@ -185,8 +185,19 @@ WebInspector.ProfilesPanel.prototype = {
_reset: function()
{
- for (var i = 0; i < this._profiles.length; ++i)
+ WebInspector.Panel.prototype.reset.call(this);
+
+ for (var i = 0; i < this._profiles.length; ++i) {
+ var view = this._profiles[i]._profileView;
+ if (view && ("dispose" in view))
+ view.dispose();
delete this._profiles[i]._profileView;
+ var profile = this._profiles[i];
+ if (profile.nodes) {
+ delete profile.nodes;
+ delete profile.strings;
+ }
+ }
delete this.visibleView;
delete this.currentQuery;
@@ -215,7 +226,7 @@ WebInspector.ProfilesPanel.prototype = {
_clearProfiles: function()
{
- InspectorBackend.clearProfiles();
+ ProfilerAgent.clearProfiles();
this._reset();
},
@@ -351,7 +362,7 @@ WebInspector.ProfilesPanel.prototype = {
sidebarParent.removeChild(profile._profilesTreeElement);
if (!profile.isTemporary)
- InspectorBackend.removeProfile(profile.typeId, profile.uid);
+ ProfilerAgent.removeProfile(profile.typeId, profile.uid);
// No other item will be selected if there aren't any other profiles, so
// make sure that view gets cleared when the last profile is removed.
@@ -409,6 +420,11 @@ WebInspector.ProfilesPanel.prototype = {
return !!this._profilesIdMap[this._makeKey(profile.uid, profile.typeId)];
},
+ getProfile: function(typeId, uid)
+ {
+ return this._profilesIdMap[this._makeKey(uid, typeId)];
+ },
+
loadHeapSnapshot: function(uid, callback)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
@@ -424,7 +440,7 @@ WebInspector.ProfilesPanel.prototype = {
profile._callbacks = [callback];
profile._json = "";
profile.sideBarElement.subtitle = WebInspector.UIString("Loading…");
- InspectorBackend.getProfile(profile.typeId, profile.uid);
+ ProfilerAgent.getProfile(profile.typeId, profile.uid);
}
},
@@ -455,6 +471,12 @@ WebInspector.ProfilesPanel.prototype = {
delete profile._is_loading;
profile._loaded = true;
profile.sideBarElement.subtitle = "";
+
+ if (!Preferences.detailedHeapProfiles && WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) {
+ WebInspector.panels.profiles._enableDetailedHeapProfiles(false);
+ return;
+ }
+
if (!Preferences.detailedHeapProfiles)
WebInspector.HeapSnapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
else
@@ -592,10 +614,10 @@ WebInspector.ProfilesPanel.prototype = {
{
if (this._profilerEnabled) {
WebInspector.settings.profilerEnabled = false;
- InspectorBackend.disableProfiler(true);
+ InspectorAgent.disableProfiler(true);
} else {
WebInspector.settings.profilerEnabled = !!optionalAlways;
- InspectorBackend.enableProfiler();
+ InspectorAgent.enableProfiler();
}
},
@@ -612,7 +634,7 @@ WebInspector.ProfilesPanel.prototype = {
this._addProfileHeader(profileHeaders[i]);
}
- InspectorBackend.getProfileHeaders(populateCallback.bind(this));
+ ProfilerAgent.getProfileHeaders(populateCallback.bind(this));
this._profilesWereRequested = true;
},
@@ -658,7 +680,7 @@ WebInspector.ProfilesPanel.prototype = {
}
this._addProfileHeader(this._temporaryTakingSnapshot);
}
- InspectorBackend.takeHeapSnapshot(detailed);
+ ProfilerAgent.takeHeapSnapshot(detailed);
},
_reportHeapSnapshotProgress: function(done, total)
@@ -668,6 +690,63 @@ WebInspector.ProfilesPanel.prototype = {
if (done >= total)
this._removeProfileHeader(this._temporaryTakingSnapshot);
}
+ },
+
+ handleShortcut: function(event)
+ {
+ if (!Preferences.heapProfilerPresent || Preferences.detailedHeapProfiles)
+ return;
+ var combo = ["U+004C", "U+0045", "U+0041", "U+004B", "U+005A"]; // "LEAKZ"
+ if (this._recognizeKeyboardCombo(combo, event)) {
+ this._displayDetailedHeapProfilesEnabledHint();
+ this._enableDetailedHeapProfiles(true);
+ }
+ },
+
+ _recognizeKeyboardCombo: function(combo, event)
+ {
+ var isRecognized = false;
+ if (!this._comboPosition) {
+ if (event.keyIdentifier === combo[0])
+ this._comboPosition = 1;
+ } else if (event.keyIdentifier === combo[this._comboPosition]) {
+ if (++this._comboPosition === combo.length)
+ isRecognized = true;
+ } else
+ delete this._comboPosition;
+ if (this._comboPosition)
+ event.handled = true;
+ return isRecognized;
+ },
+
+ _displayDetailedHeapProfilesEnabledHint: function()
+ {
+ var message = new WebInspector.HelpScreen("Congratulations!");
+ message.contentElement.addStyleClass("help-table");
+ message.contentElement.textContent = "Detailed Heap snapshots are now enabled.";
+ message.show();
+
+ function hideHint()
+ {
+ message._hide();
+ }
+
+ setTimeout(hideHint, 2000);
+ },
+
+ _enableDetailedHeapProfiles: function(resetAgent)
+ {
+ if (resetAgent)
+ this._clearProfiles();
+ else
+ this._reset();
+ var oldProfileType = this._profileTypesByIdMap[WebInspector.HeapSnapshotProfileType.TypeId];
+ var profileType = new WebInspector.DetailedHeapshotProfileType();
+ profileType.treeElement = oldProfileType.treeElement;
+ this._profileTypesByIdMap[profileType.id] = profileType;
+ Preferences.detailedHeapProfiles = true;
+ this.hide();
+ this.show();
}
}
diff --git a/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js b/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js
index a1e37bc..0c314bc 100644
--- a/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js
@@ -42,15 +42,40 @@ WebInspector.PropertiesSidebarPane.prototype = {
return;
}
- function callback(prototypes)
+ RuntimeAgent.releaseObjectGroup(0, "dom-selection");
+ WebInspector.RemoteObject.resolveNode(node, nodeResolved.bind(this));
+
+ function nodeResolved(objectPayload)
{
+ if (!objectPayload)
+ return;
+ var object = WebInspector.RemoteObject.fromPayload(objectPayload);
+ object.evaluate("var proto = this; result = {}; var counter = 1; while (proto) { result[counter++] = proto; proto = proto.__proto__ }; return result;", nodePrototypesReady.bind(this));
+ }
+
+ function nodePrototypesReady(objectPayload)
+ {
+ if (!objectPayload)
+ return;
+ var object = WebInspector.RemoteObject.fromPayload(objectPayload);
+ object.getOwnProperties(false, fillSection.bind(this));
+ }
+
+ function fillSection(prototypes)
+ {
+ if (!prototypes)
+ return;
+
var body = this.bodyElement;
body.removeChildren();
this.sections = [];
// Get array of prototype user-friendly names.
for (var i = 0; i < prototypes.length; ++i) {
- var prototype = WebInspector.RemoteObject.fromPayload(prototypes[i]);
+ if (!parseInt(prototypes[i].name))
+ continue;
+
+ var prototype = prototypes[i].value;
var title = prototype.description;
if (title.match(/Prototype$/))
title = title.replace(/Prototype$/, "");
@@ -59,7 +84,6 @@ WebInspector.PropertiesSidebarPane.prototype = {
body.appendChild(section.element);
}
}
- InspectorBackend.getNodePrototypes(node.id, callback.bind(this));
}
}
diff --git a/Source/WebCore/inspector/front-end/RemoteObject.js b/Source/WebCore/inspector/front-end/RemoteObject.js
index 10af2e3..4a20cf1 100644
--- a/Source/WebCore/inspector/front-end/RemoteObject.js
+++ b/Source/WebCore/inspector/front-end/RemoteObject.js
@@ -52,7 +52,7 @@ WebInspector.RemoteObject.resolveNode = function(node, callback)
{
callback(object ? WebInspector.RemoteObject.fromPayload(object) : null);
}
- InspectorBackend.resolveNode(node.id, mycallback);
+ DOMAgent.resolveNode(node.id, "dom-selection", mycallback);
}
WebInspector.RemoteObject.fromPayload = function(payload)
@@ -118,7 +118,7 @@ WebInspector.RemoteObject.prototype = {
properties[i].value = WebInspector.RemoteObject.fromPayload(properties[i].value);
callback(properties);
}
- InspectorBackend.getProperties(this._objectId, !!ignoreHasOwnProperty, abbreviate, remoteObjectBinder);
+ RuntimeAgent.getProperties(this._objectId, !!ignoreHasOwnProperty, abbreviate, remoteObjectBinder);
},
setPropertyValue: function(name, value, callback)
@@ -127,12 +127,20 @@ WebInspector.RemoteObject.prototype = {
callback(false);
return;
}
- InspectorBackend.setPropertyValue(this._objectId, name, value, callback);
+ RuntimeAgent.setPropertyValue(this._objectId, name, value, callback);
},
pushNodeToFrontend: function(callback)
{
- InspectorBackend.pushNodeToFrontend(this._objectId, callback);
+ if (this._objectId)
+ WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback);
+ else
+ callback(0);
+ },
+
+ evaluate: function(expression, callback)
+ {
+ RuntimeAgent.evaluateOn(this._objectId, expression, callback);
}
}
diff --git a/Source/WebCore/inspector/front-end/ResourceHeadersView.js b/Source/WebCore/inspector/front-end/ResourceHeadersView.js
index ee1010f..e79078a 100644
--- a/Source/WebCore/inspector/front-end/ResourceHeadersView.js
+++ b/Source/WebCore/inspector/front-end/ResourceHeadersView.js
@@ -224,7 +224,7 @@ WebInspector.ResourceHeadersView.prototype = {
if (this._resource.statusCode) {
var statusImageSource = "";
- if (this._resource.statusCode < 300)
+ if (this._resource.statusCode < 300 || this._resource.statusCode === 304)
statusImageSource = "Images/successGreenDot.png";
else if (this._resource.statusCode < 400)
statusImageSource = "Images/warningOrangeDot.png";
diff --git a/Source/WebCore/inspector/front-end/ResourceView.js b/Source/WebCore/inspector/front-end/ResourceView.js
index e38cd0a..83cf99d5 100644
--- a/Source/WebCore/inspector/front-end/ResourceView.js
+++ b/Source/WebCore/inspector/front-end/ResourceView.js
@@ -50,9 +50,8 @@ WebInspector.ResourceView.createResourceView = function(resource)
case WebInspector.resourceCategories.stylesheets:
case WebInspector.resourceCategories.scripts:
case WebInspector.resourceCategories.xhr:
- var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
- var isScript = resource.type === WebInspector.Resource.Type.Script;
- var view = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
+ var delegate = new WebInspector.SourceFrameDelegateForResourcesPanel(resource);
+ var view = new WebInspector.SourceFrame(delegate, resource.url);
view.resource = resource;
return view;
case WebInspector.resourceCategories.images:
@@ -120,35 +119,31 @@ WebInspector.ResourceView.existingResourceViewForResource = function(resource)
}
-WebInspector.SourceFrameContentProviderForResource = function(resource)
+WebInspector.SourceFrameDelegateForResourcesPanel = function(resource)
{
- WebInspector.SourceFrameContentProvider.call(this);
+ WebInspector.SourceFrameDelegate.call(this);
this._resource = resource;
}
//This is a map from resource.type to mime types
//found in WebInspector.SourceTokenizer.Registry.
-WebInspector.SourceFrameContentProviderForResource.DefaultMIMETypeForResourceType = {
+WebInspector.SourceFrameDelegateForResourcesPanel.DefaultMIMETypeForResourceType = {
0: "text/html",
1: "text/css",
4: "text/javascript"
}
-WebInspector.SourceFrameContentProviderForResource.prototype = {
+WebInspector.SourceFrameDelegateForResourcesPanel.prototype = {
requestContent: function(callback)
{
- function contentLoaded(content)
+ function contentLoaded(text)
{
- var mimeType = WebInspector.SourceFrameContentProviderForResource.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType;
- callback(mimeType, content);
+ var mimeType = WebInspector.SourceFrameDelegateForResourcesPanel.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType;
+ var sourceMapping = new WebInspector.IdenticalSourceMapping();
+ callback(mimeType, new WebInspector.SourceFrameContent(text, sourceMapping, []));
}
this._resource.requestContent(contentLoaded.bind(this));
- },
-
- scripts: function()
- {
- return WebInspector.debuggerModel.scriptsForURL(this._resource.url);
}
}
-WebInspector.SourceFrameContentProviderForResource.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;
+WebInspector.SourceFrameDelegateForResourcesPanel.prototype.__proto__ = WebInspector.SourceFrameDelegate.prototype;
diff --git a/Source/WebCore/inspector/front-end/ResourcesPanel.js b/Source/WebCore/inspector/front-end/ResourcesPanel.js
index 7c0649f..3c85892 100644
--- a/Source/WebCore/inspector/front-end/ResourcesPanel.js
+++ b/Source/WebCore/inspector/front-end/ResourcesPanel.js
@@ -904,7 +904,7 @@ WebInspector.FrameTreeElement.prototype = {
this._storagePanel.showCategoryView(this._displayName);
this.listItemElement.removeStyleClass("hovered");
- InspectorBackend.hideFrameHighlight();
+ InspectorAgent.hideFrameHighlight();
},
get displayName()
@@ -937,10 +937,10 @@ WebInspector.FrameTreeElement.prototype = {
{
if (hovered) {
this.listItemElement.addStyleClass("hovered");
- InspectorBackend.highlightFrame(this._frameId);
+ InspectorAgent.highlightFrame(this._frameId);
} else {
this.listItemElement.removeStyleClass("hovered");
- InspectorBackend.hideFrameHighlight();
+ InspectorAgent.hideFrameHighlight();
}
}
}
@@ -969,7 +969,7 @@ WebInspector.FrameResourceTreeElement.prototype = {
ondblclick: function(event)
{
- InspectorBackend.openInInspectedWindow(this._resource.url);
+ InspectorAgent.openInInspectedWindow(this._resource.url);
},
onattach: function()
diff --git a/Source/WebCore/inspector/front-end/Script.js b/Source/WebCore/inspector/front-end/Script.js
index 8d3eabf..3f27485 100644
--- a/Source/WebCore/inspector/front-end/Script.js
+++ b/Source/WebCore/inspector/front-end/Script.js
@@ -120,6 +120,6 @@ WebInspector.Script.prototype = {
this._source = source;
callback(this._source);
}
- InspectorBackend.getScriptSource(this.sourceID, didGetScriptSource.bind(this));
+ DebuggerAgent.getScriptSource(this.sourceID, didGetScriptSource.bind(this));
}
}
diff --git a/Source/WebCore/inspector/front-end/ScriptFormatter.js b/Source/WebCore/inspector/front-end/ScriptFormatter.js
index 5c00e51..f70d6c6 100644
--- a/Source/WebCore/inspector/front-end/ScriptFormatter.js
+++ b/Source/WebCore/inspector/front-end/ScriptFormatter.js
@@ -36,6 +36,38 @@ WebInspector.ScriptFormatter = function()
this._tasks = [];
}
+WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, lineNumber, columnNumber)
+{
+ var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
+ return position + columnNumber;
+}
+
+WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position)
+{
+ var location = {};
+ location.lineNumber = lineEndings.upperBound(position - 1);
+ if (!location.lineNumber)
+ location.columnNumber = position;
+ else
+ location.columnNumber = position - lineEndings[location.lineNumber - 1] - 1;
+ return location;
+}
+
+WebInspector.ScriptFormatter.findScriptRanges = function(lineEndings, scripts)
+{
+ var scriptRanges = [];
+ for (var i = 0; i < scripts.length; ++i) {
+ var start = { lineNumber: scripts[i].lineOffset, columnNumber: scripts[i].columnOffset };
+ start.position = WebInspector.ScriptFormatter.locationToPosition(lineEndings, start.lineNumber, start.columnNumber);
+ var endPosition = start.position + scripts[i].length;
+ var end = WebInspector.ScriptFormatter.positionToLocation(lineEndings, endPosition);
+ end.position = endPosition;
+ scriptRanges.push({ start: start, end: end, sourceID: scripts[i].sourceID });
+ }
+ scriptRanges.sort(function(x, y) { return x.start.position - y.start.position; });
+ return scriptRanges;
+}
+
WebInspector.ScriptFormatter.prototype = {
formatContent: function(content, callback)
{
@@ -44,7 +76,18 @@ WebInspector.ScriptFormatter.prototype = {
function didFormatChunks()
{
var result = this._buildContentFromChunks(chunks);
- callback(new WebInspector.FormattedSourceFrameContent(content, result.text, result.mapping));
+
+ var sourceMapping = new WebInspector.SourceMappingForFormattedScript(content.text.lineEndings(), result.text.lineEndings(), result.mapping);
+ var formattedScriptRanges = [];
+ for (var i = 0; i < content.scriptRanges.length; ++i) {
+ var scriptRange = content.scriptRanges[i];
+ formattedScriptRange = {};
+ formattedScriptRange.start = sourceMapping.originalPositionToFormattedLocation(scriptRange.start.position);
+ formattedScriptRange.end = sourceMapping.originalPositionToFormattedLocation(scriptRange.end.position);
+ formattedScriptRange.sourceID = scriptRange.sourceID;
+ formattedScriptRanges.push(formattedScriptRange);
+ }
+ callback(new WebInspector.SourceFrameContent(result.text, sourceMapping, formattedScriptRanges));
}
this._formatChunks(chunks, 0, didFormatChunks.bind(this));
},
@@ -63,11 +106,12 @@ WebInspector.ScriptFormatter.prototype = {
}
var currentPosition = 0;
for (var i = 0; i < scriptRanges.length; ++i) {
- var scriptRange = scriptRanges[i];
- if (currentPosition < scriptRange.start)
- addChunk(currentPosition, scriptRange.start, false);
- addChunk(scriptRange.start, scriptRange.end, true);
- currentPosition = scriptRange.end;
+ var start = scriptRanges[i].start.position;
+ var end = scriptRanges[i].end.position;
+ if (currentPosition < start)
+ addChunk(currentPosition, start, false);
+ addChunk(start, end, true);
+ currentPosition = end;
}
if (currentPosition < text.length)
addChunk(currentPosition, text.length, false);
@@ -142,3 +186,48 @@ WebInspector.ScriptFormatter.prototype = {
task.callback(task.source, { original: [], formatted: [] });
}
}
+
+
+WebInspector.SourceMappingForFormattedScript = function(originalLineEndings, formattedLineEndings, mapping)
+{
+ WebInspector.SourceMapping.call(this);
+ this._originalLineEndings = originalLineEndings;
+ this._formattedLineEndings = formattedLineEndings;
+ this._mapping = mapping;
+}
+
+WebInspector.SourceMappingForFormattedScript.prototype = {
+ actualLocationToSourceLocation: function(lineNumber, columnNumber)
+ {
+ var position = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber);
+ return this.originalPositionToFormattedLocation(position);
+ },
+
+ sourceLocationToActualLocation: function(lineNumber, columnNumber)
+ {
+ var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber);
+ var position = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
+ return WebInspector.ScriptFormatter.positionToLocation(this._originalLineEndings, position);
+ },
+
+ originalPositionToFormattedLocation: function(position)
+ {
+ var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, position);
+ var location = WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition);
+ location.position = formattedPosition;
+ return location;
+ },
+
+ _convertPosition: function(positions1, positions2, position)
+ {
+ var index = positions1.upperBound(position);
+ var range1 = positions1[index] - positions1[index - 1];
+ var range2 = positions2[index] - positions2[index - 1];
+ var position2 = positions2[index - 1];
+ if (range1)
+ position2 += Math.round((position - positions1[index - 1]) * range2 / range1);
+ return position2;
+ }
+}
+
+WebInspector.SourceMappingForFormattedScript.prototype.__proto__ = WebInspector.SourceMapping.prototype;
diff --git a/Source/WebCore/inspector/front-end/ScriptsPanel.js b/Source/WebCore/inspector/front-end/ScriptsPanel.js
index 264291f..2647cee 100644
--- a/Source/WebCore/inspector/front-end/ScriptsPanel.js
+++ b/Source/WebCore/inspector/front-end/ScriptsPanel.js
@@ -27,6 +27,8 @@ WebInspector.ScriptsPanel = function()
{
WebInspector.Panel.call(this, "scripts");
+ this._presentationModel = new WebInspector.DebuggerPresentationModel();
+
this.topStatusBar = document.createElement("div");
this.topStatusBar.className = "status-bar";
this.topStatusBar.id = "scripts-status-bar";
@@ -50,11 +52,11 @@ WebInspector.ScriptsPanel = function()
this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
this.topStatusBar.appendChild(this.forwardButton);
- this.filesSelectElement = document.createElement("select");
- this.filesSelectElement.className = "status-bar-item";
- this.filesSelectElement.id = "scripts-files";
- this.filesSelectElement.addEventListener("change", this._changeVisibleFile.bind(this), false);
- this.topStatusBar.appendChild(this.filesSelectElement);
+ this._filesSelectElement = document.createElement("select");
+ this._filesSelectElement.className = "status-bar-item";
+ this._filesSelectElement.id = "scripts-files";
+ this._filesSelectElement.addEventListener("change", this._filesSelectChanged.bind(this), false);
+ this.topStatusBar.appendChild(this._filesSelectElement);
this.functionsSelectElement = document.createElement("select");
this.functionsSelectElement.className = "status-bar-item";
@@ -138,7 +140,7 @@ WebInspector.ScriptsPanel = function()
this.sidebarPanes = {};
this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
- this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
+ this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(this._presentationModel);
this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane();
if (Preferences.nativeInstrumentationEnabled) {
@@ -153,7 +155,6 @@ WebInspector.ScriptsPanel = function()
this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
this.sidebarPanes.callstack.expanded = true;
- this.sidebarPanes.callstack.addEventListener("call frame selected", this._callFrameSelected, this);
this.sidebarPanes.scopechain.expanded = true;
this.sidebarPanes.jsBreakpoints.expanded = true;
@@ -189,6 +190,9 @@ WebInspector.ScriptsPanel = function()
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ScriptSourceChanged, this._scriptSourceChanged, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
+ this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, this._breakpointAdded, this);
+ this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
+ this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, this._callFrameSelected, this);
}
// Keep these in sync with WebCore::ScriptDebugServer
@@ -211,7 +215,7 @@ WebInspector.ScriptsPanel.prototype = {
get defaultFocusedElement()
{
- return this.filesSelectElement;
+ return this._filesSelectElement;
},
get paused()
@@ -255,23 +259,14 @@ WebInspector.ScriptsPanel.prototype = {
var sourceID = event.data.sourceID;
var oldSource = event.data.oldSource;
- var oldView, newView;
var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
if (script.resource) {
- oldView = this._urlToSourceFrame[script.resource.url];
- delete this._urlToSourceFrame[script.resource.url];
- newView = this._sourceFrameForResource(script.resource);
var revertHandle = WebInspector.debuggerModel.editScriptSource.bind(WebInspector.debuggerModel, sourceID, oldSource);
script.resource.setContent(script.source, revertHandle);
- } else {
- var oldView = script._sourceFrame;
- delete script._sourceFrame;
- newView = this._sourceFrameForScript(script);
}
- newView.scrollTop = oldView.scrollTop;
- if (this.visibleView === oldView)
- this.visibleView = newView;
+ var sourceFileId = this._sourceFileIdForScript(script);
+ this._recreateSourceFrame(sourceFileId);
var callFrames = WebInspector.debuggerModel.callFrames;
if (callFrames.length)
@@ -280,11 +275,20 @@ WebInspector.ScriptsPanel.prototype = {
_addScript: function(script)
{
- var resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL);
+ if (!script.sourceURL) {
+ // Anonymous scripts are shown only when stepping.
+ return;
+ }
+
+ var resource = this._resourceForURL(script.sourceURL);
if (resource) {
if (resource.finished) {
// Resource is finished, bind the script right away.
script.resource = resource;
+
+ // Add resource url to files select if not already added while debugging inlined scripts.
+ if (!(resource.url in this._sourceFileIdToFilesSelectOption))
+ this._addOptionToFilesSelectAndShowSourceFrameIfNeeded(resource.url);
} else {
// Resource is not finished, bind the script later.
if (!resource._scriptsPendingResourceLoad) {
@@ -292,40 +296,84 @@ WebInspector.ScriptsPanel.prototype = {
resource.addEventListener("finished", this._resourceLoadingFinished, this);
}
resource._scriptsPendingResourceLoad.push(script);
+
+ // Source frame content is outdated since we have new script parsed.
+ this._recreateSourceFrame(script.sourceURL);
}
+ } else if (!(script.sourceURL in this._sourceFileIdToFilesSelectOption)) {
+ // This is a dynamic script with "//@ sourceURL=" comment.
+ this._addOptionToFilesSelectAndShowSourceFrameIfNeeded(script.sourceURL);
}
- this._addScriptToFilesMenu(script);
+ },
+
+ _resourceForURL: function(url)
+ {
+ return WebInspector.networkManager.inflightResourceForURL(url) || WebInspector.resourceForURL(url);
},
_resourceLoadingFinished: function(e)
{
var resource = e.target;
- var visible = false;
- var select = this.filesSelectElement;
+ // Bind scripts to resource.
for (var i = 0; i < resource._scriptsPendingResourceLoad.length; ++i) {
- // Bind script to resource.
var script = resource._scriptsPendingResourceLoad[i];
script.resource = resource;
+ }
+ delete resource._scriptsPendingResourceLoad;
+
+ // Recreate source frame to show resource content.
+ this._recreateSourceFrame(resource.url);
+
+ // Add resource url to files select if not already added while debugging inlined scripts.
+ if (!(resource.url in this._sourceFileIdToFilesSelectOption))
+ this._addOptionToFilesSelectAndShowSourceFrameIfNeeded(resource.url);
+ },
- if (select.options[select.selectedIndex] === script.filesSelectOption)
- visible = true;
+ _addOptionToFilesSelectAndShowSourceFrameIfNeeded: function(url)
+ {
+ this._addOptionToFilesSelect(url);
- // Remove script from the files list.
- script.filesSelectOption.parentElement.removeChild(script.filesSelectOption);
+ var lastViewedURL = WebInspector.settings.lastViewedScriptFile;
+ if (this._filesSelectElement.length === 1) {
+ // Option we just added is the only option in files select.
+ // We have to show corresponding source frame immediately.
+ this._showSourceFrameAndAddToHistory(url);
+ // Restore original value of lastViewedScriptFile because
+ // source frame was shown as a result of initial load.
+ WebInspector.settings.lastViewedScriptFile = lastViewedURL;
+ } else if (url === lastViewedURL)
+ this._showSourceFrameAndAddToHistory(url);
+ },
+
+ _addOptionToFilesSelect: function(sourceFileId)
+ {
+ var script = this._scriptForSourceFileId(sourceFileId);
+ var select = this._filesSelectElement;
+ var option = document.createElement("option");
+ option.text = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
+ if (script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD)
+ option.addStyleClass("extension-script");
+ function optionCompare(a, b)
+ {
+ if (a.text === b.text)
+ return 0;
+ return a.text < b.text ? -1 : 1;
}
- // Adding first script will add resource.
- this._addScriptToFilesMenu(resource._scriptsPendingResourceLoad[0]);
- delete resource._scriptsPendingResourceLoad;
+ var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
+ if (insertionIndex < 0)
+ select.appendChild(option);
+ else
+ select.insertBefore(option, select.childNodes.item(insertionIndex));
- if (visible)
- this._showScriptOrResource(resource, { initialLoad: true });
+ option._sourceFileId = sourceFileId;
+ this._sourceFileIdToFilesSelectOption[sourceFileId] = option;
},
addConsoleMessage: function(message)
{
this._messages.push(message);
- var sourceFrame = this._urlToSourceFrame[message.url];
+ var sourceFrame = this._sourceFileIdToSourceFrame[message.url];
if (sourceFrame)
sourceFrame.addMessage(message);
},
@@ -333,36 +381,40 @@ WebInspector.ScriptsPanel.prototype = {
clearConsoleMessages: function()
{
this._messages = [];
- for (var url in this._urlToSourceFrame)
- this._urlToSourceFrame[url].clearMessages();
+ for (var url in this._sourceFileIdToSourceFrame)
+ this._sourceFileIdToSourceFrame[url].clearMessages();
},
- selectedCallFrameId: function()
+ _breakpointAdded: function(event)
{
- var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
- if (!selectedCallFrame)
- return null;
- return selectedCallFrame.id;
+ var breakpoint = event.data;
+
+ var sourceFrame = this._sourceFileIdToSourceFrame[breakpoint.sourceFileId];
+ if (sourceFrame && sourceFrame.loaded)
+ sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
},
- evaluateInSelectedCallFrame: function(code, updateInterface, objectGroup, includeCommandLineAPI, callback)
+ _breakpointRemoved: function(event)
{
- var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+ var breakpoint = event.data;
+
+ var sourceFrame = this._sourceFileIdToSourceFrame[breakpoint.sourceFileId];
+ if (sourceFrame && sourceFrame.loaded)
+ sourceFrame.removeBreakpoint(breakpoint.lineNumber);
+ },
+
+ evaluateInSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, callback)
+ {
+ var selectedCallFrame = this._presentationModel.selectedCallFrame;
if (!this._paused || !selectedCallFrame)
return;
- if (typeof updateInterface === "undefined")
- updateInterface = true;
-
function updatingCallbackWrapper(result)
{
- if (result) {
+ if (result)
callback(WebInspector.RemoteObject.fromPayload(result));
- if (updateInterface)
- this.sidebarPanes.scopechain.update(selectedCallFrame);
- }
}
- InspectorBackend.evaluateOnCallFrame(selectedCallFrame.id, code, objectGroup, includeCommandLineAPI, updatingCallbackWrapper.bind(this));
+ DebuggerAgent.evaluateOnCallFrame(selectedCallFrame.id, code, objectGroup, includeCommandLineAPI, updatingCallbackWrapper.bind(this));
},
_debuggerPaused: function(event)
@@ -377,7 +429,7 @@ WebInspector.ScriptsPanel.prototype = {
WebInspector.currentPanel = this;
- this.sidebarPanes.callstack.update(callFrames, event.data.eventType, event.data.eventData);
+ this.sidebarPanes.callstack.update(event.data);
this.sidebarPanes.callstack.selectedCallFrame = callFrames[0];
window.focus();
@@ -386,6 +438,8 @@ WebInspector.ScriptsPanel.prototype = {
_debuggerResumed: function()
{
+ this._presentationModel.selectedCallFrame = null;
+
this._paused = false;
this._waitingToPause = false;
this._stepping = false;
@@ -425,10 +479,10 @@ WebInspector.ScriptsPanel.prototype = {
this._currentBackForwardIndex = -1;
this._updateBackAndForwardButtons();
- this._urlToSourceFrame = {};
+ this._sourceFileIdToSourceFrame = {};
+ this._sourceFileIdToFilesSelectOption = {};
this._messages = [];
- this._resourceForURLInFilesSelect = {};
- this.filesSelectElement.removeChildren();
+ this._filesSelectElement.removeChildren();
this.functionsSelectElement.removeChildren();
this.viewsContainerElement.removeChildren();
@@ -458,35 +512,15 @@ WebInspector.ScriptsPanel.prototype = {
canShowSourceLine: function(url, line)
{
- if (!this._debuggerEnabled)
- return false;
- return !!this._scriptOrResourceForURLAndLine(url, line);
+ return this._debuggerEnabled && (url in this._sourceFileIdToFilesSelectOption);
},
showSourceLine: function(url, line)
{
- var scriptOrResource = this._scriptOrResourceForURLAndLine(url, line);
- this._showScriptOrResource(scriptOrResource, {line: line, shouldHighlightLine: true});
- },
-
- _scriptOrResourceForURLAndLine: function(url, line)
- {
- var scripts = WebInspector.debuggerModel.scriptsForURL(url);
- for (var i = 0; i < scripts.length; ++i) {
- var script = scripts[i];
- if (script.resource)
- return script.resource;
- if (script.startingLine <= line && script.startingLine + script.linesCount > line)
- return script;
- }
- return null;
- },
-
- showView: function(view)
- {
- if (!view)
+ if (!(url in this._sourceFileIdToFilesSelectOption))
return;
- this._showScriptOrResource(view.resource || view.script);
+ var sourceFrame = this._showSourceFrameAndAddToHistory(url);
+ sourceFrame.highlightLine(line);
},
handleShortcut: function(event)
@@ -500,167 +534,114 @@ WebInspector.ScriptsPanel.prototype = {
this.sidebarPanes.callstack.handleShortcut(event);
},
- _sourceFrameForScriptOrResource: function(scriptOrResource)
+ _showSourceFrameAndAddToHistory: function(sourceFileId)
{
- if (scriptOrResource instanceof WebInspector.Resource)
- return this._sourceFrameForResource(scriptOrResource);
- return this._sourceFrameForScript(scriptOrResource);
+ var sourceFrame = this._showSourceFrame(sourceFileId);
+
+ var oldIndex = this._currentBackForwardIndex;
+ if (oldIndex >= 0)
+ this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
+
+ // Check for a previous entry of the same object in _backForwardList.
+ // If one is found, remove it.
+ var previousEntryIndex = this._backForwardList.indexOf(sourceFileId);
+ if (previousEntryIndex !== -1)
+ this._backForwardList.splice(previousEntryIndex, 1);
+
+ this._backForwardList.push(sourceFileId);
+ this._currentBackForwardIndex = this._backForwardList.length - 1;
+
+ this._updateBackAndForwardButtons();
+
+ return sourceFrame;
},
- _sourceFrameForResource: function(resource)
+ _showSourceFrame: function(sourceFileId)
{
- var sourceFrame = this._urlToSourceFrame[resource.url];
- if (sourceFrame)
- return sourceFrame;
- var contentProvider = new WebInspector.SourceFrameContentProviderForResource(resource);
- var isScript = resource.type === WebInspector.Resource.Type.Script;
- sourceFrame = new WebInspector.SourceFrame(contentProvider, resource.url, isScript);
- for (var i = 0; i < this._messages.length; ++i) {
- var message = this._messages[i];
- if (this._messages[i].url === resource.url)
- sourceFrame.addMessage(message);
- }
- this._urlToSourceFrame[resource.url] = sourceFrame;
+ var index = this._sourceFileIdToFilesSelectOption[sourceFileId].index;
+ this._filesSelectElement.selectedIndex = index;
+
+ var sourceFrame = this._sourceFrameForSourceFileId(sourceFileId);
+ this.visibleView = sourceFrame;
+
+ var script = this._scriptForSourceFileId(sourceFileId);
+ if (script.sourceURL)
+ WebInspector.settings.lastViewedScriptFile = script.sourceURL;
+
return sourceFrame;
},
- _sourceFrameForScript: function(script)
+ _sourceFrameForSourceFileId: function(sourceFileId)
{
- if (script._sourceFrame)
- return script._sourceFrame;
- var contentProvider = new WebInspector.SourceFrameContentProviderForScript(script);
- script._sourceFrame = new WebInspector.SourceFrame(contentProvider, script.sourceURL, true);
- return script._sourceFrame;
+ var sourceFrame = this._sourceFileIdToSourceFrame[sourceFileId];
+ return sourceFrame || this._createSourceFrame(sourceFileId);
},
- _showScriptOrResource: function(scriptOrResource, options)
+ _createSourceFrame: function(sourceFileId)
{
- // options = {line:, shouldHighlightLine:, fromBackForwardAction:, initialLoad:}
- options = options || {};
+ var script = this._scriptForSourceFileId(sourceFileId);
+ var delegate = new WebInspector.SourceFrameDelegateForScriptsPanel(script);
+ var sourceFrame = new WebInspector.SourceFrame(delegate, script.sourceURL);
+ sourceFrame._sourceFileId = sourceFileId;
+ sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
+ this._sourceFileIdToSourceFrame[sourceFileId] = sourceFrame;
+ return sourceFrame;
+ },
- if (!scriptOrResource)
+ _recreateSourceFrame: function(sourceFileId)
+ {
+ var oldSourceFrame = this._sourceFileIdToSourceFrame[sourceFileId];
+ if (!oldSourceFrame)
return;
-
- var view = this._sourceFrameForScriptOrResource(scriptOrResource);
- if (!view)
+ oldSourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
+ delete this._sourceFileIdToSourceFrame[sourceFileId];
+ oldSourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
+ if (this.visibleView !== oldSourceFrame)
return;
- var url = scriptOrResource.url || scriptOrResource.sourceURL;
- if (url && !options.initialLoad)
- WebInspector.settings.lastViewedScriptFile = url;
-
- if (!options.fromBackForwardAction) {
- var oldIndex = this._currentBackForwardIndex;
- if (oldIndex >= 0)
- this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
-
- // Check for a previous entry of the same object in _backForwardList.
- // If one is found, remove it and update _currentBackForwardIndex to match.
- var previousEntryIndex = this._backForwardList.indexOf(scriptOrResource);
- if (previousEntryIndex !== -1) {
- this._backForwardList.splice(previousEntryIndex, 1);
- --this._currentBackForwardIndex;
- }
+ var newSourceFrame = this._createSourceFrame(sourceFileId)
+ newSourceFrame.scrollTop = oldSourceFrame.scrollTop;
+ this.visibleView = newSourceFrame;
+ },
- this._backForwardList.push(scriptOrResource);
- ++this._currentBackForwardIndex;
+ _sourceFrameLoaded: function(event)
+ {
+ var sourceFrame = event.target;
+ var sourceFileId = sourceFrame._sourceFileId;
- this._updateBackAndForwardButtons();
+ for (var i = 0; i < this._messages.length; ++i) {
+ var message = this._messages[i];
+ if (message.url === sourceFileId)
+ sourceFrame.addMessage(message);
}
- this.visibleView = view;
-
- if (options.line) {
- if (view.revealLine)
- view.revealLine(options.line);
- if (view.highlightLine && options.shouldHighlightLine)
- view.highlightLine(options.line);
+ var breakpoints = this._presentationModel.breakpointsForSourceFileId(sourceFileId);
+ for (var i = 0; i < breakpoints.length; ++i) {
+ var breakpoint = breakpoints[i];
+ sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
}
- var option;
- if (scriptOrResource instanceof WebInspector.Script) {
- option = scriptOrResource.filesSelectOption;
-
- // hasn't been added yet - happens for stepping in evals,
- // so use the force option to force the script into the menu.
- if (!option) {
- this._addScriptToFilesMenu(scriptOrResource, true);
- option = scriptOrResource.filesSelectOption;
+ var selectedCallFrame = this._presentationModel.selectedCallFrame;
+ if (selectedCallFrame) {
+ if (selectedCallFrame.sourceLocation.sourceFileId === sourceFileId) {
+ sourceFrame.setExecutionLine(selectedCallFrame.sourceLocation.lineNumber);
+ this._executionSourceFrame = sourceFrame;
}
-
- console.assert(option);
- } else
- option = scriptOrResource.filesSelectOption;
-
- if (option)
- this.filesSelectElement.selectedIndex = option.index;
+ }
},
- _addScriptToFilesMenu: function(script, force)
+ _sourceFileIdForScript: function(script)
{
- if (!script.sourceURL && !force)
- return;
-
- if (script.resource) {
- if (this._resourceForURLInFilesSelect[script.resource.url])
- return;
- this._resourceForURLInFilesSelect[script.resource.url] = script.resource;
- }
-
- var displayName = script.sourceURL ? WebInspector.displayNameForURL(script.sourceURL) : WebInspector.UIString("(program)");
-
- var select = this.filesSelectElement;
- var option = document.createElement("option");
- option.representedObject = script.resource || script;
- option.url = displayName;
- option.startingLine = script.startingLine;
- option.text = script.resource || script.startingLine === 1 ? displayName : String.sprintf("%s:%d", displayName, script.startingLine);
+ return script.sourceURL || script.sourceID;
+ },
- function optionCompare(a, b)
+ _scriptForSourceFileId: function(sourceFileId)
+ {
+ function filter(script)
{
- if (a.url < b.url)
- return -1;
- else if (a.url > b.url)
- return 1;
-
- if (typeof a.startingLine !== "number")
- return -1;
- if (typeof b.startingLine !== "number")
- return -1;
- return a.startingLine - b.startingLine;
- }
-
- var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
- if (insertionIndex < 0)
- select.appendChild(option);
- else
- select.insertBefore(option, select.childNodes.item(insertionIndex));
-
- if (script.resource)
- script.resource.filesSelectOption = option;
- else
- script.filesSelectOption = option;
-
- if (select.options[select.selectedIndex] === option) {
- // Call _showScriptOrResource if the option we just appended ended up being selected.
- // This will happen for the first item added to the menu.
- this._showScriptOrResource(option.representedObject, {initialLoad: true});
- } else {
- // If not first item, check to see if this was the last viewed
- var url = option.representedObject.url || option.representedObject.sourceURL;
- var lastURL = WebInspector.settings.lastViewedScriptFile;
- if (url && url === lastURL) {
- // For resources containing multiple <script> tags, we first report them separately and
- // then glue them all together. They all share url and there is no need to show them all one
- // by one.
- var isResource = !!option.representedObject.url;
- if (isResource || !this.visibleView || !this.visibleView.script || this.visibleView.script.sourceURL !== url)
- this._showScriptOrResource(option.representedObject, {initialLoad: true});
- }
+ return (script.sourceURL || script.sourceID) === sourceFileId;
}
-
- if (script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD)
- script.filesSelectOption.addStyleClass("extension-script");
+ return WebInspector.debuggerModel.queryScripts(filter)[0];
},
_clearCurrentExecutionLine: function()
@@ -670,31 +651,36 @@ WebInspector.ScriptsPanel.prototype = {
delete this._executionSourceFrame;
},
- _callFrameSelected: function()
+ _callFrameSelected: function(event)
{
+ var callFrame = event.data;
+
this._clearCurrentExecutionLine();
- var callStackPane = this.sidebarPanes.callstack;
- var currentFrame = callStackPane.selectedCallFrame;
- if (!currentFrame)
+ if (!callFrame)
return;
- this.sidebarPanes.scopechain.update(currentFrame);
+ this.sidebarPanes.scopechain.update(callFrame);
this.sidebarPanes.watchExpressions.refreshExpressions();
- var script = WebInspector.debuggerModel.scriptForSourceID(currentFrame.sourceID);
- var scriptOrResource = script.resource || script;
- this._showScriptOrResource(scriptOrResource, {line: currentFrame.line});
-
- this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource);
- if (this._executionSourceFrame)
- this._executionSourceFrame.setExecutionLine(currentFrame.line);
+ var sourceFileId = callFrame.sourceLocation.sourceFileId;
+ if (!(sourceFileId in this._sourceFileIdToFilesSelectOption)) {
+ // This happens in two cases:
+ // 1) Current call frame function is defined in anonymous script (anonymous scripts aren't added to files select by default)
+ // 2) We are debugging synchronously executed inlined script and there is no resource so far
+ this._addOptionToFilesSelect(sourceFileId);
+ }
+ var sourceFrame = this._showSourceFrameAndAddToHistory(sourceFileId);
+ if (sourceFrame.loaded) {
+ sourceFrame.setExecutionLine(callFrame.sourceLocation.lineNumber);
+ this._executionSourceFrame = sourceFrame;
+ }
},
- _changeVisibleFile: function(event)
+ _filesSelectChanged: function()
{
- var select = this.filesSelectElement;
- this._showScriptOrResource(select.options[select.selectedIndex].representedObject);
+ var sourceFileId = this._filesSelectElement[this._filesSelectElement.selectedIndex]._sourceFileId;
+ this._showSourceFrameAndAddToHistory(sourceFileId);
},
_startSidebarResizeDrag: function(event)
@@ -747,7 +733,7 @@ WebInspector.ScriptsPanel.prototype = {
this._pauseOnExceptionButton.state = pauseOnExceptionsState;
WebInspector.settings.pauseOnExceptionState = pauseOnExceptionsState;
}
- InspectorBackend.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this));
+ DebuggerAgent.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this));
},
_updateDebuggerButtons: function()
@@ -812,7 +798,7 @@ WebInspector.ScriptsPanel.prototype = {
return;
}
- this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], {fromBackForwardAction: true});
+ this._showSourceFrame(this._backForwardList[--this._currentBackForwardIndex]);
this._updateBackAndForwardButtons();
},
@@ -823,7 +809,7 @@ WebInspector.ScriptsPanel.prototype = {
return;
}
- this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], {fromBackForwardAction: true});
+ this._showSourceFrame(this._backForwardList[++this._currentBackForwardIndex]);
this._updateBackAndForwardButtons();
},
@@ -865,11 +851,11 @@ WebInspector.ScriptsPanel.prototype = {
if (this._paused) {
this._paused = false;
this._waitingToPause = false;
- InspectorBackend.resume();
+ DebuggerAgent.resume();
} else {
this._stepping = false;
this._waitingToPause = true;
- InspectorBackend.pause();
+ DebuggerAgent.pause();
}
this._clearInterface();
@@ -882,7 +868,7 @@ WebInspector.ScriptsPanel.prototype = {
this._clearInterface();
- InspectorBackend.stepOver();
+ DebuggerAgent.stepOver();
},
_stepIntoClicked: function()
@@ -892,7 +878,7 @@ WebInspector.ScriptsPanel.prototype = {
this._clearInterface();
- InspectorBackend.stepInto();
+ DebuggerAgent.stepInto();
},
_stepOutClicked: function()
@@ -902,18 +888,18 @@ WebInspector.ScriptsPanel.prototype = {
this._clearInterface();
- InspectorBackend.stepOut();
+ DebuggerAgent.stepOut();
},
toggleBreakpointsClicked: function()
{
this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
if (this.toggleBreakpointsButton.toggled) {
- InspectorBackend.activateBreakpoints();
+ DebuggerAgent.activateBreakpoints();
this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
} else {
- InspectorBackend.deactivateBreakpoints();
+ DebuggerAgent.deactivateBreakpoints();
this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
}
@@ -976,8 +962,6 @@ WebInspector.ScriptsPanel.prototype = {
searchCanceled: function()
{
- WebInspector.updateSearchMatchesCount(0, this);
-
if (this._searchView)
this._searchView.searchCanceled();
@@ -987,6 +971,8 @@ WebInspector.ScriptsPanel.prototype = {
performSearch: function(query)
{
+ WebInspector.searchController.updateSearchMatchesCount(0, this);
+
if (!this.visibleView)
return;
@@ -1001,7 +987,7 @@ WebInspector.ScriptsPanel.prototype = {
if (!searchMatches)
return;
- WebInspector.updateSearchMatchesCount(searchMatches, this);
+ WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
view.jumpToFirstSearchResult();
}
@@ -1053,39 +1039,205 @@ WebInspector.ScriptsPanel.prototype = {
WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.SourceFrameContentProviderForScript = function(script)
+WebInspector.SourceFrameDelegateForScriptsPanel = function(script)
{
- WebInspector.SourceFrameContentProvider.call(this);
+ WebInspector.SourceFrameDelegate.call(this);
this._script = script;
+ this._popoverObjectGroup = "popover";
}
-WebInspector.SourceFrameContentProviderForScript.prototype = {
+WebInspector.SourceFrameDelegateForScriptsPanel.prototype = {
requestContent: function(callback)
{
- if (this._script.source) {
- callback("text/javascript", this._script.source);
+ function didGetTextAndScriptRanges(mimeType, text, scriptRanges)
+ {
+ this._content = new WebInspector.SourceFrameContent(text, new WebInspector.IdenticalSourceMapping(), scriptRanges);
+ callback(mimeType, this._content);
+ }
+
+ if (this._script.resource)
+ this._loadResourceContent(this._script.resource, didGetTextAndScriptRanges.bind(this));
+ else
+ this._loadAndConcatenateScriptsContent(didGetTextAndScriptRanges.bind(this));
+ },
+
+ _loadResourceContent: function(resource, callback)
+ {
+ function didRequestContent(text)
+ {
+ var mimeType = "text/javascript";
+ if (resource.type !== WebInspector.Resource.Type.Script) {
+ mimeType = "text/html";
+ // WebKit html lexer normalizes line endings and scripts are passed to VM with "\n" line endings.
+ // However, resource content has original line endings, so we have to normalize line endings here.
+ text = text.replace(/\r\n/g, "\n");
+ }
+ var scripts = this._scripts();
+ var scriptRanges = WebInspector.ScriptFormatter.findScriptRanges(text.lineEndings(), scripts);
+ callback(mimeType, text, scriptRanges);
+ }
+ resource.requestContent(didRequestContent.bind(this));
+ },
+
+ _loadAndConcatenateScriptsContent: function(callback)
+ {
+ var scripts = this._scripts();
+ var scriptsLeft = scripts.length;
+ var sources = [];
+ function didRequestSource(index, source)
+ {
+ sources[index] = source;
+ if (--scriptsLeft)
+ return;
+ var result = this._buildSource(scripts, sources);
+ callback(result.mimeType, result.source, result.scriptRanges);
+ }
+ for (var i = 0; i < scripts.length; ++i)
+ scripts[i].requestSource(didRequestSource.bind(this, i));
+ },
+
+ _buildSource: function(scripts, sources)
+ {
+ var source = "";
+ var lineNumber = 0;
+ var columnNumber = 0;
+ var scriptRanges = [];
+ function appendChunk(chunk, script)
+ {
+ var start = { lineNumber: lineNumber, columnNumber: columnNumber };
+ source += chunk;
+ var lineEndings = chunk.lineEndings();
+ var lineCount = lineEndings.length;
+ if (lineCount === 1)
+ columnNumber += chunk.length;
+ else {
+ lineNumber += lineCount - 1;
+ columnNumber = lineEndings[lineCount - 1] - lineEndings[lineCount - 2] - 1;
+ }
+ var end = { lineNumber: lineNumber, columnNumber: columnNumber };
+ if (script)
+ scriptRanges.push({ start: start, end: end, sourceID: script.sourceID });
+ }
+
+ var mimeType;
+ if (scripts.length === 1 && !scripts[0].lineOffset && !scripts[0].columnOffset) {
+ // Single script source.
+ mimeType = "text/javascript";
+ appendChunk(sources[0], scripts[0]);
+ } else {
+ // Scripts inlined in html document.
+ mimeType = "text/html";
+ var scriptOpenTag = "<script>";
+ var scriptCloseTag = "</script>";
+ for (var i = 0; i < scripts.length; ++i) {
+ // Fill the gap with whitespace characters.
+ while (lineNumber < scripts[i].lineOffset)
+ appendChunk("\n");
+ while (columnNumber < scripts[i].columnOffset - scriptOpenTag.length)
+ appendChunk(" ");
+
+ // Add script tag.
+ appendChunk(scriptOpenTag);
+ appendChunk(sources[i], scripts[i]);
+ appendChunk(scriptCloseTag);
+ }
+ }
+ return { mimeType: mimeType, source: source, scriptRanges: scriptRanges };
+ },
+
+ _scripts: function()
+ {
+ var scripts = [this._script];
+ if (this._script.sourceURL)
+ scripts = WebInspector.debuggerModel.scriptsForURL(this._script.sourceURL);
+ scripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; });
+ return scripts;
+ },
+
+ debuggingSupported: function()
+ {
+ return true;
+ },
+
+ setBreakpoint: function(lineNumber, condition, enabled)
+ {
+ var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+ if (this._script.sourceURL)
+ WebInspector.debuggerModel.setBreakpoint(this._script.sourceURL, location.lineNumber, location.columnNumber, condition, enabled);
+ else if (location.sourceID)
+ WebInspector.debuggerModel.setBreakpointBySourceId(location.sourceID, location.lineNumber, location.columnNumber, condition, enabled);
+ else
return;
+
+ if (!WebInspector.panels.scripts.breakpointsActivated)
+ WebInspector.panels.scripts.toggleBreakpointsClicked();
+ },
+
+ removeBreakpoint: function(breakpointId)
+ {
+ WebInspector.debuggerModel.removeBreakpoint(breakpointId);
+ },
+
+ updateBreakpoint: function(breakpointId, condition, enabled)
+ {
+ WebInspector.debuggerModel.updateBreakpoint(breakpointId, condition, enabled);
+ },
+
+ findBreakpoint: function(lineNumber)
+ {
+ var url = this._script.sourceURL;
+ var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+ function filter(breakpoint)
+ {
+ if (breakpoint.url) {
+ if (breakpoint.url !== url)
+ return false;
+ } else {
+ if (breakpoint.sourceID !== location.sourceID)
+ return false;
+ }
+ var lineNumber = breakpoint.locations.length ? breakpoint.locations[0].lineNumber : breakpoint.lineNumber;
+ return lineNumber === location.lineNumber;
}
+ return WebInspector.debuggerModel.queryBreakpoints(filter)[0];
+ },
+
+ continueToLine: function(lineNumber)
+ {
+ var location = this._content.sourceFrameLineNumberToActualLocation(lineNumber);
+ if (location.sourceID)
+ WebInspector.debuggerModel.continueToLocation(location.sourceID, location.lineNumber, location.columnNumber);
+ },
- function didRequestSource(content)
+ canEditScriptSource: function()
+ {
+ return Preferences.canEditScriptSource && !this._script.lineOffset && !this._script.columnOffset;
+ },
+
+ editScriptSource: function(text)
+ {
+ WebInspector.debuggerModel.editScriptSource(this._script.sourceID, text);
+ },
+
+ debuggerPaused: function()
+ {
+ return WebInspector.panels.scripts.paused;
+ },
+
+ evaluateInSelectedCallFrame: function(string, callback)
+ {
+ function didEvaluateInSelectedCallFrame(result)
{
- var source;
- if (content) {
- var prefix = "";
- for (var i = 0; i < this._script.startingLine - 1; ++i)
- prefix += "\n";
- source = prefix + content;
- } else
- source = WebInspector.UIString("<source is not available>");
- callback("text/javascript", source);
+ if (!result.isError() && this.debuggerPaused())
+ callback(result);
}
- this._script.requestSource(didRequestSource.bind(this));
+ WebInspector.panels.scripts.evaluateInSelectedCallFrame(string, this._popoverObjectGroup, false, didEvaluateInSelectedCallFrame.bind(this));
},
- scripts: function()
+ releaseEvaluationResult: function()
{
- return [this._script];
+ RuntimeAgent.releaseObjectGroup(0, this._popoverObjectGroup);
}
}
-WebInspector.SourceFrameContentProviderForScript.prototype.__proto__ = WebInspector.SourceFrameContentProvider.prototype;
+WebInspector.SourceFrameDelegateForScriptsPanel.prototype.__proto__ = WebInspector.SourceFrameDelegate.prototype;
diff --git a/Source/WebCore/inspector/front-end/SearchController.js b/Source/WebCore/inspector/front-end/SearchController.js
new file mode 100755
index 0000000..735c424
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/SearchController.js
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ * Copyright (C) 2009 Joseph Pecoraro
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SearchController = function()
+{
+ this.element = document.getElementById("search");
+ this._matchesElement = document.getElementById("search-results-matches");
+ this._toolbarLabelElement = document.getElementById("search-toolbar-label");
+
+ this.element.addEventListener("search", this._onSearch.bind(this), false); // when the search is emptied
+ this.element.addEventListener("mousedown", this._onSearchFieldManualFocus.bind(this), false); // when the search field is manually selected
+ this.element.addEventListener("keydown", this._onKeyDown.bind(this), true);
+}
+
+WebInspector.SearchController.prototype = {
+ updateSearchMatchesCount: function(matches, panel)
+ {
+ if (!panel)
+ panel = WebInspector.currentPanel;
+
+ panel.currentSearchMatches = matches;
+
+ if (panel === WebInspector.currentPanel)
+ this._updateSearchMatchesCount(WebInspector.currentPanel.currentQuery && matches);
+ },
+
+ updateSearchLabel: function()
+ {
+ var panelName = WebInspector.currentPanel && WebInspector.currentPanel.toolbarItemLabel;
+ if (!panelName)
+ return;
+ var newLabel = WebInspector.UIString("Search %s", panelName);
+ if (WebInspector.attached)
+ this.element.setAttribute("placeholder", newLabel);
+ else {
+ this.element.removeAttribute("placeholder");
+ this._toolbarLabelElement.textContent = newLabel;
+ }
+ },
+
+ cancelSearch: function()
+ {
+ this.element.value = "";
+ this._performSearch("");
+ },
+
+ handleShortcut: function(event)
+ {
+ var isMac = WebInspector.isMac();
+
+ switch (event.keyIdentifier) {
+ case "U+0046": // F key
+ if (isMac)
+ var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
+ else
+ var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
+
+ if (isFindKey) {
+ this._focusSearchField();
+ event.handled = true;
+ }
+ break;
+
+
+ case "F3":
+ if (!isMac) {
+ this._focusSearchField();
+ event.handled = true;
+ }
+ break;
+
+ case "U+0047": // G key
+ var currentPanel = WebInspector.currentPanel;
+
+ if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) {
+ if (event.shiftKey) {
+ if (currentPanel.jumpToPreviousSearchResult)
+ currentPanel.jumpToPreviousSearchResult();
+ } else if (currentPanel.jumpToNextSearchResult)
+ currentPanel.jumpToNextSearchResult();
+ event.handled = true;
+ }
+ break;
+ }
+ },
+
+ activePanelChanged: function()
+ {
+ this.updateSearchLabel();
+
+ if (!this._currentQuery)
+ return;
+
+ panel = WebInspector.currentPanel;
+ if (panel.performSearch) {
+ function performPanelSearch()
+ {
+ this._updateSearchMatchesCount();
+
+ panel.currentQuery = this._currentQuery;
+ panel.performSearch(this._currentQuery);
+ }
+
+ // Perform the search on a timeout so the panel switches fast.
+ setTimeout(performPanelSearch.bind(this), 0);
+ } else {
+ // Update to show Not found for panels that can't be searched.
+ this._updateSearchMatchesCount();
+ }
+ },
+
+ _updateSearchMatchesCount: function(matches)
+ {
+ if (matches == null) {
+ this._matchesElement.addStyleClass("hidden");
+ return;
+ }
+
+ if (matches) {
+ if (matches === 1)
+ var matchesString = WebInspector.UIString("1 match");
+ else
+ var matchesString = WebInspector.UIString("%d matches", matches);
+ } else
+ var matchesString = WebInspector.UIString("Not Found");
+
+ this._matchesElement.removeStyleClass("hidden");
+ this._matchesElement.textContent = matchesString;
+ WebInspector.toolbar.resize();
+ },
+
+ _focusSearchField: function()
+ {
+ this.element.focus();
+ this.element.select();
+ },
+
+ _onSearchFieldManualFocus: function(event)
+ {
+ WebInspector.currentFocusElement = event.target;
+ },
+
+ _onKeyDown: function(event)
+ {
+ // Escape Key will clear the field and clear the search results
+ if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
+ // If focus belongs here and text is empty - nothing to do, return unhandled.
+ // When search was selected manually and is currently blank, we'd like Esc stay unhandled
+ // and hit console drawer handler.
+ if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
+ return;
+ event.preventDefault();
+ event.stopPropagation();
+
+ this.cancelSearch(event);
+ WebInspector.currentFocusElement = WebInspector.previousFocusElement;
+ if (WebInspector.currentFocusElement === event.target)
+ WebInspector.currentFocusElement.currentFocusElement.select();
+ return false;
+ }
+
+ if (!isEnterKey(event))
+ return false;
+
+ // Select all of the text so the user can easily type an entirely new query.
+ event.target.select();
+
+ // Only call performSearch if the Enter key was pressed. Otherwise the search
+ // performance is poor because of searching on every key. The search field has
+ // the incremental attribute set, so we still get incremental searches.
+ this._onSearch(event);
+
+ // Call preventDefault since this was the Enter key. This prevents a "search" event
+ // from firing for key down. This stops performSearch from being called twice in a row.
+ event.preventDefault();
+ },
+
+ _onSearch: function(event)
+ {
+ var forceSearch = event.keyIdentifier === "Enter";
+ this._performSearch(event.target.value, forceSearch, event.shiftKey, false);
+ },
+
+ _performSearch: function(query, forceSearch, isBackwardSearch, repeatSearch)
+ {
+ var isShortSearch = (query.length < 3);
+
+ // Clear a leftover short search flag due to a non-conflicting forced search.
+ if (isShortSearch && this._shortSearchWasForcedByKeyEvent && this._currentQuery !== query)
+ delete this._shortSearchWasForcedByKeyEvent;
+
+ // Indicate this was a forced search on a short query.
+ if (isShortSearch && forceSearch)
+ this._shortSearchWasForcedByKeyEvent = true;
+
+ if (!query || !query.length || (!forceSearch && isShortSearch)) {
+ // Prevent clobbering a short search forced by the user.
+ if (this._shortSearchWasForcedByKeyEvent) {
+ delete this._shortSearchWasForcedByKeyEvent;
+ return;
+ }
+
+ delete this._currentQuery;
+
+ for (var panelName in WebInspector.panels) {
+ var panel = WebInspector.panels[panelName];
+ var hadCurrentQuery = !!panel.currentQuery;
+ delete panel.currentQuery;
+ if (hadCurrentQuery && panel.searchCanceled)
+ panel.searchCanceled();
+ }
+
+ this._updateSearchMatchesCount();
+
+ return;
+ }
+
+ var currentPanel = WebInspector.currentPanel;
+ if (!repeatSearch && query === currentPanel.currentQuery && currentPanel.currentQuery === this._currentQuery) {
+ // When this is the same query and a forced search, jump to the next
+ // search result for a good user experience.
+ if (forceSearch) {
+ if (!isBackwardSearch && currentPanel.jumpToNextSearchResult)
+ currentPanel.jumpToNextSearchResult();
+ else if (isBackwardSearch && currentPanel.jumpToPreviousSearchResult)
+ currentPanel.jumpToPreviousSearchResult();
+ }
+ return;
+ }
+
+ this._currentQuery = query;
+
+ this._updateSearchMatchesCount();
+
+ if (!currentPanel.performSearch)
+ return;
+
+ currentPanel.currentQuery = query;
+ currentPanel.performSearch(query);
+ }
+}
diff --git a/Source/WebCore/inspector/front-end/SourceFrame.js b/Source/WebCore/inspector/front-end/SourceFrame.js
index f2e0be1..3120159 100644
--- a/Source/WebCore/inspector/front-end/SourceFrame.js
+++ b/Source/WebCore/inspector/front-end/SourceFrame.js
@@ -28,15 +28,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.SourceFrame = function(contentProvider, url, isScript)
+WebInspector.SourceFrame = function(delegate, url)
{
WebInspector.View.call(this);
this.element.addStyleClass("script-view");
- this._contentProvider = contentProvider;
+ this._delegate = delegate;
this._url = url;
- this._isScript = isScript;
this._textModel = new WebInspector.TextEditorModel();
this._textModel.replaceTabsWithSpaces = true;
@@ -47,8 +46,10 @@ WebInspector.SourceFrame = function(contentProvider, url, isScript)
this._messages = [];
this._rowMessages = {};
this._messageBubbles = {};
+}
- this._popoverObjectGroup = "popover";
+WebInspector.SourceFrame.Events = {
+ Loaded: "loaded"
}
WebInspector.SourceFrame.prototype = {
@@ -59,7 +60,7 @@ WebInspector.SourceFrame.prototype = {
if (!this._contentRequested) {
this._contentRequested = true;
- this._contentProvider.requestContent(this._createTextViewer.bind(this));
+ this._delegate.requestContent(this._createTextViewer.bind(this));
}
if (this._textViewer) {
@@ -85,6 +86,11 @@ WebInspector.SourceFrame.prototype = {
this._clearLineHighlight();
},
+ get loaded()
+ {
+ return !!this._content;
+ },
+
hasContent: function()
{
return true;
@@ -132,12 +138,6 @@ WebInspector.SourceFrame.prototype = {
this._textViewer.resize();
},
- sizeToFitContentHeight: function()
- {
- if (this._textViewer)
- this._textViewer.revalidateDecorationsAndPaint();
- },
-
get textModel()
{
return this._textModel;
@@ -171,18 +171,34 @@ WebInspector.SourceFrame.prototype = {
delete this._lineToHighlight;
},
- _createTextViewer: function(mimeType, text)
+ _startEditing: function()
{
- this._content = new WebInspector.SourceFrameContent(text, this._contentProvider.scripts());
- this._textModel.setText(null, text);
+ WebInspector.searchController.cancelSearch();
+ this.clearMessages();
+ },
+
+ _endEditing: function(oldRange, newRange)
+ {
+ // FIXME: Implement this.
+ },
+
+ _createTextViewer: function(mimeType, content)
+ {
+ this._content = content;
+ this._textModel.setText(null, content.text);
this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url);
+ this._textViewer.startEditingListener = this._startEditing.bind(this);
+ this._textViewer.endEditingListener = this._endEditing.bind(this);
+
var element = this._textViewer.element;
- element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
- element.addEventListener("mousedown", this._mouseDown.bind(this), true);
- element.addEventListener("mousemove", this._mouseMove.bind(this), true);
- element.addEventListener("scroll", this._scroll.bind(this), true);
- element.addEventListener("dblclick", this._doubleClick.bind(this), true);
+ if (this._delegate.debuggingSupported()) {
+ element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
+ element.addEventListener("mousedown", this._mouseDown.bind(this), true);
+ element.addEventListener("mousemove", this._mouseMove.bind(this), true);
+ element.addEventListener("dblclick", this._doubleClick.bind(this), true);
+ element.addEventListener("scroll", this._scroll.bind(this), true);
+ }
this.element.appendChild(element);
this._textViewer.beginUpdates();
@@ -205,11 +221,9 @@ WebInspector.SourceFrame.prototype = {
delete this._delayedFindSearchMatches;
}
- this._textViewer.endUpdates();
+ this.dispatchEventToListeners(WebInspector.SourceFrame.Events.Loaded);
- WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
- WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
- WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
+ this._textViewer.endUpdates();
},
_setTextViewerDecorations: function()
@@ -222,32 +236,11 @@ WebInspector.SourceFrame.prototype = {
this._addExistingMessagesToSource();
this._updateDiffDecorations();
- if (this._executionLine)
- this.setExecutionLine(this._executionLine);
-
- this._breakpointIdToTextViewerLineNumber = {};
- this._textViewerLineNumberToBreakpointId = {};
- var breakpoints = WebInspector.debuggerModel.breakpoints;
- for (var id in breakpoints)
- this._breakpointAdded({ data: breakpoints[id] });
-
this._textViewer.resize();
this._textViewer.endUpdates();
},
- _shouldDisplayBreakpoint: function(breakpoint)
- {
- if (this._url)
- return this._url === breakpoint.url;
- var scripts = this._contentProvider.scripts();
- for (var i = 0; i < scripts.length; ++i) {
- if (breakpoint.sourceID === scripts[i].sourceID)
- return true;
- }
- return false;
- },
-
performSearch: function(query, callback)
{
// Call searchCanceled since it will reset everything we need before doing a new search.
@@ -363,20 +356,15 @@ WebInspector.SourceFrame.prototype = {
setExecutionLine: function(lineNumber)
{
- this._executionLine = lineNumber;
- if (!this._textViewer)
- return;
- var textViewerLineNumber = this._originalLocationToTextViewerLineNumber(this._executionLine - 1, 0);
- this._textViewer.addDecoration(textViewerLineNumber, "webkit-execution-line");
+ this._executionLineNumber = lineNumber;
+ this._textViewer.addDecoration(lineNumber, "webkit-execution-line");
+ this._textViewer.revealLine(lineNumber);
},
clearExecutionLine: function()
{
- if (!this._textViewer)
- return;
- var textViewerLineNumber = this._originalLocationToTextViewerLineNumber(this._executionLine - 1, 0);
- this._textViewer.removeDecoration(textViewerLineNumber, "webkit-execution-line");
- delete this._executionLine;
+ this._textViewer.removeDecoration(this._executionLineNumber, "webkit-execution-line");
+ delete this._executionLineNumber;
},
_updateDiffDecorations: function()
@@ -467,63 +455,18 @@ WebInspector.SourceFrame.prototype = {
msg._resourceMessageLineElement = messageLineElement;
},
- _breakpointAdded: function(event)
- {
- var breakpoint = event.data;
-
- if (!this._shouldDisplayBreakpoint(breakpoint))
- return;
-
- var resolved = breakpoint.locations.length;
- var location = resolved ? breakpoint.locations[0] : breakpoint;
-
- var textViewerLineNumber = this._originalLocationToTextViewerLineNumber(location.lineNumber, location.columnNumber);
- if (textViewerLineNumber >= this._textModel.linesCount)
- return;
-
- var existingBreakpointId = this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
- if (existingBreakpointId) {
- WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
- return;
- }
-
- this._breakpointIdToTextViewerLineNumber[breakpoint.id] = textViewerLineNumber;
- this._textViewerLineNumberToBreakpointId[textViewerLineNumber] = breakpoint.id;
- this._setBreakpointDecoration(textViewerLineNumber, resolved, breakpoint.enabled, !!breakpoint.condition);
- },
-
- _breakpointRemoved: function(event)
- {
- var breakpointId = event.data;
-
- var textViewerLineNumber = this._breakpointIdToTextViewerLineNumber[breakpointId];
- if (textViewerLineNumber === undefined)
- return;
-
- delete this._breakpointIdToTextViewerLineNumber[breakpointId];
- delete this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
- this._removeBreakpointDecoration(textViewerLineNumber);
- },
-
- _breakpointResolved: function(event)
- {
- var breakpoint = event.data;
- this._breakpointRemoved({ data: breakpoint.id });
- this._breakpointAdded({ data: breakpoint });
- },
-
- _setBreakpointDecoration: function(lineNumber, resolved, enabled, hasCondition)
+ addBreakpoint: function(lineNumber, resolved, conditional, enabled)
{
this._textViewer.beginUpdates();
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint");
if (!enabled)
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
- if (hasCondition)
+ if (conditional)
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional");
this._textViewer.endUpdates();
},
- _removeBreakpointDecoration: function(lineNumber)
+ removeBreakpoint: function(lineNumber)
{
this._textViewer.beginUpdates();
this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint");
@@ -534,55 +477,48 @@ WebInspector.SourceFrame.prototype = {
_contextMenu: function(event)
{
- if (!WebInspector.panels.scripts)
- return;
-
var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
if (!target)
return;
- var textViewerLineNumber = target.lineNumber;
+ var lineNumber = target.lineNumber;
var contextMenu = new WebInspector.ContextMenu();
- contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._continueToLine.bind(this, textViewerLineNumber));
+ contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._delegate.continueToLine.bind(this._delegate, lineNumber));
- var breakpoint = this._findBreakpoint(textViewerLineNumber);
+ var breakpoint = this._delegate.findBreakpoint(lineNumber);
if (!breakpoint) {
// This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint.
- contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this._setBreakpoint.bind(this, textViewerLineNumber, "", true));
+ contextMenu.appendItem(WebInspector.UIString("Add Breakpoint"), this._delegate.setBreakpoint.bind(this._delegate, lineNumber, "", true));
function addConditionalBreakpoint()
{
- this._setBreakpointDecoration(textViewerLineNumber, true, true, true);
+ this.addBreakpoint(lineNumber, true, true, true);
function didEditBreakpointCondition(committed, condition)
{
- this._removeBreakpointDecoration(textViewerLineNumber);
+ this.removeBreakpoint(lineNumber);
if (committed)
- this._setBreakpoint(textViewerLineNumber, condition, true);
+ this._delegate.setBreakpoint(lineNumber, condition, true);
}
- this._editBreakpointCondition(textViewerLineNumber, "", didEditBreakpointCondition.bind(this));
+ this._editBreakpointCondition(lineNumber, "", didEditBreakpointCondition.bind(this));
}
contextMenu.appendItem(WebInspector.UIString("Add Conditional Breakpoint…"), addConditionalBreakpoint.bind(this));
} else {
// This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable.
- function removeBreakpoint()
- {
- WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
- }
- contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint);
+ contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), this._delegate.removeBreakpoint.bind(this._delegate, breakpoint.id));
function editBreakpointCondition()
{
function didEditBreakpointCondition(committed, condition)
{
if (committed)
- WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, condition, breakpoint.enabled);
+ this._delegate.updateBreakpoint(breakpoint.id, condition, breakpoint.enabled);
}
- this._editBreakpointCondition(textViewerLineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this));
+ this._editBreakpointCondition(lineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this));
}
contextMenu.appendItem(WebInspector.UIString("Edit Breakpoint…"), editBreakpointCondition.bind(this));
function setBreakpointEnabled(enabled)
{
- WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, breakpoint.condition, enabled);
+ this._delegate.updateBreakpoint(breakpoint.id, breakpoint.condition, enabled);
}
if (breakpoint.enabled)
contextMenu.appendItem(WebInspector.UIString("Disable Breakpoint"), setBreakpointEnabled.bind(this, false));
@@ -606,16 +542,16 @@ WebInspector.SourceFrame.prototype = {
var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
if (!target)
return;
- var textViewerLineNumber = target.lineNumber;
+ var lineNumber = target.lineNumber;
- var breakpoint = this._findBreakpoint(textViewerLineNumber);
+ var breakpoint = this._delegate.findBreakpoint(lineNumber);
if (breakpoint) {
if (event.shiftKey)
- WebInspector.debuggerModel.updateBreakpoint(breakpoint.id, breakpoint.condition, !breakpoint.enabled);
+ this._delegate.updateBreakpoint(breakpoint.id, breakpoint.condition, !breakpoint.enabled);
else
- WebInspector.debuggerModel.removeBreakpoint(breakpoint.id);
+ this._delegate.removeBreakpoint(breakpoint.id);
} else
- this._setBreakpoint(textViewerLineNumber, "", true);
+ this._delegate.setBreakpoint(lineNumber, "", true);
event.preventDefault();
},
@@ -641,7 +577,7 @@ WebInspector.SourceFrame.prototype = {
this._hoverElement = event.target;
// Now that cleanup routines are set up above, leave this in case we are not on a break.
- if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
+ if (!this._delegate.debuggerPaused())
return;
// We are interested in identifiers and "this" keyword.
@@ -680,16 +616,13 @@ WebInspector.SourceFrame.prototype = {
this._popup.hide();
delete this._popup;
- InspectorBackend.releaseWrapperObjectGroup(0, this._popoverObjectGroup);
+ this._delegate.releaseEvaluationResult();
},
_mouseHover: function(element)
{
delete this._hoverTimer;
- if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
- return;
-
var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineRow)
return;
@@ -729,9 +662,6 @@ WebInspector.SourceFrame.prototype = {
function showObjectPopup(result)
{
- if (!WebInspector.panels.scripts.paused)
- return;
-
var popupContentElement = null;
if (result.type !== "object" && result.type !== "node" && result.type !== "array") {
popupContentElement = document.createElement("span");
@@ -766,15 +696,7 @@ WebInspector.SourceFrame.prototype = {
popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true);
}
- function evaluateCallback(result)
- {
- if (result.isError())
- return;
- if (!WebInspector.panels.scripts.paused)
- return;
- showObjectPopup.call(this, result);
- }
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(element.textContent, false, this._popoverObjectGroup, false, evaluateCallback.bind(this));
+ this._delegate.evaluateInSelectedCallFrame(element.textContent, showObjectPopup.bind(this));
},
_editBreakpointCondition: function(lineNumber, condition, callback)
@@ -820,24 +742,6 @@ WebInspector.SourceFrame.prototype = {
return conditionElement;
},
- _evalSelectionInCallFrame: function(event)
- {
- if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused)
- return;
-
- var selection = this.element.contentWindow.getSelection();
- if (!selection.rangeCount)
- return;
-
- var expression = selection.getRangeAt(0).toString().trim();
- WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", function(result) {
- WebInspector.showConsole();
- var commandMessage = new WebInspector.ConsoleCommand(expression);
- WebInspector.console.addMessage(commandMessage);
- WebInspector.console.addMessage(new WebInspector.ConsoleCommandResult(result, commandMessage));
- });
- },
-
resize: function()
{
if (this._textViewer)
@@ -851,7 +755,7 @@ WebInspector.SourceFrame.prototype = {
function didFormat(formattedContent)
{
- this._formattedContent = formattedContent;
+ this._content = formattedContent;
this._textModel.setText(null, formattedContent.text);
this._setTextViewerDecorations();
}
@@ -859,91 +763,96 @@ WebInspector.SourceFrame.prototype = {
formatter.formatContent(this._content, didFormat.bind(this))
},
- _continueToLine: function(lineNumber)
- {
- var location = this._textViewerLineNumberToScriptLocation(lineNumber);
- if (location.sourceID)
- WebInspector.debuggerModel.continueToLine(location.sourceID, location.lineNumber);
- },
-
_doubleClick: function(event)
{
- if (!Preferences.canEditScriptSource || !this._isScript)
+ if (!this._delegate.canEditScriptSource())
return;
var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineRow)
return; // Do not trigger editing from line numbers.
- var lineNumber = lineRow.lineNumber;
- var location = this._textViewerLineNumberToScriptLocation(lineNumber);
- if (!location.sourceID)
- return;
+ this._textViewer.editLine(lineRow, this._didEditLine.bind(this, lineRow.lineNumber));
+ },
- function didEditLine(newContent)
- {
- var lines = [];
- var oldLines = this._content.text.split('\n');
- for (var i = 0; i < oldLines.length; ++i) {
- if (i === lineNumber)
- lines.push(newContent);
- else
- lines.push(oldLines[i]);
- }
- WebInspector.debuggerModel.editScriptSource(location.sourceID, lines.join("\n"));
+ _didEditLine: function(lineNumber, newContent)
+ {
+ var lines = [];
+ var oldLines = this._content.text.split('\n');
+ for (var i = 0; i < oldLines.length; ++i) {
+ if (i === lineNumber)
+ lines.push(newContent);
+ else
+ lines.push(oldLines[i]);
}
- this._textViewer.editLine(lineRow, didEditLine.bind(this));
+ this._delegate.editScriptSource(lines.join("\n"));
+ }
+}
+
+WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;
+
+
+WebInspector.SourceFrameDelegate = function()
+{
+}
+
+WebInspector.SourceFrameDelegate.prototype = {
+ requestContent: function(callback)
+ {
+ // Should be implemented by subclasses.
},
- _setBreakpoint: function(lineNumber, condition, enabled)
+ debuggingSupported: function()
{
- var location = this._textViewerLineNumberToScriptLocation(lineNumber);
- if (this._url)
- WebInspector.debuggerModel.setBreakpoint(this._url, location.lineNumber, location.columnNumber, condition, enabled);
- else if (location.sourceID)
- WebInspector.debuggerModel.setBreakpointBySourceId(location.sourceID, location.lineNumber, location.columnNumber, condition, enabled);
- else
- return;
+ return false;
+ },
- if (!WebInspector.panels.scripts.breakpointsActivated)
- WebInspector.panels.scripts.toggleBreakpointsClicked();
+ setBreakpoint: function(lineNumber, condition, enabled)
+ {
+ // Should be implemented by subclasses.
},
- _findBreakpoint: function(textViewerLineNumber)
+ removeBreakpoint: function(breakpointId)
{
- var breakpointId = this._textViewerLineNumberToBreakpointId[textViewerLineNumber];
- return WebInspector.debuggerModel.breakpointForId(breakpointId);
+ // Should be implemented by subclasses.
},
- _originalLocationToTextViewerLineNumber: function(lineNumber, columnNumber)
+ updateBreakpoint: function(breakpointId, condition, enabled)
{
- if (!this._formattedContent)
- return lineNumber;
- return this._formattedContent.originalLocationToFormattedLocation(lineNumber, columnNumber).lineNumber;
+ // Should be implemented by subclasses.
},
- _textViewerLineNumberToScriptLocation: function(lineNumber)
+ findBreakpoint: function(lineNumber)
{
- if (!this._formattedContent)
- return this._content.scriptLocationForLineNumber(lineNumber);
- return this._formattedContent.scriptLocationForFormattedLineNumber(lineNumber);
- }
-}
+ // Should be implemented by subclasses.
+ },
-WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;
+ continueToLine: function(lineNumber)
+ {
+ // Should be implemented by subclasses.
+ },
+ canEditScriptSource: function()
+ {
+ return false;
+ },
-WebInspector.SourceFrameContentProvider = function()
-{
-}
+ editScriptSource: function(text)
+ {
+ // Should be implemented by subclasses.
+ },
-WebInspector.SourceFrameContentProvider.prototype = {
- requestContent: function(callback)
+ debuggerPaused: function()
+ {
+ // Should be implemented by subclasses.
+ },
+
+ evaluateInSelectedCallFrame: function(string)
{
// Should be implemented by subclasses.
},
- scripts: function()
+ releaseEvaluationResult: function()
{
// Should be implemented by subclasses.
}
diff --git a/Source/WebCore/inspector/front-end/SourceFrameContent.js b/Source/WebCore/inspector/front-end/SourceFrameContent.js
index e4a74ec..91b397b 100644
--- a/Source/WebCore/inspector/front-end/SourceFrameContent.js
+++ b/Source/WebCore/inspector/front-end/SourceFrameContent.js
@@ -28,24 +28,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.SourceFrameContent = function(text, scripts)
+WebInspector.SourceFrameContent = function(text, mapping, scriptRanges)
{
- if (scripts.length && scripts[0].length < text.length) {
- // WebKit html lexer normalizes line endings and scripts are passed to VM with "\n" line endings.
- // However, resource content has original line endings, so we have to normalize line endings here.
- text = text.replace(/\r\n/g, "\n");
- }
this._text = text;
- this._lineEndings = text.findAll("\n");
- this._lineEndings.push(text.length);
-
- this._scriptRanges = [];
- for (var i = 0; i < scripts.length; ++i) {
- var script = scripts[i];
- var offset = this.locationToPosition(script.lineOffset, script.columnOffset);
- this._scriptRanges.push({ start: offset, end: offset + script.length, script: script });
- }
- this._scriptRanges.sort(function(x, y) { return x.start - y.start; });
+ this._mapping = mapping;
+ this._scriptRanges = scriptRanges;
}
WebInspector.SourceFrameContent.prototype = {
@@ -59,95 +46,77 @@ WebInspector.SourceFrameContent.prototype = {
return this._scriptRanges;
},
- locationToPosition: function(lineNumber, columnNumber)
- {
- var position = lineNumber ? this._lineEndings[lineNumber - 1] + 1 : 0;
- return position + columnNumber;
- },
-
- positionToLocation: function(position)
+ sourceFrameLineNumberToActualLocation: function(lineNumber)
{
- var location = {};
- location.lineNumber = this._lineEndings.upperBound(position - 1);
- if (!location.lineNumber)
- location.columnNumber = position;
- else
- location.columnNumber = position - this._lineEndings[location.lineNumber - 1] - 1;
+ // Script content may start right after <script> tag without new line (e.g. "<script>function f()...").
+ // In that case, column number should be equal to script column offset.
+ var columnNumber = 0;
+ for (var i = 0; i < this._scriptRanges.length; ++i) {
+ var scriptRange = this._scriptRanges[i];
+ if (scriptRange.start.lineNumber < lineNumber)
+ continue;
+ if (scriptRange.start.lineNumber === lineNumber)
+ columnNumber = scriptRange.start.columnNumber;
+ break;
+ }
+ var location = this._mapping.sourceLocationToActualLocation(lineNumber, columnNumber);
+ location.sourceID = this._sourceIDForSourceFrameLineNumber(lineNumber);
return location;
},
- scriptLocationForLineNumber: function(lineNumber)
- {
- var range = this.lineNumberToRange(lineNumber);
- return this.scriptLocationForRange(range.start, range.end);
- },
-
- scriptLocationForRange: function(start, end)
+ actualLocationToSourceFrameLineNumber: function(lineNumber, columnNumber)
{
- var position = start;
- var scriptRange = this._intersectingScriptRange(start, end);
- if (scriptRange)
- position = Math.max(position, scriptRange.start);
- var scriptLocation = this.positionToLocation(position);
- if (scriptRange)
- scriptLocation.sourceID = scriptRange.script.sourceID;
- return scriptLocation;
+ return this._mapping.actualLocationToSourceLocation(lineNumber, columnNumber).lineNumber;
},
- lineNumberToRange: function(lineNumber)
- {
- var previousLineEnd = this._lineEndings[lineNumber - 1] || 0;
- var lineEnd = this._lineEndings[lineNumber];
- return { start: previousLineEnd + 1, end: lineEnd };
- },
-
- _intersectingScriptRange: function(start, end)
+ _sourceIDForSourceFrameLineNumber: function(lineNumber)
{
for (var i = 0; i < this._scriptRanges.length; ++i) {
var scriptRange = this._scriptRanges[i];
- if (start < scriptRange.end && end > scriptRange.start)
- return scriptRange;
+ if (lineNumber < scriptRange.start.lineNumber)
+ return;
+ if (lineNumber > scriptRange.end.lineNumber)
+ continue;
+ if (lineNumber === scriptRange.end.lineNumber && !scriptRange.end.columnNumber)
+ continue;
+ return scriptRange.sourceID;
}
}
}
-WebInspector.FormattedSourceFrameContent = function(originalContent, text, mapping)
+WebInspector.SourceMapping = function()
{
- this._originalContent = originalContent;
- this._formattedContent = new WebInspector.SourceFrameContent(text, []);
- this._mapping = mapping;
}
-WebInspector.FormattedSourceFrameContent.prototype = {
- get text()
+WebInspector.SourceMapping.prototype = {
+ actualLocationToSourceLocation: function(lineNumber, columnNumber)
{
- return this._formattedContent.text;
+ // Should be implemented by subclasses.
},
- originalLocationToFormattedLocation: function(lineNumber, columnNumber)
+ sourceLocationToActualLocation: function(lineNumber, columnNumber)
{
- var originalPosition = this._originalContent.locationToPosition(lineNumber, columnNumber);
- var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition);
- return this._formattedContent.positionToLocation(formattedPosition);
- },
+ // Should be implemented by subclasses.
+ }
+}
+
+
+WebInspector.IdenticalSourceMapping = function()
+{
+ WebInspector.SourceMapping.call(this);
+}
- scriptLocationForFormattedLineNumber: function(lineNumber)
+WebInspector.IdenticalSourceMapping.prototype = {
+ actualLocationToSourceLocation: function(lineNumber, columnNumber)
{
- var range = this._formattedContent.lineNumberToRange(lineNumber);
- var start = this._convertPosition(this._mapping.formatted, this._mapping.original, range.start);
- var end = this._convertPosition(this._mapping.formatted, this._mapping.original, range.end);
- return this._originalContent.scriptLocationForRange(start, end);
+ return { lineNumber: lineNumber, columnNumber: columnNumber};
},
- _convertPosition: function(positions1, positions2, position)
+ sourceLocationToActualLocation: function(lineNumber, columnNumber)
{
- var index = positions1.upperBound(position);
- var range1 = positions1[index] - positions1[index - 1];
- var range2 = positions2[index] - positions2[index - 1];
- var position2 = positions2[index - 1];
- if (range1)
- position2 += Math.round((position - positions1[index - 1]) * range2 / range1);
- return position2;
+ return { lineNumber: lineNumber, columnNumber: columnNumber};
}
}
+
+WebInspector.IdenticalSourceMapping.prototype.__proto__ = WebInspector.SourceMapping.prototype;
diff --git a/Source/WebCore/inspector/front-end/SourceTokenizer.js b/Source/WebCore/inspector/front-end/SourceTokenizer.js
index d30744c..bb44a86 100644
--- a/Source/WebCore/inspector/front-end/SourceTokenizer.js
+++ b/Source/WebCore/inspector/front-end/SourceTokenizer.js
@@ -48,11 +48,6 @@ WebInspector.SourceTokenizer.prototype = {
return this._condition;
},
- get subTokenizer()
- {
- return this._condition.subTokenizer;
- },
-
getLexCondition: function()
{
return this.condition.lexCondition;
diff --git a/Source/WebCore/inspector/front-end/StylesSidebarPane.js b/Source/WebCore/inspector/front-end/StylesSidebarPane.js
index 57d3b76..c7d151a 100644
--- a/Source/WebCore/inspector/front-end/StylesSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/StylesSidebarPane.js
@@ -438,7 +438,7 @@ WebInspector.StylesSidebarPane.prototype = {
if (computedStyle)
var section = new WebInspector.ComputedStylePropertiesSection(styleRule, usedProperties, disabledComputedProperties, styleRules);
else
- var section = new WebInspector.StylePropertiesSection(styleRule, editable, styleRule.isInherited, lastWasSeparator);
+ var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator);
section.pane = this;
section.expanded = true;
@@ -503,7 +503,7 @@ WebInspector.StylesSidebarPane.prototype = {
addBlankSection: function()
{
- var blankSection = new WebInspector.BlankStylePropertiesSection(appropriateSelectorForNode(this.node, true));
+ var blankSection = new WebInspector.BlankStylePropertiesSection(this, appropriateSelectorForNode(this.node, true));
blankSection.pane = this;
var elementStyleSection = this.sections[0][1];
@@ -591,7 +591,7 @@ WebInspector.ComputedStyleSidebarPane = function()
WebInspector.ComputedStyleSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
-WebInspector.StylePropertiesSection = function(styleRule, editable, isInherited, isFirstSection)
+WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, isInherited, isFirstSection)
{
WebInspector.PropertiesSection.call(this, "");
this.element.className = "styles-section monospace" + (isFirstSection ? " first-styles-section" : "");
@@ -613,6 +613,7 @@ WebInspector.StylePropertiesSection = function(styleRule, editable, isInherited,
this._selectorElement.addEventListener("dblclick", this._handleSelectorDoubleClick.bind(this), false);
this.element.addEventListener("dblclick", this._handleEmptySpaceDoubleClick.bind(this), false);
+ this._parentPane = parentPane;
this.styleRule = styleRule;
this.rule = this.styleRule.rule;
this.editable = editable;
@@ -792,7 +793,7 @@ WebInspector.StylePropertiesSection.prototype = {
var inherited = this.isPropertyInherited(property.name);
var overloaded = this.isPropertyOverloaded(property.name, isShorthand);
- var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, isShorthand, inherited, overloaded);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, isShorthand, inherited, overloaded);
this.propertiesTreeOutline.appendChild(item);
handledProperties[property.name] = property;
}
@@ -813,7 +814,7 @@ WebInspector.StylePropertiesSection.prototype = {
{
var style = this.styleRule.style;
var property = style.newBlankProperty();
- var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, false, false, false);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, false, false);
this.propertiesTreeOutline.appendChild(item);
item.listItemElement.textContent = "";
item._newProperty = true;
@@ -1025,7 +1026,7 @@ WebInspector.ComputedStylePropertiesSection.prototype = {
for (var i = 0; i < uniqueProperties.length; ++i) {
var property = uniqueProperties[i];
var inherited = this._isPropertyInherited(property.name);
- var item = new WebInspector.StylePropertyTreeElement(this.styleRule, style, property, false, inherited, false);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, inherited, false);
this.propertiesTreeOutline.appendChild(item);
this._propertyTreeElements[property.name] = item;
}
@@ -1070,9 +1071,9 @@ WebInspector.ComputedStylePropertiesSection.prototype = {
WebInspector.ComputedStylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;
-WebInspector.BlankStylePropertiesSection = function(defaultSelectorText)
+WebInspector.BlankStylePropertiesSection = function(parentPane, defaultSelectorText)
{
- WebInspector.StylePropertiesSection.call(this, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false);
+ WebInspector.StylePropertiesSection.call(this, parentPane, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false);
this.element.addStyleClass("blank-section");
}
@@ -1121,8 +1122,9 @@ WebInspector.BlankStylePropertiesSection.prototype = {
WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype;
-WebInspector.StylePropertyTreeElement = function(styleRule, style, property, shorthand, inherited, overloaded)
+WebInspector.StylePropertyTreeElement = function(parentPane, styleRule, style, property, shorthand, inherited, overloaded)
{
+ this._parentPane = parentPane;
this._styleRule = styleRule;
this.style = style;
this.property = property;
@@ -1483,7 +1485,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
}
var liveProperty = this.style.getLiveProperty(name);
- var item = new WebInspector.StylePropertyTreeElement(this._styleRule, this.style, liveProperty, false, inherited, overloaded);
+ var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this._styleRule, this.style, liveProperty, false, inherited, overloaded);
this.appendChild(item);
}
},
@@ -1609,6 +1611,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
return "move-forward";
}
+ this._parentPane.isModifyingStyle = true;
WebInspector.startEditing(selectElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
@@ -1719,6 +1722,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
editedElement.parentElement.removeStyleClass("child-editing");
delete this.originalPropertyText;
+ delete this._parentPane.isModifyingStyle;
},
editingCancelled: function(element, context)
@@ -1767,6 +1771,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
var isDirtyViaPaste = isDataPasted && (this.nameElement.textContent !== context.originalName || this.valueElement.textContent !== context.originalValue);
var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput));
if (((userInput !== previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) {
+ this._parentPane.isModifyingStyle = true;
this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section);
var propertyText;
if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent)))
@@ -1781,7 +1786,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
} else {
if (!isDataPasted && !this._newProperty)
this.updateTitle();
- moveToNextCallback(this._newProperty, false, this.treeOutline.section);
+ moveToNextCallback.call(this, this._newProperty, false, this.treeOutline.section);
}
var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1;
@@ -1789,6 +1794,8 @@ WebInspector.StylePropertyTreeElement.prototype = {
// The Callback to start editing the next/previous property/selector.
function moveToNextCallback(alreadyNew, valueChanged, section)
{
+ delete this._parentPane.isModifyingStyle;
+
if (!moveDirection)
return;
diff --git a/Source/WebCore/inspector/front-end/TestController.js b/Source/WebCore/inspector/front-end/TestController.js
index 3bfe28c..e6783f9 100644
--- a/Source/WebCore/inspector/front-end/TestController.js
+++ b/Source/WebCore/inspector/front-end/TestController.js
@@ -28,40 +28,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-WebInspector.TestController = function(callId)
+WebInspector.TestController = function()
{
- this._callId = callId;
- this._waitUntilDone = false;
- this.results = [];
}
WebInspector.TestController.prototype = {
- waitUntilDone: function()
+ notifyDone: function(callId, result)
{
- this._waitUntilDone = true;
- },
-
- notifyDone: function(result)
- {
- if (typeof result === "undefined" && this.results.length)
- result = this.results;
var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result);
- InspectorBackend.didEvaluateForTestInFrontend(this._callId, message);
- },
-
- runAfterPendingDispatches: function(callback)
- {
- if (WebInspector.pendingDispatches === 0) {
- callback();
- return;
- }
- setTimeout(this.runAfterPendingDispatches.bind(this), 0, callback);
+ InspectorAgent.didEvaluateForTestInFrontend(callId, message);
}
}
WebInspector.evaluateForTestInFrontend = function(callId, script)
{
- var controller = new WebInspector.TestController(callId);
function invokeMethod()
{
try {
@@ -71,11 +51,10 @@ WebInspector.evaluateForTestInFrontend = function(callId, script)
else
result = window.eval(script);
- if (!controller._waitUntilDone)
- controller.notifyDone(result);
+ WebInspector.TestController.prototype.notifyDone(callId, result);
} catch (e) {
- controller.notifyDone(e.toString());
+ WebInspector.testController.prototype.notifyDone(callId, e.toString());
}
}
- controller.runAfterPendingDispatches(invokeMethod);
+ InspectorBackend.runAfterPendingDispatches(invokeMethod);
}
diff --git a/Source/WebCore/inspector/front-end/TextEditorHighlighter.js b/Source/WebCore/inspector/front-end/TextEditorHighlighter.js
index 4ac831e..9bdcc82 100644
--- a/Source/WebCore/inspector/front-end/TextEditorHighlighter.js
+++ b/Source/WebCore/inspector/front-end/TextEditorHighlighter.js
@@ -34,6 +34,7 @@ WebInspector.TextEditorHighlighter = function(textModel, damageCallback)
this._textModel = textModel;
this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html");
this._damageCallback = damageCallback;
+ this._highlightChunkLimit = 1000;
this.reset();
}
@@ -43,18 +44,23 @@ WebInspector.TextEditorHighlighter.prototype = {
var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
if (tokenizer) {
this._tokenizer = tokenizer;
- this._tokenizerCondition = this._tokenizer.initialCondition;
+ this._tokenizerConditionStringified = JSON.stringify(this._tokenizer.initialCondition);
}
},
+ set highlightChunkLimit(highlightChunkLimit)
+ {
+ this._highlightChunkLimit = highlightChunkLimit;
+ },
+
reset: function()
{
this._lastHighlightedLine = 0;
this._lastHighlightedColumn = 0;
- this._tokenizerCondition = this._tokenizer.initialCondition;
+ this._tokenizerConditionStringified = JSON.stringify(this._tokenizer.initialCondition);
},
- highlight: function(endLine)
+ highlight: function(endLine, opt_forceRun)
{
// First check if we have work to do.
if (endLine <= this._lastHighlightedLine)
@@ -62,7 +68,7 @@ WebInspector.TextEditorHighlighter.prototype = {
this._requestedEndLine = endLine;
- if (this._highlightTimer) {
+ if (this._highlightTimer && !opt_forceRun) {
// There is a timer scheduled, it will catch the new job based on the new endLine set.
return;
}
@@ -75,6 +81,58 @@ WebInspector.TextEditorHighlighter.prototype = {
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100);
},
+ updateHighlight: function(startLine, endLine)
+ {
+ if (this._lastHighlightedLine < startLine) {
+ // Highlighter did not reach this point yet, nothing to update. It will reach it on subsequent timer tick and do the job.
+ return false;
+ }
+
+ var savedLastHighlightedLine = this._lastHighlightedLine;
+ var savedLastHighlightedColumn = this._lastHighlightedColumn;
+ var savedTokenizerCondition = this._tokenizerConditionStringified;
+
+ this._lastHighlightedLine = startLine;
+ this._lastHighlightedColumn = 0;
+
+ // Restore highlighter context taken from the previous line.
+ var attributes = this._textModel.getAttribute(startLine - 1, "highlight") || {};
+ this._tokenizerConditionStringified = attributes.postConditionStringified || JSON.stringify(this._tokenizer.initialCondition);
+
+ // Try to update highlight synchronously.
+ this._highlightLines(endLine);
+
+ if (this._lastHighlightedLine >= this._textModel.linesCount) {
+ // All is done up to the end.
+ return true;
+ }
+
+ var attributes1 = this._textModel.getAttribute(this._lastHighlightedLine - 1, "highlight") || {};
+ var attributes2 = this._textModel.getAttribute(this._lastHighlightedLine, "highlight") || {};
+ if (this._lastHighlightedColumn === 0 && attributes2.preConditionStringified && attributes1.postConditionStringified === attributes2.preConditionStringified) {
+ // Highlighting ended ahead of time. Restore previously saved state, unless we have done more than it was before.
+ if (savedLastHighlightedLine >= this._lastHighlightedLine) {
+ this._lastHighlightedLine = savedLastHighlightedLine;
+ this._lastHighlightedColumn = savedLastHighlightedColumn;
+ this._tokenizerConditionStringified = savedTokenizerCondition;
+ }
+ return true;
+ } else {
+ // If failed to update highlight synchronously, invalidate highlight data for the subsequent lines.
+ if (this._lastHighlightedColumn === 0)
+ this._textModel.removeAttribute(this._lastHighlightedLine, "highlight");
+ for (var i = this._lastHighlightedLine + 1; i < this._textModel.linesCount; ++i)
+ this._textModel.removeAttribute(i, "highlight");
+
+ // Continue highlighting on subsequent timer ticks.
+ this._requestedEndLine = endLine;
+ if (!this._highlightTimer)
+ this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, endLine), 100);
+
+ return false;
+ }
+ },
+
_highlightInChunks: function(endLine)
{
delete this._highlightTimer;
@@ -89,6 +147,10 @@ WebInspector.TextEditorHighlighter.prototype = {
return;
}
+ // The textModel may have been already updated.
+ if (this._requestedEndLine > this._textModel.linesCount)
+ this._requestedEndLine = this._textModel.linesCount;
+
this._highlightLines(this._requestedEndLine);
// Schedule tail highlight if necessary.
@@ -98,35 +160,49 @@ WebInspector.TextEditorHighlighter.prototype = {
_highlightLines: function(endLine)
{
- // Tokenizer is stateless and reused accross viewers, restore its condition before highlight and save it after.
- this._tokenizer.condition = this._tokenizerCondition;
+ // Tokenizer is stateless and reused across viewers, restore its condition before highlight and save it after.
+ this._tokenizer.condition = JSON.parse(this._tokenizerConditionStringified);
var tokensCount = 0;
for (var lineNumber = this._lastHighlightedLine; lineNumber < endLine; ++lineNumber) {
var line = this._textModel.line(lineNumber);
this._tokenizer.line = line;
- var attributes = this._textModel.getAttribute(lineNumber, "highlight") || {};
+
+ if (this._lastHighlightedColumn === 0) {
+ var attributes = {};
+ attributes.preConditionStringified = JSON.stringify(this._tokenizer.condition);
+ this._textModel.setAttribute(lineNumber, "highlight", attributes);
+ } else
+ var attributes = this._textModel.getAttribute(lineNumber, "highlight");
// Highlight line.
do {
var newColumn = this._tokenizer.nextToken(this._lastHighlightedColumn);
var tokenType = this._tokenizer.tokenType;
if (tokenType)
- attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType, subTokenizer: this._tokenizer.subTokenizer };
+ attributes[this._lastHighlightedColumn] = { length: newColumn - this._lastHighlightedColumn, tokenType: tokenType };
this._lastHighlightedColumn = newColumn;
- if (++tokensCount > 1000)
+ if (++tokensCount > this._highlightChunkLimit)
break;
- } while (this._lastHighlightedColumn < line.length)
+ } while (this._lastHighlightedColumn < line.length);
- this._textModel.setAttribute(lineNumber, "highlight", attributes);
if (this._lastHighlightedColumn < line.length) {
// Too much work for single chunk - exit.
break;
- } else
+ } else {
this._lastHighlightedColumn = 0;
+ attributes.postConditionStringified = JSON.stringify(this._tokenizer.condition);
+
+ var nextAttributes = this._textModel.getAttribute(lineNumber + 1, "highlight") || {};
+ if (nextAttributes.preConditionStringified === attributes.postConditionStringified) {
+ // Following lines are up to date, no need to re-highlight.
+ ++lineNumber;
+ break;
+ }
+ }
}
this._damageCallback(this._lastHighlightedLine, lineNumber);
- this._tokenizerCondition = this._tokenizer.condition;
+ this._tokenizerConditionStringified = JSON.stringify(this._tokenizer.condition);
this._lastHighlightedLine = lineNumber;
}
}
diff --git a/Source/WebCore/inspector/front-end/TextViewer.js b/Source/WebCore/inspector/front-end/TextViewer.js
index ce6502d..65b4724 100644
--- a/Source/WebCore/inspector/front-end/TextViewer.js
+++ b/Source/WebCore/inspector/front-end/TextViewer.js
@@ -37,9 +37,11 @@ WebInspector.TextViewer = function(textModel, platform, url)
this.element = document.createElement("div");
this.element.className = "text-editor monospace";
+ var enterTextChangeMode = this._enterInternalTextChangeMode.bind(this);
+ var exitTextChangeMode = this._exitInternalTextChangeMode.bind(this);
var syncScrollListener = this._syncScroll.bind(this);
var syncDecorationsForLineListener = this._syncDecorationsForLine.bind(this);
- this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener);
+ this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode);
this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener);
this.element.appendChild(this._mainPanel.element);
this.element.appendChild(this._gutterPanel.element);
@@ -51,6 +53,21 @@ WebInspector.TextViewer.prototype = {
this._mainPanel.mimeType = mimeType;
},
+ set readOnly(readOnly)
+ {
+ this._mainPanel.readOnly = readOnly;
+ },
+
+ set startEditingListener(startEditingListener)
+ {
+ this._startEditingListener = startEditingListener;
+ },
+
+ set endEditingListener(endEditingListener)
+ {
+ this._endEditingListener = endEditingListener;
+ },
+
get textModel()
{
return this._textModel;
@@ -129,6 +146,7 @@ WebInspector.TextViewer.prototype = {
{
this._mainPanel.endUpdates();
this._gutterPanel.endUpdates();
+ this._updatePanelOffsets();
},
resize: function()
@@ -141,9 +159,31 @@ WebInspector.TextViewer.prototype = {
// WebInspector.TextModel listener
_textChanged: function(oldRange, newRange, oldText, newText)
{
- this._mainPanel.textChanged();
- this._gutterPanel.textChanged();
+ if (!this._internalTextChangeMode) {
+ this._mainPanel.textChanged(oldRange, newRange);
+ this._gutterPanel.textChanged(oldRange, newRange);
+ this._updatePanelOffsets();
+ }
+ },
+
+ _enterInternalTextChangeMode: function()
+ {
+ this._internalTextChangeMode = true;
+
+ if (this._startEditingListener)
+ this._startEditingListener();
+ },
+
+ _exitInternalTextChangeMode: function(oldRange, newRange)
+ {
+ this._internalTextChangeMode = false;
+
+ // Update the gutter panel.
+ this._gutterPanel.textChanged(oldRange, newRange);
this._updatePanelOffsets();
+
+ if (this._endEditingListener)
+ this._endEditingListener(oldRange, newRange);
},
_updatePanelOffsets: function()
@@ -161,13 +201,8 @@ WebInspector.TextViewer.prototype = {
setTimeout(function() {
var mainElement = this._mainPanel.element;
var gutterElement = this._gutterPanel.element;
-
// Handle horizontal scroll bar at the bottom of the main panel.
- if (gutterElement.offsetHeight > mainElement.clientHeight)
- gutterElement.style.setProperty("padding-bottom", (gutterElement.offsetHeight - mainElement.clientHeight) + "px");
- else
- gutterElement.style.removeProperty("padding-bottom");
-
+ this._gutterPanel.syncClientHeight(mainElement.clientHeight);
gutterElement.scrollTop = mainElement.scrollTop;
}.bind(this), 0);
},
@@ -177,13 +212,19 @@ WebInspector.TextViewer.prototype = {
if (lineNumber >= this._textModel.linesCount)
return;
- var mainChunk = this._mainPanel.makeLineAChunk(lineNumber);
- var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber);
- var height = mainChunk.height;
- if (height)
- gutterChunk.element.style.setProperty("height", height + "px");
- else
- gutterChunk.element.style.removeProperty("height");
+ var mainChunk = this._mainPanel.chunkForLine(lineNumber);
+ if (mainChunk.linesCount === 1) {
+ var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber);
+ var height = mainChunk.height;
+ if (height)
+ gutterChunk.element.style.setProperty("height", height + "px");
+ else
+ gutterChunk.element.style.removeProperty("height");
+ } else {
+ var gutterChunk = this._gutterPanel.chunkForLine(lineNumber);
+ if (gutterChunk.linesCount === 1)
+ gutterChunk.element.style.removeProperty("height");
+ }
}
}
@@ -193,6 +234,7 @@ WebInspector.TextEditorChunkedPanel = function(textModel)
this._defaultChunkSize = 50;
this._paintCoalescingLevel = 0;
+ this._domUpdateCoalescingLevel = 0;
}
WebInspector.TextEditorChunkedPanel.prototype = {
@@ -222,23 +264,27 @@ WebInspector.TextEditorChunkedPanel.prototype = {
chunk.removeDecoration(decoration);
},
- textChanged: function(oldRange, newRange, oldText, newText)
+ textChanged: function(oldRange, newRange)
{
this._buildChunks();
},
_buildChunks: function()
{
- this.element.removeChildren();
+ this.beginDomUpdates();
+
+ this._container.removeChildren();
this._textChunks = [];
for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) {
var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
this._textChunks.push(chunk);
- this.element.appendChild(chunk.element);
+ this._container.appendChild(chunk.element);
}
this._repaintAll();
+
+ this.endDomUpdates();
},
makeLineAChunk: function(lineNumber)
@@ -251,6 +297,8 @@ WebInspector.TextEditorChunkedPanel.prototype = {
if (oldChunk.linesCount === 1)
return oldChunk;
+ this.beginDomUpdates();
+
var wasExpanded = oldChunk.expanded;
oldChunk.expanded = false;
@@ -260,24 +308,24 @@ WebInspector.TextEditorChunkedPanel.prototype = {
if (lineNumber > oldChunk.startLine) {
var prefixChunk = this._createNewChunk(oldChunk.startLine, lineNumber);
this._textChunks.splice(insertIndex++, 0, prefixChunk);
- this.element.insertBefore(prefixChunk.element, oldChunk.element);
+ this._container.insertBefore(prefixChunk.element, oldChunk.element);
}
// Line chunk.
var lineChunk = this._createNewChunk(lineNumber, lineNumber + 1);
this._textChunks.splice(insertIndex++, 0, lineChunk);
- this.element.insertBefore(lineChunk.element, oldChunk.element);
+ this._container.insertBefore(lineChunk.element, oldChunk.element);
// Suffix chunk.
if (oldChunk.startLine + oldChunk.linesCount > lineNumber + 1) {
var suffixChunk = this._createNewChunk(lineNumber + 1, oldChunk.startLine + oldChunk.linesCount);
this._textChunks.splice(insertIndex, 0, suffixChunk);
- this.element.insertBefore(suffixChunk.element, oldChunk.element);
+ this._container.insertBefore(suffixChunk.element, oldChunk.element);
}
// Remove enclosing chunk.
this._textChunks.splice(chunkNumber, 1);
- this.element.removeChild(oldChunk.element);
+ this._container.removeChild(oldChunk.element);
if (wasExpanded) {
if (prefixChunk)
@@ -287,11 +335,17 @@ WebInspector.TextEditorChunkedPanel.prototype = {
suffixChunk.expanded = true;
}
+ this.endDomUpdates();
+
return lineChunk;
},
_scroll: function()
{
+ // FIXME: Replace the "2" with the padding-left value from CSS.
+ if (this.element.scrollLeft <= 2)
+ this.element.scrollLeft = 0;
+
this._scheduleRepaintAll();
if (this._syncScrollListener)
this._syncScrollListener();
@@ -316,26 +370,52 @@ WebInspector.TextEditorChunkedPanel.prototype = {
this._repaintAll();
},
+ beginDomUpdates: function()
+ {
+ this._domUpdateCoalescingLevel++;
+ },
+
+ endDomUpdates: function()
+ {
+ this._domUpdateCoalescingLevel--;
+ },
+
_chunkNumberForLine: function(lineNumber)
{
- for (var i = 0; i < this._textChunks.length; ++i) {
- var line = this._textChunks[i].startLine;
- if (lineNumber >= line && lineNumber < line + this._textChunks[i].linesCount)
- return i;
+ function compareLineNumbers(value, chunk)
+ {
+ return value < chunk.startLine ? -1 : 1;
}
- return this._textChunks.length - 1;
+ var insertBefore = insertionIndexForObjectInListSortedByFunction(lineNumber, this._textChunks, compareLineNumbers);
+ return insertBefore - 1;
},
- _chunkForLine: function(lineNumber)
+ chunkForLine: function(lineNumber)
{
return this._textChunks[this._chunkNumberForLine(lineNumber)];
},
+ _findVisibleChunks: function(visibleFrom, visibleTo)
+ {
+ function compareOffsetTops(value, chunk)
+ {
+ return value < chunk.offsetTop ? -1 : 1;
+ }
+ var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, this._textChunks, compareOffsetTops);
+
+ var from = insertBefore - 1;
+ for (var to = from + 1; to < this._textChunks.length; ++to) {
+ if (this._textChunks[to].offsetTop >= visibleTo)
+ break;
+ }
+ return { start: from, end: to };
+ },
+
_repaintAll: function()
{
delete this._repaintAllTimer;
- if (this._paintCoalescingLevel)
+ if (this._paintCoalescingLevel || this._dirtyLines)
return;
if (!this._textChunks)
@@ -344,25 +424,10 @@ WebInspector.TextEditorChunkedPanel.prototype = {
var visibleFrom = this.element.scrollTop;
var visibleTo = this.element.scrollTop + this.element.clientHeight;
- var offset = 0;
- var fromIndex = -1;
- var toIndex = 0;
- for (var i = 0; i < this._textChunks.length; ++i) {
- var chunk = this._textChunks[i];
- var chunkHeight = chunk.height;
- if (offset + chunkHeight > visibleFrom && offset < visibleTo) {
- if (fromIndex === -1)
- fromIndex = i;
- toIndex = i + 1;
- } else {
- if (offset >= visibleTo)
- break;
- }
- offset += chunkHeight;
+ if (visibleTo) {
+ var result = this._findVisibleChunks(visibleFrom, visibleTo);
+ this._expandChunks(result.start, result.end);
}
-
- if (toIndex)
- this._expandChunks(fromIndex, toIndex);
},
_totalHeight: function(firstElement, lastElement)
@@ -370,11 +435,19 @@ WebInspector.TextEditorChunkedPanel.prototype = {
lastElement = (lastElement || firstElement).nextElementSibling;
if (lastElement)
return lastElement.offsetTop - firstElement.offsetTop;
- else if (firstElement.offsetParent)
- return firstElement.offsetParent.scrollHeight - firstElement.offsetTop;
- return firstElement.offsetHeight;
+
+ var offsetParent = firstElement.offsetParent;
+ if (offsetParent && offsetParent.scrollHeight > offsetParent.clientHeight)
+ return offsetParent.scrollHeight - firstElement.offsetTop;
+
+ var total = 0;
+ while (firstElement && firstElement !== lastElement) {
+ total += firstElement.offsetHeight;
+ firstElement = firstElement.nextElementSibling;
+ }
+ return total;
},
-
+
resize: function()
{
this._repaintAll();
@@ -390,6 +463,10 @@ WebInspector.TextEditorGutterPanel = function(textModel, syncDecorationsForLineL
this.element = document.createElement("div");
this.element.className = "text-editor-lines";
+ this._container = document.createElement("div");
+ this._container.className = "inner-container";
+ this.element.appendChild(this._container);
+
this.element.addEventListener("scroll", this._scroll.bind(this), false);
this.freeCachedElements();
@@ -409,9 +486,59 @@ WebInspector.TextEditorGutterPanel.prototype = {
_expandChunks: function(fromIndex, toIndex)
{
- for (var i = 0; i < this._textChunks.length; ++i) {
+ for (var i = 0; i < this._textChunks.length; ++i)
this._textChunks[i].expanded = (fromIndex <= i && i < toIndex);
+ },
+
+ textChanged: function(oldRange, newRange)
+ {
+ if (!this._textChunks) {
+ this._buildChunks();
+ return;
}
+
+ var linesDiff = newRange.linesCount - oldRange.linesCount;
+ if (linesDiff) {
+ // Remove old chunks (if needed).
+ for (var chunkNumber = this._textChunks.length - 1; chunkNumber >= 0 ; --chunkNumber) {
+ var chunk = this._textChunks[chunkNumber];
+ if (chunk.startLine + chunk.linesCount <= this._textModel.linesCount)
+ break;
+ chunk.expanded = false;
+ this._container.removeChild(chunk.element);
+ }
+ this._textChunks.length = chunkNumber + 1;
+
+ // Add new chunks (if needed).
+ var totalLines = 0;
+ if (this._textChunks.length) {
+ var lastChunk = this._textChunks[this._textChunks.length - 1];
+ totalLines = lastChunk.startLine + lastChunk.linesCount;
+ }
+ for (var i = totalLines; i < this._textModel.linesCount; i += this._defaultChunkSize) {
+ var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
+ this._textChunks.push(chunk);
+ this._container.appendChild(chunk.element);
+ }
+ this._repaintAll();
+ } else {
+ // Decorations may have been removed, so we may have to sync those lines.
+ var chunkNumber = this._chunkNumberForLine(newRange.startLine);
+ var chunk = this._textChunks[chunkNumber];
+ while (chunk && chunk.startLine <= newRange.endLine) {
+ if (chunk.linesCount === 1)
+ this._syncDecorationsForLineListener(chunk.startLine);
+ chunk = this._textChunks[++chunkNumber];
+ }
+ }
+ },
+
+ syncClientHeight: function(clientHeight)
+ {
+ if (this.element.offsetHeight > clientHeight)
+ this._container.style.setProperty("padding-bottom", (this.element.offsetHeight - clientHeight) + "px");
+ else
+ this._container.style.removeProperty("padding-bottom");
}
}
@@ -444,9 +571,8 @@ WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine)
this.element.appendChild(outerSpan);
} else {
var lineNumbers = [];
- for (var i = startLine; i < endLine; ++i) {
+ for (var i = startLine; i < endLine; ++i)
lineNumbers.push(i + 1);
- }
this.element.textContent = lineNumbers.join("\n");
}
}
@@ -454,16 +580,18 @@ WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine)
WebInspector.TextEditorGutterChunk.prototype = {
addDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.addStyleClass(decoration);
- }
+ this._textViewer.endDomUpdates();
},
removeDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.removeStyleClass(decoration);
- }
+ this._textViewer.endDomUpdates();
},
get expanded()
@@ -484,6 +612,8 @@ WebInspector.TextEditorGutterChunk.prototype = {
if (this.linesCount === 1)
return;
+ this._textViewer.beginDomUpdates();
+
if (expanded) {
this._expandedLineRows = [];
var parentElement = this.element.parentElement;
@@ -503,12 +633,14 @@ WebInspector.TextEditorGutterChunk.prototype = {
elementInserted = true;
parentElement.insertBefore(this.element, lineRow);
}
- this._textViewer._cachedRows.push(lineRow);
parentElement.removeChild(lineRow);
}
+ this._textViewer._cachedRows.push(lineRow);
}
delete this._expandedLineRows;
}
+
+ this._textViewer.endDomUpdates();
},
get height()
@@ -518,6 +650,11 @@ WebInspector.TextEditorGutterChunk.prototype = {
return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
},
+ get offsetTop()
+ {
+ return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop;
+ },
+
_createRow: function(lineNumber)
{
var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
@@ -528,27 +665,42 @@ WebInspector.TextEditorGutterChunk.prototype = {
}
}
-WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener)
+WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode)
{
WebInspector.TextEditorChunkedPanel.call(this, textModel);
this._syncScrollListener = syncScrollListener;
this._syncDecorationsForLineListener = syncDecorationsForLineListener;
+ this._enterTextChangeMode = enterTextChangeMode;
+ this._exitTextChangeMode = exitTextChangeMode;
this._url = url;
this._highlighter = new WebInspector.TextEditorHighlighter(textModel, this._highlightDataReady.bind(this));
+ this._readOnly = true;
this.element = document.createElement("div");
this.element.className = "text-editor-contents";
this.element.tabIndex = 0;
+ this._container = document.createElement("div");
+ this._container.className = "inner-container";
+ this._container.tabIndex = 0;
+ this.element.appendChild(this._container);
+
this.element.addEventListener("scroll", this._scroll.bind(this), false);
- this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);
- var handleDOMUpdates = this._handleDOMUpdates.bind(this);
- this.element.addEventListener("DOMCharacterDataModified", handleDOMUpdates, false);
- this.element.addEventListener("DOMNodeInserted", handleDOMUpdates, false);
- this.element.addEventListener("DOMNodeRemoved", handleDOMUpdates, false);
+ // FIXME: Remove old live editing functionality and Preferences.sourceEditorEnabled flag.
+ if (!Preferences.sourceEditorEnabled)
+ this._container.addEventListener("keydown", this._handleKeyDown.bind(this), false);
+
+ // In WebKit the DOMNodeRemoved event is fired AFTER the node is removed, thus it should be
+ // attached to all DOM nodes that we want to track. Instead, we attach the DOMNodeRemoved
+ // listeners only on the line rows, and use DOMSubtreeModified to track node removals inside
+ // the line rows. For more info see: https://bugs.webkit.org/show_bug.cgi?id=55666
+ this._handleDOMUpdatesCallback = this._handleDOMUpdates.bind(this);
+ this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false);
+ this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false);
+ this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false);
this.freeCachedElements();
this._buildChunks();
@@ -560,6 +712,21 @@ WebInspector.TextEditorMainPanel.prototype = {
this._highlighter.mimeType = mimeType;
},
+ set readOnly(readOnly)
+ {
+ // FIXME: Remove the Preferences.sourceEditorEnabled flag.
+ if (!Preferences.sourceEditorEnabled)
+ return;
+
+ this.beginDomUpdates();
+ this._readOnly = readOnly;
+ if (this._readOnly)
+ this._container.removeStyleClass("text-editor-editable");
+ else
+ this._container.addStyleClass("text-editor-editable");
+ this.endDomUpdates();
+ },
+
markAndRevealRange: function(range)
{
if (this._rangeToMark) {
@@ -653,6 +820,9 @@ WebInspector.TextEditorMainPanel.prototype = {
_buildChunks: function()
{
this._highlighter.reset();
+ for (var i = 0; i < this._textModel.linesCount; ++i)
+ this._textModel.removeAttribute(i, "highlight");
+
WebInspector.TextEditorChunkedPanel.prototype._buildChunks.call(this);
},
@@ -672,9 +842,8 @@ WebInspector.TextEditorMainPanel.prototype = {
this._highlighter.highlight(lastVisibleLine);
delete this._muteHighlightListener;
- for (var i = 0; i < this._textChunks.length; ++i) {
+ for (var i = 0; i < this._textChunks.length; ++i)
this._textChunks[i].expanded = (fromIndex <= i && i < toIndex);
- }
this._restoreSelection(selection);
},
@@ -686,13 +855,46 @@ WebInspector.TextEditorMainPanel.prototype = {
this._paintLines(fromLine, toLine, true /*restoreSelection*/);
},
+ _markSkippedPaintLines: function(startLine, endLine)
+ {
+ if (!this._skippedPaintLines)
+ this._skippedPaintLines = [ { startLine: startLine, endLine: endLine } ];
+ else {
+ for (var i = 0; i < this._skippedPaintLines.length; ++i) {
+ var chunk = this._skippedPaintLines[i];
+ if (chunk.startLine <= endLine && chunk.endLine >= startLine) {
+ chunk.startLine = Math.min(chunk.startLine, startLine);
+ chunk.endLine = Math.max(chunk.endLine, endLine);
+ return;
+ }
+ }
+ this._skippedPaintLines.push({ startLine: startLine, endLine: endLine });
+ }
+ },
+
+ _paintSkippedLines: function()
+ {
+ if (!this._skippedPaintLines || this._dirtyLines)
+ return;
+ for (var i = 0; i < this._skippedPaintLines.length; ++i) {
+ var chunk = this._skippedPaintLines[i];
+ this._paintLines(chunk.startLine, chunk.endLine);
+ }
+ delete this._skippedPaintLines;
+ },
+
_paintLines: function(fromLine, toLine, restoreSelection)
{
+ if (this._dirtyLines) {
+ this._markSkippedPaintLines(fromLine, toLine);
+ return;
+ }
+
var selection;
- var chunk = this._chunkForLine(fromLine);
+ var chunk = this.chunkForLine(fromLine);
for (var i = fromLine; i < toLine; ++i) {
if (i >= chunk.startLine + chunk.linesCount)
- chunk = this._chunkForLine(i);
+ chunk = this.chunkForLine(i);
var lineRow = chunk.getExpandedLineRow(i);
if (!lineRow)
continue;
@@ -706,46 +908,56 @@ WebInspector.TextEditorMainPanel.prototype = {
_paintLine: function(lineRow, lineNumber)
{
- var highlight = this._textModel.getAttribute(lineNumber, "highlight");
- if (!highlight) {
- if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
- this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+ if (this._dirtyLines) {
+ this._markSkippedPaintLines(lineNumber, lineNumber + 1);
return;
}
- lineRow.removeChildren();
- var line = this._textModel.line(lineNumber);
- if (!line)
- lineRow.appendChild(document.createElement("br"));
-
- var plainTextStart = -1;
- for (var j = 0; j < line.length;) {
- if (j > 1000) {
- // This line is too long - do not waste cycles on minified js highlighting.
- if (plainTextStart === -1)
- plainTextStart = j;
- break;
+ this.beginDomUpdates();
+ try {
+ var highlight = this._textModel.getAttribute(lineNumber, "highlight");
+ if (!highlight) {
+ if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
+ this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+ return;
}
- var attribute = highlight[j];
- if (!attribute || !attribute.tokenType) {
- if (plainTextStart === -1)
- plainTextStart = j;
- j++;
- } else {
- if (plainTextStart !== -1) {
- this._appendTextNode(lineRow, line.substring(plainTextStart, j));
- plainTextStart = -1;
+
+ lineRow.removeChildren();
+ var line = this._textModel.line(lineNumber);
+ if (!line)
+ lineRow.appendChild(document.createElement("br"));
+
+ var plainTextStart = -1;
+ for (var j = 0; j < line.length;) {
+ if (j > 1000) {
+ // This line is too long - do not waste cycles on minified js highlighting.
+ if (plainTextStart === -1)
+ plainTextStart = j;
+ break;
+ }
+ var attribute = highlight[j];
+ if (!attribute || !attribute.tokenType) {
+ if (plainTextStart === -1)
+ plainTextStart = j;
+ j++;
+ } else {
+ if (plainTextStart !== -1) {
+ this._appendTextNode(lineRow, line.substring(plainTextStart, j));
+ plainTextStart = -1;
+ }
+ this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType);
+ j += attribute.length;
}
- this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType);
- j += attribute.length;
}
+ if (plainTextStart !== -1)
+ this._appendTextNode(lineRow, line.substring(plainTextStart, line.length));
+ if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
+ this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
+ if (lineRow.decorationsElement)
+ lineRow.appendChild(lineRow.decorationsElement);
+ } finally {
+ this.endDomUpdates();
}
- if (plainTextStart !== -1)
- this._appendTextNode(lineRow, line.substring(plainTextStart, line.length));
- if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
- this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
- if (lineRow.decorationsElement)
- lineRow.appendChild(lineRow.decorationsElement);
},
_releaseLinesHighlight: function(lineRow)
@@ -774,7 +986,7 @@ WebInspector.TextEditorMainPanel.prototype = {
return null;
var selectionRange = selection.getRangeAt(0);
// Selection may be outside of the viewer.
- if (!this.element.isAncestor(selectionRange.startContainer) || !this.element.isAncestor(selectionRange.endContainer))
+ if (!this._container.isAncestor(selectionRange.startContainer) || !this._container.isAncestor(selectionRange.endContainer))
return null;
var start = this._selectionToPosition(selectionRange.startContainer, selectionRange.startOffset);
var end = selectionRange.collapsed ? start : this._selectionToPosition(selectionRange.endContainer, selectionRange.endOffset);
@@ -795,9 +1007,9 @@ WebInspector.TextEditorMainPanel.prototype = {
_selectionToPosition: function(container, offset)
{
- if (container === this.element && offset === 0)
+ if (container === this._container && offset === 0)
return { line: 0, column: 0 };
- if (container === this.element && offset === 1)
+ if (container === this._container && offset === 1)
return { line: this._textModel.linesCount - 1, column: this._textModel.lineLength(this._textModel.linesCount - 1) };
var lineRow = container.enclosingNodeOrSelfWithNodeName("DIV");
@@ -835,7 +1047,7 @@ WebInspector.TextEditorMainPanel.prototype = {
_positionToSelection: function(line, column)
{
- var chunk = this._chunkForLine(line);
+ var chunk = this.chunkForLine(line);
var lineRow = chunk.getExpandedLineRow(line);
if (lineRow)
var rangeBoundary = lineRow.rangeBoundaryForOffset(column);
@@ -909,17 +1121,268 @@ WebInspector.TextEditorMainPanel.prototype = {
_handleDOMUpdates: function(e)
{
+ if (this._domUpdateCoalescingLevel)
+ return;
+
var target = e.target;
+ if (target === this._container)
+ return;
+
var lineRow = target.enclosingNodeOrSelfWithClass("webkit-line-content");
- if (lineRow === target || !lineRow || !lineRow.decorationsElement || !lineRow.decorationsElement.isAncestor(target))
+ if (!lineRow)
return;
- if (this._syncDecorationsForLineListener) {
- // Wait until this event is processed and only then sync the sizes. This is necessary in
- // case of the DOMNodeRemoved event, because it is dispatched before the removal takes place.
- setTimeout(function() {
+
+ if (lineRow.decorationsElement && (lineRow.decorationsElement === target || lineRow.decorationsElement.isAncestor(target))) {
+ if (this._syncDecorationsForLineListener)
this._syncDecorationsForLineListener(lineRow.lineNumber);
- }.bind(this), 0);
+ return;
+ }
+
+ if (this._readOnly)
+ return;
+
+ var lineNumber = lineRow.lineNumber;
+ if (this._dirtyLines) {
+ this._dirtyLines.start = Math.min(this._dirtyLines.start, lineNumber);
+ this._dirtyLines.end = Math.max(this._dirtyLines.end, lineNumber + 1);
+ } else {
+ this._dirtyLines = { start: lineNumber, end: lineNumber + 1 };
+ setTimeout(this._applyDomUpdates.bind(this), 0);
+ // Remove marked ranges, if any.
+ this.markAndRevealRange(null);
+ }
+ },
+
+ _applyDomUpdates: function()
+ {
+ if (!this._dirtyLines)
+ return;
+
+ // Check if the editor had been set readOnly by the moment when this async callback got executed.
+ if (this._readOnly) {
+ delete this._dirtyLines;
+ return;
+ }
+
+ // This is a "foreign" call outside of this class. Should be before we delete the dirty lines flag.
+ this._enterTextChangeMode();
+
+ var dirtyLines = this._dirtyLines;
+ delete this._dirtyLines;
+
+ var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start);
+ var startLine = this._textChunks[firstChunkNumber].startLine;
+ var endLine = this._textModel.linesCount;
+
+ // Collect lines.
+ var firstLineRow;
+ if (firstChunkNumber) {
+ var chunk = this._textChunks[firstChunkNumber - 1];
+ firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
+ firstLineRow = firstLineRow.nextSibling;
+ } else
+ firstLineRow = this._container.firstChild;
+
+ var lines = [];
+ for (var lineRow = firstLineRow; lineRow; lineRow = lineRow.nextSibling) {
+ if (typeof lineRow.lineNumber === "number" && lineRow.lineNumber >= dirtyLines.end) {
+ endLine = lineRow.lineNumber;
+ break;
+ }
+ // Update with the newest lineNumber, so that the call to the _getSelection method below should work.
+ lineRow.lineNumber = startLine + lines.length;
+ this._collectLinesFromDiv(lines, lineRow);
+ }
+
+ // Try to decrease the range being replaced if possible.
+ var startOffset = 0;
+ while (startLine < dirtyLines.start && startOffset < lines.length) {
+ if (this._textModel.line(startLine) !== lines[startOffset])
+ break;
+ ++startOffset;
+ ++startLine;
+ }
+
+ var endOffset = lines.length;
+ while (endLine > dirtyLines.end && endOffset > startOffset) {
+ if (this._textModel.line(endLine - 1) !== lines[endOffset - 1])
+ break;
+ --endOffset;
+ --endLine;
+ }
+
+ lines = lines.slice(startOffset, endOffset);
+
+ var selection = this._getSelection();
+
+ if (lines.length === 0 && endLine < this._textModel.linesCount) {
+ var oldRange = new WebInspector.TextRange(startLine, 0, endLine, 0);
+ var newRange = this._textModel.setText(oldRange, "");
+ } else {
+ var oldRange = new WebInspector.TextRange(startLine, 0, endLine - 1, this._textModel.lineLength(endLine - 1));
+ var newRange = this._textModel.setText(oldRange, lines.join("\n"));
+ }
+
+ this.beginDomUpdates();
+ this._removeDecorationsInRange(oldRange);
+ this._updateChunksForRanges(oldRange, newRange);
+ this._updateHighlightsForRange(newRange);
+ this._paintSkippedLines();
+ this.endDomUpdates();
+
+ this._restoreSelection(selection);
+
+ this._exitTextChangeMode(oldRange, newRange);
+ },
+
+ _removeDecorationsInRange: function(range)
+ {
+ for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) {
+ var chunk = this._textChunks[i];
+ if (chunk.startLine > range.endLine)
+ break;
+ chunk.removeAllDecorations();
+ }
+ },
+
+ _updateChunksForRanges: function(oldRange, newRange)
+ {
+ // Update the chunks in range: firstChunkNumber <= index <= lastChunkNumber
+ var firstChunkNumber = this._chunkNumberForLine(oldRange.startLine);
+ var lastChunkNumber = firstChunkNumber;
+ while (lastChunkNumber + 1 < this._textChunks.length) {
+ if (this._textChunks[lastChunkNumber + 1].startLine > oldRange.endLine)
+ break;
+ ++lastChunkNumber;
+ }
+
+ var startLine = this._textChunks[firstChunkNumber].startLine;
+ var linesCount = this._textChunks[lastChunkNumber].startLine + this._textChunks[lastChunkNumber].linesCount - startLine;
+ var linesDiff = newRange.linesCount - oldRange.linesCount;
+ linesCount += linesDiff;
+
+ if (linesDiff) {
+ // Lines shifted, update the line numbers of the chunks below.
+ for (var chunkNumber = lastChunkNumber + 1; chunkNumber < this._textChunks.length; ++chunkNumber)
+ this._textChunks[chunkNumber].startLine += linesDiff;
+ }
+
+ var firstLineRow;
+ if (firstChunkNumber) {
+ var chunk = this._textChunks[firstChunkNumber - 1];
+ firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
+ firstLineRow = firstLineRow.nextSibling;
+ } else
+ firstLineRow = this._container.firstChild;
+
+ // Most frequent case: a chunk remained the same.
+ for (var chunkNumber = firstChunkNumber; chunkNumber <= lastChunkNumber; ++chunkNumber) {
+ var chunk = this._textChunks[chunkNumber];
+ var lineNumber = chunk.startLine;
+ for (var lineRow = firstLineRow; lineRow && lineNumber < chunk.startLine + chunk.linesCount; lineRow = lineRow.nextSibling) {
+ if (lineRow.lineNumber !== lineNumber || lineRow !== chunk.getExpandedLineRow(lineNumber) || lineRow.textContent !== this._textModel.line(lineNumber) || !lineRow.firstChild)
+ break;
+ ++lineNumber;
+ }
+ if (lineNumber < chunk.startLine + chunk.linesCount)
+ break;
+ chunk.updateCollapsedLineRow();
+ ++firstChunkNumber;
+ firstLineRow = lineRow;
+ startLine += chunk.linesCount;
+ linesCount -= chunk.linesCount;
+ }
+
+ if (firstChunkNumber > lastChunkNumber && linesCount === 0)
+ return;
+
+ // Maybe merge with the next chunk, so that we should not create 1-sized chunks when appending new lines one by one.
+ var chunk = this._textChunks[lastChunkNumber + 1];
+ var linesInLastChunk = linesCount % this._defaultChunkSize;
+ if (chunk && !chunk.decorated && linesInLastChunk > 0 && linesInLastChunk + chunk.linesCount <= this._defaultChunkSize) {
+ ++lastChunkNumber;
+ linesCount += chunk.linesCount;
+ }
+
+ var scrollTop = this.element.scrollTop;
+ var scrollLeft = this.element.scrollLeft;
+
+ // Delete all DOM elements that were either controlled by the old chunks, or have just been inserted.
+ var firstUnmodifiedLineRow = null;
+ var chunk = this._textChunks[lastChunkNumber + 1];
+ if (chunk) {
+ firstUnmodifiedLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine) : chunk.element;
}
+ while (firstLineRow && firstLineRow !== firstUnmodifiedLineRow) {
+ var lineRow = firstLineRow;
+ firstLineRow = firstLineRow.nextSibling;
+ this._container.removeChild(lineRow);
+ }
+
+ // Replace old chunks with the new ones.
+ for (var chunkNumber = firstChunkNumber; linesCount > 0; ++chunkNumber) {
+ var chunkLinesCount = Math.min(this._defaultChunkSize, linesCount);
+ var newChunk = this._createNewChunk(startLine, startLine + chunkLinesCount);
+ this._container.insertBefore(newChunk.element, firstUnmodifiedLineRow);
+
+ if (chunkNumber <= lastChunkNumber)
+ this._textChunks[chunkNumber] = newChunk;
+ else
+ this._textChunks.splice(chunkNumber, 0, newChunk);
+ startLine += chunkLinesCount;
+ linesCount -= chunkLinesCount;
+ }
+ if (chunkNumber <= lastChunkNumber)
+ this._textChunks.splice(chunkNumber, lastChunkNumber - chunkNumber + 1);
+
+ this.element.scrollTop = scrollTop;
+ this.element.scrollLeft = scrollLeft;
+ },
+
+ _updateHighlightsForRange: function(range)
+ {
+ var visibleFrom = this.element.scrollTop;
+ var visibleTo = this.element.scrollTop + this.element.clientHeight;
+
+ var result = this._findVisibleChunks(visibleFrom, visibleTo);
+ var chunk = this._textChunks[result.end - 1];
+ var lastVisibleLine = chunk.startLine + chunk.linesCount;
+
+ lastVisibleLine = Math.max(lastVisibleLine, range.endLine);
+
+ var updated = this._highlighter.updateHighlight(range.startLine, lastVisibleLine);
+ if (!updated) {
+ // Highlights for the chunks below are invalid, so just collapse them.
+ for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i)
+ this._textChunks[i].expanded = false;
+ }
+
+ this._repaintAll();
+ },
+
+ _collectLinesFromDiv: function(lines, element)
+ {
+ var textContents = [];
+ var node = element.traverseNextNode(element);
+ while (node) {
+ if (element.decorationsElement === node) {
+ node = node.nextSibling;
+ continue;
+ }
+ if (node.nodeName.toLowerCase() === "br")
+ textContents.push("\n");
+ else if (node.nodeType === Node.TEXT_NODE)
+ textContents.push(node.textContent);
+ node = node.traverseNextNode(element);
+ }
+
+ var textContent = textContents.join("");
+ // The last \n (if any) does not "count" in a DIV.
+ textContent = textContent.replace(/\n$/, "");
+
+ textContents = textContent.split("\n");
+ for (var i = 0; i < textContents.length; ++i)
+ lines.push(textContents[i]);
}
}
@@ -933,49 +1396,73 @@ WebInspector.TextEditorMainChunk = function(textViewer, startLine, endLine)
this.element = document.createElement("div");
this.element.lineNumber = startLine;
this.element.className = "webkit-line-content";
+ this.element.addEventListener("DOMNodeRemoved", this._textViewer._handleDOMUpdatesCallback, false);
- this.startLine = startLine;
+ this._startLine = startLine;
endLine = Math.min(this._textModel.linesCount, endLine);
this.linesCount = endLine - startLine;
this._expanded = false;
- var lines = [];
- for (var i = startLine; i < endLine; ++i) {
- lines.push(this._textModel.line(i));
- }
-
- this.element.textContent = lines.join("\n");
-
- // The last empty line will get swallowed otherwise.
- if (!lines[lines.length - 1])
- this.element.appendChild(document.createElement("br"));
+ this.updateCollapsedLineRow();
}
WebInspector.TextEditorMainChunk.prototype = {
addDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.addStyleClass(decoration);
- return;
- }
- if (!this.element.decorationsElement) {
- this.element.decorationsElement = document.createElement("div");
- this.element.decorationsElement.className = "webkit-line-decorations";
- this.element.appendChild(this.element.decorationsElement);
+ else {
+ if (!this.element.decorationsElement) {
+ this.element.decorationsElement = document.createElement("div");
+ this.element.decorationsElement.className = "webkit-line-decorations";
+ this.element.appendChild(this.element.decorationsElement);
+ }
+ this.element.decorationsElement.appendChild(decoration);
}
- this.element.decorationsElement.appendChild(decoration);
+ this._textViewer.endDomUpdates();
},
removeDecoration: function(decoration)
{
- if (typeof decoration === "string") {
+ this._textViewer.beginDomUpdates();
+ if (typeof decoration === "string")
this.element.removeStyleClass(decoration);
- return;
+ else if (this.element.decorationsElement)
+ this.element.decorationsElement.removeChild(decoration);
+ this._textViewer.endDomUpdates();
+ },
+
+ removeAllDecorations: function()
+ {
+ this._textViewer.beginDomUpdates();
+ this.element.className = "webkit-line-content";
+ if (this.element.decorationsElement) {
+ this.element.removeChild(this.element.decorationsElement);
+ delete this.element.decorationsElement;
+ }
+ this._textViewer.endDomUpdates();
+ },
+
+ get decorated()
+ {
+ return this.element.className !== "webkit-line-content" || !!(this.element.decorationsElement && this.element.decorationsElement.firstChild);
+ },
+
+ get startLine()
+ {
+ return this._startLine;
+ },
+
+ set startLine(startLine)
+ {
+ this._startLine = startLine;
+ this.element.lineNumber = startLine;
+ if (this._expandedLineRows) {
+ for (var i = 0; i < this._expandedLineRows.length; ++i)
+ this._expandedLineRows[i].lineNumber = startLine + i;
}
- if (!this.element.decorationsElement)
- return;
- this.element.decorationsElement.removeChild(decoration);
},
get expanded()
@@ -996,6 +1483,8 @@ WebInspector.TextEditorMainChunk.prototype = {
return;
}
+ this._textViewer.beginDomUpdates();
+
if (expanded) {
this._expandedLineRows = [];
var parentElement = this.element.parentElement;
@@ -1016,12 +1505,14 @@ WebInspector.TextEditorMainChunk.prototype = {
elementInserted = true;
parentElement.insertBefore(this.element, lineRow);
}
- this._textViewer._releaseLinesHighlight(lineRow);
parentElement.removeChild(lineRow);
}
+ this._textViewer._releaseLinesHighlight(lineRow);
}
delete this._expandedLineRows;
}
+
+ this._textViewer.endDomUpdates();
},
get height()
@@ -1031,11 +1522,17 @@ WebInspector.TextEditorMainChunk.prototype = {
return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
},
+ get offsetTop()
+ {
+ return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop;
+ },
+
_createRow: function(lineNumber)
{
var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
lineRow.lineNumber = lineNumber;
lineRow.className = "webkit-line-content";
+ lineRow.addEventListener("DOMNodeRemoved", this._textViewer._handleDOMUpdatesCallback, false);
lineRow.textContent = this._textModel.line(lineNumber);
if (!lineRow.textContent)
lineRow.appendChild(document.createElement("br"));
@@ -1049,5 +1546,22 @@ WebInspector.TextEditorMainChunk.prototype = {
if (!this._expandedLineRows)
return this.element;
return this._expandedLineRows[lineNumber - this.startLine];
+ },
+
+ updateCollapsedLineRow: function()
+ {
+ if (this.linesCount === 1 && this._expanded)
+ return;
+
+ var lines = [];
+ for (var i = this.startLine; i < this.startLine + this.linesCount; ++i)
+ lines.push(this._textModel.line(i));
+
+ this.element.removeChildren();
+ this.element.textContent = lines.join("\n");
+
+ // The last empty line will get swallowed otherwise.
+ if (!lines[lines.length - 1])
+ this.element.appendChild(document.createElement("br"));
}
}
diff --git a/Source/WebCore/inspector/front-end/TimelinePanel.js b/Source/WebCore/inspector/front-end/TimelinePanel.js
index 1d8b9c9..62c5de0 100644
--- a/Source/WebCore/inspector/front-end/TimelinePanel.js
+++ b/Source/WebCore/inspector/front-end/TimelinePanel.js
@@ -270,10 +270,10 @@ WebInspector.TimelinePanel.prototype = {
_toggleTimelineButtonClicked: function()
{
if (this.toggleTimelineButton.toggled)
- InspectorBackend.stopTimelineProfiler();
+ TimelineAgent.stop();
else {
this._clearPanel();
- InspectorBackend.startTimelineProfiler();
+ TimelineAgent.start();
}
},
@@ -865,7 +865,6 @@ WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, pane
this.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : this.startTime;
this._selfTime = this.endTime - this.startTime;
this._lastChildEndTime = this.endTime;
- this.originalRecordForTests = record;
if (record.stackTrace && record.stackTrace.length)
this.stackTrace = record.stackTrace;
this.totalHeapSize = record.totalHeapSize;
diff --git a/Source/WebCore/inspector/front-end/Toolbar.js b/Source/WebCore/inspector/front-end/Toolbar.js
new file mode 100755
index 0000000..d1cc9a6
--- /dev/null
+++ b/Source/WebCore/inspector/front-end/Toolbar.js
@@ -0,0 +1,220 @@
+ /*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
+ * Copyright (C) 2009 Joseph Pecoraro
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Toolbar = function()
+{
+ this.element = document.getElementById("toolbar");
+ this.element.addEventListener("mousedown", this._toolbarDragStart.bind(this), true);
+
+ this._dropdownButton = document.getElementById("toolbar-dropdown-arrow");
+ this._dropdownButton.addEventListener("click", this._toggleDropdown.bind(this), false);
+
+ document.getElementById("close-button-left").addEventListener("click", this._onClose, true);
+ document.getElementById("close-button-right").addEventListener("click", this._onClose, true);
+}
+
+WebInspector.Toolbar.prototype = {
+ resize: function()
+ {
+ this._updateDropdownButtonAndHideDropdown();
+ },
+
+ addPanel: function(panel)
+ {
+ this.element.appendChild(panel.toolbarItem);
+ this.resize();
+ },
+
+ _toolbarDragStart: function(event)
+ {
+ if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
+ return;
+
+ var target = event.target;
+ if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
+ return;
+
+ if (target !== this.element && !target.hasStyleClass("toolbar-item"))
+ return;
+
+ this.element.lastScreenX = event.screenX;
+ this.element.lastScreenY = event.screenY;
+
+ WebInspector.elementDragStart(this.element, this._toolbarDrag.bind(this), this._toolbarDragEnd.bind(this), event, (WebInspector.attached ? "row-resize" : "default"));
+ },
+
+ _toolbarDragEnd: function(event)
+ {
+ WebInspector.elementDragEnd(event);
+
+ delete this.element.lastScreenX;
+ delete this.element.lastScreenY;
+ },
+
+ _toolbarDrag: function(event)
+ {
+ if (WebInspector.attached) {
+ var height = window.innerHeight - (event.screenY - this.element.lastScreenY);
+
+ InspectorFrontendHost.setAttachedWindowHeight(height);
+ } else {
+ var x = event.screenX - this.element.lastScreenX;
+ var y = event.screenY - this.element.lastScreenY;
+
+ // We cannot call window.moveBy here because it restricts the movement
+ // of the window at the edges.
+ InspectorFrontendHost.moveWindowBy(x, y);
+ }
+
+ this.element.lastScreenX = event.screenX;
+ this.element.lastScreenY = event.screenY;
+
+ event.preventDefault();
+ },
+
+ _onClose: function()
+ {
+ WebInspector.close();
+ },
+
+ _setDropdownVisible: function(visible)
+ {
+ if (!this._dropdown) {
+ if (!visible)
+ return;
+ this._dropdown = new WebInspector.ToolbarDropdown();
+ }
+ if (visible)
+ this._dropdown.show();
+ else
+ this._dropdown.hide();
+ },
+
+ _toggleDropdown: function()
+ {
+ this._setDropdownVisible(!this._dropdown || !this._dropdown.visible);
+ },
+
+ _updateDropdownButtonAndHideDropdown: function()
+ {
+ this._setDropdownVisible(false);
+
+ var toolbar = document.getElementById("toolbar");
+ if (this.element.scrollHeight > this.element.clientHeight)
+ this._dropdownButton.removeStyleClass("hidden");
+ else
+ this._dropdownButton.addStyleClass("hidden");
+ }
+};
+
+WebInspector.Toolbar.createPanelToolbarItem = function(panel)
+{
+ var toolbarItem = document.createElement("button");
+ toolbarItem.className = "toolbar-item toggleable";
+ toolbarItem.panel = panel;
+ toolbarItem.addStyleClass(panel._panelName);
+ function onToolbarItemClicked()
+ {
+ WebInspector.toolbar._updateDropdownButtonAndHideDropdown();
+ WebInspector.currentPanel = panel;
+ }
+ toolbarItem.addEventListener("click", onToolbarItemClicked);
+
+ var iconElement = toolbarItem.createChild("div", "toolbar-icon");
+
+ if ("toolbarItemLabel" in panel)
+ toolbarItem.createChild("div", "toolbar-label").textContent = panel.toolbarItemLabel;
+
+ if (panel === WebInspector.currentPanel)
+ toolbarItem.addStyleClass("toggled-on");
+
+ return toolbarItem;
+}
+
+WebInspector.ToolbarDropdown = function()
+{
+ this._toolbar = document.getElementById("toolbar");
+ this._arrow = document.getElementById("toolbar-dropdown-arrow");
+ this.element = document.createElement("div");
+ this.element.id = "toolbar-dropdown";
+ this._contentElement = this.element.createChild("div", "scrollable-content");
+ this._contentElement.tabIndex = 0;
+ this._contentElement.addEventListener("keydown", this._onKeyDown.bind(this), true);
+}
+
+WebInspector.ToolbarDropdown.prototype = {
+ show: function()
+ {
+ if (this.visible)
+ return;
+ var style = this.element.style;
+ this._populate();
+ var top = this._arrow.totalOffsetTop + this._arrow.clientHeight;
+ this._arrow.addStyleClass("dropdown-visible");
+ this.element.style.top = top + "px";
+ this.element.style.left = this._arrow.totalOffsetLeft + "px";
+ this._contentElement.style.maxHeight = window.innerHeight - top - 20 + "px";
+ this._toolbar.appendChild(this.element);
+ WebInspector.currentFocusElement = this.contentElement;
+ },
+
+ hide: function()
+ {
+ if (!this.visible)
+ return;
+ this._arrow.removeStyleClass("dropdown-visible");
+ this.element.parentNode.removeChild(this.element);
+ this._contentElement.removeChildren();
+ },
+
+ get visible()
+ {
+ return !!this.element.parentNode;
+ },
+
+ _populate: function()
+ {
+ var toolbarItems = this._toolbar.querySelectorAll(".toolbar-item.toggleable");
+
+ for (var i = 0; i < toolbarItems.length; ++i) {
+ if (toolbarItems[i].offsetTop > 0)
+ this._contentElement.appendChild(WebInspector.Toolbar.createPanelToolbarItem(toolbarItems[i].panel));
+ }
+ },
+
+ _onKeyDown: function(event)
+ {
+ if (event.keyCode !== WebInspector.KeyboardShortcut.Keys.Esc.code)
+ return;
+ event.stopPropagation();
+ this.hide();
+ }
+};
diff --git a/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js b/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
index a6f59ca..bb3460d 100644
--- a/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js
@@ -120,7 +120,7 @@ WebInspector.WatchExpressionsSection.prototype = {
}
// TODO: pass exact injected script id.
- InspectorBackend.releaseWrapperObjectGroup(0, this._watchObjectGroupId)
+ RuntimeAgent.releaseObjectGroup(0, this._watchObjectGroupId)
var properties = [];
// Count the properties, so we known when to call this.updateProperties()
diff --git a/Source/WebCore/inspector/front-end/WebKit.qrc b/Source/WebCore/inspector/front-end/WebKit.qrc
index dd325ba..91d72d8 100644
--- a/Source/WebCore/inspector/front-end/WebKit.qrc
+++ b/Source/WebCore/inspector/front-end/WebKit.qrc
@@ -27,9 +27,11 @@
<file>Database.js</file>
<file>DatabaseQueryView.js</file>
<file>DatabaseTableView.js</file>
+ <file>DetailedHeapshotGridNodes.js</file>
<file>DetailedHeapshotView.js</file>
<file>DataGrid.js</file>
<file>DebuggerModel.js</file>
+ <file>DebuggerPresentationModel.js</file>
<file>DOMAgent.js</file>
<file>DOMStorage.js</file>
<file>DOMStorageItemsView.js</file>
@@ -85,6 +87,7 @@
<file>ScriptFormatter.js</file>
<file>ScriptFormatterWorker.js</file>
<file>ScriptsPanel.js</file>
+ <file>SearchController.js</file>
<file>Section.js</file>
<file>Settings.js</file>
<file>ShortcutsHelp.js</file>
@@ -110,6 +113,7 @@
<file>TimelineGrid.js</file>
<file>TimelineOverviewPane.js</file>
<file>TimelinePanel.js</file>
+ <file>Toolbar.js</file>
<file>TopDownProfileDataGridTree.js</file>
<file>treeoutline.js</file>
<file>utilities.js</file>
diff --git a/Source/WebCore/inspector/front-end/WorkersSidebarPane.js b/Source/WebCore/inspector/front-end/WorkersSidebarPane.js
index b254f3c..efdb936 100644
--- a/Source/WebCore/inspector/front-end/WorkersSidebarPane.js
+++ b/Source/WebCore/inspector/front-end/WorkersSidebarPane.js
@@ -74,9 +74,9 @@ WebInspector.WorkersSidebarPane.prototype = {
setInstrumentation: function(enabled)
{
- InspectorBackend.removeAllScriptsToEvaluateOnLoad();
+ InspectorAgent.removeAllScriptsToEvaluateOnLoad();
if (enabled)
- InspectorBackend.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")");
+ InspectorAgent.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")");
},
reset: function()
diff --git a/Source/WebCore/inspector/front-end/heapProfiler.css b/Source/WebCore/inspector/front-end/heapProfiler.css
index 03a6dd0..add02a1 100644
--- a/Source/WebCore/inspector/front-end/heapProfiler.css
+++ b/Source/WebCore/inspector/front-end/heapProfiler.css
@@ -134,3 +134,108 @@
width: 50%;
left: 25%;
}
+
+.detailed-heapshot-view {
+ display: none;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ -webkit-box-orient: vertical;
+}
+
+.detailed-heapshot-view.visible {
+ display: -webkit-box;
+}
+
+.detailed-heapshot-view .view {
+ display: none;
+ -webkit-box-flex: 3;
+ -webkit-box-orient: vertical;
+}
+
+.detailed-heapshot-view .view.visible {
+ display: -webkit-box;
+}
+
+.detailed-heapshot-view .data-grid {
+ border: none;
+ position: relative;
+ -webkit-box-flex: 1;
+}
+
+.detailed-heapshot-view .data-grid td.count-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.addedCount-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.removedCount-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.countDelta-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.addedSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.removedSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.sizeDelta-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.shallowSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .data-grid td.retainedSize-column {
+ text-align: right;
+}
+
+.detailed-heapshot-view .console-formatted-object, .console-formatted-node {
+ display: inline;
+ position: static;
+}
+
+.detailed-heapshot-view .delimiter {
+ height: 24px;
+ background-color: #d6dde5;
+}
+
+.detailed-heapshot-view .retaining-paths-view {
+ -webkit-box-flex: 1;
+}
+
+.detailed-heapshot-view .retaining-paths-view .title {
+ background-color: rgb(235, 235, 235);
+ background-image: url(Images/statusbarBackground.png);
+ background-repeat: repeat-x;
+ height: 23px;
+ font: -webkit-small-control;
+ font-weight: bold;
+ color: rgb(48, 48, 48);
+ text-shadow: rgba(255, 255, 255, 0.75) 0 1px 0;
+}
+
+.detailed-heapshot-view .retaining-paths-view .title > span {
+ vertical-align: middle;
+ margin-left: 4px;
+}
+
+.heapshot-help-status-bar-item .glyph {
+ -webkit-mask-image: url(Images/helpButtonGlyph.png);
+}
+
+table.heapshot-help {
+ border-spacing: 12px 2px;
+}
diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css
index c992806..a7bd3b3 100644
--- a/Source/WebCore/inspector/front-end/inspector.css
+++ b/Source/WebCore/inspector/front-end/inspector.css
@@ -76,7 +76,6 @@ img {
left: 0;
right: 0;
height: 56px;
- display: -webkit-box;
padding: 0 5px;
background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
border-bottom: 1px solid rgb(80, 80, 80);
@@ -111,32 +110,23 @@ body.attached.inactive #toolbar {
}
.toolbar-item {
- display: -webkit-box;
- padding: 4px 6px;
margin: 0;
+ padding: 0 6px;
background-color: transparent;
border-style: none;
border-color: transparent;
- -webkit-box-orient: vertical;
- -webkit-box-align: center;
- -webkit-box-pack: end;
+}
+
+.toolbar-item.toggleable {
+ padding-top: 4px;
}
.toolbar-item.toggleable.toggled-on {
border-width: 0 2px 0 2px;
- padding: 4px 4px;
+ padding: 4px 4px 0 4px;
-webkit-border-image: url(Images/toolbarItemSelected.png) 0 2 0 2;
}
-.toolbar-item.flexable-space {
- -webkit-box-flex: 1;
- visibility: hidden;
-}
-
-.toolbar-item input {
- margin-bottom: 8px;
-}
-
.toolbar-icon {
display: inline-block;
width: 32px;
@@ -144,7 +134,8 @@ body.attached.inactive #toolbar {
-webkit-background-size: 100% auto;
}
-body.attached .toolbar-icon {
+body.attached .toolbar-icon,
+#toolbar-dropdown .toolbar-icon {
width: 24px;
height: 24px;
vertical-align: middle;
@@ -168,9 +159,9 @@ body.attached .toolbar-item:active .toolbar-icon {
text-shadow: none;
}
-body.attached .toolbar-label {
+body.attached .toolbar-label,
+#toolbar-dropdown .toolbar-label {
display: inline-block;
- vertical-align: middle;
margin-left: 3px;
}
@@ -178,25 +169,145 @@ body.attached #search-toolbar-label {
display: none;
}
+#toolbar-controls {
+ float: right;
+ display: -webkit-box;
+ -webkit-box-align: center;
+ height: 100%;
+}
+
+#toolbar-dropdown-arrow {
+ font-size: 16px;
+ font-weight: bold;
+ border: 0;
+ background-color: transparent;
+ -webkit-border-radius: 5px;
+ text-shadow: none;
+}
+
+body.attached #toolbar-dropdown-arrow {
+ font-size: 14px;
+ padding-bottom: 4px;
+}
+
+#toolbar-dropdown-arrow.dropdown-visible {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(251, 251, 251, 0.9)), to(rgba(231, 231, 231, 0.9)));
+}
+
+#toolbar-dropdown-arrow:hover {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(191, 191, 191, 0.7)), to(rgba(171, 171, 171, 0.5)));
+}
+
+#toolbar-dropdown-arrow:active {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(111, 111, 111, 0.8)), to(rgba(91, 91, 91, 0.8)));
+}
+
+#toolbar-dropdown {
+ position: absolute;
+ z-index: 1000;
+ -webkit-box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.4);
+ border: 1px solid rgb(128, 128, 128);
+ padding: 4px;
+ background-color: inherit;
+ background-image: inherit;
+}
+
+body.detached.platform-mac-leopard #toolbar-dropdown,
+body.detached.platform-mac-snowleopard #toolbar-dropdown {
+ background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(191, 191, 191)), to(rgb(151, 151, 151)));
+}
+
+#toolbar-dropdown .scrollable-content {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: start;
+}
+
+#toolbar-dropdown .toolbar-item {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ margin: 0px 2px;
+ padding: 4px;
+ width: 100%;
+ border: 1px solid rgba(0, 0, 0, 0);
+}
+
+#toolbar-dropdown .toolbar-item.toggleable.toggled-on {
+ border: 1px solid rgba(100, 100, 120, 0.4);
+ -webkit-border-image: none;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgba(128, 128, 128, 0.6)), to(rgba(128, 128, 128, 0.6)), color-stop(20%, rgba(158, 158, 158, 0.2)), color-stop(80%, rgba(158, 158, 158, 0.2)));
+}
+
+#toolbar-dropdown .toolbar-item:hover {
+ -webkit-border-image: none;
+ border: 1px solid rgba(100, 100, 120, 0.8);
+}
+
+#toolbar-dropdown .toolbar-item.toggleable.toggled-on:hover {
+ border: 1px solid rgba(100, 100, 120, 1);
+}
+
+#toolbar-dropdown .toolbar-icon {
+ margin-right: 0.5em;
+}
+
+#toolbar-dropdown .toolbar-item:active .toolbar-icon {
+ background-position: 0 24px;
+}
+
+.scrollable-content {
+ position: static;
+ height: 100%;
+ overflow-y: auto;
+ width: 100%;
+ margin-right: 12px;
+ padding-right: 3px;
+}
+
+.scrollable-content::-webkit-scrollbar {
+ width: 11px;
+}
+
+.scrollable-content::-webkit-scrollbar-corner,
+.scrollable-content::-webkit-resizer {
+ display: none;
+}
+
+.scrollable-content::-webkit-scrollbar-thumb:vertical {
+ background: -webkit-gradient(linear, left top, right top, from(rgb(192, 192, 192)), to(rgb(192, 192, 192)), color-stop(40%, rgb(214, 214, 214)));
+ border-radius: 5px;
+ min-height: 20px;
+}
+
+.scrollable-content::-webkit-scrollbar-thumb:vertical:hover,
+.scrollable-content::-webkit-scrollbar-thumb:vertical:active {
+ background: -webkit-gradient(linear, left top, right top, from(rgb(230, 230, 230)), to(rgb(230, 230, 230)), color-stop(40%, rgb(252, 252, 252)));
+}
+
+.scrollable-content::-webkit-scrollbar-track:vertical {
+ background: -webkit-gradient(linear, left top, right top, from(rgb(128, 128, 128)), to(rgb(164, 164, 164)), color-stop(25%, rgb(164, 164, 164)));
+ border-radius: 5px;
+}
+
+.toolbar-search-item {
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-align: center;
+ -webkit-box-pack: end;
+}
+
#search {
width: 205px;
font-size: 16px;
- margin-bottom: 5px;
}
body.attached #search {
font-size: 11px;
- margin-bottom: 8px;
}
#search-results-matches {
font-size: 11px;
text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
- margin-bottom: 22px;
-}
-
-body.attached #search-results-matches {
- margin-bottom: 6px;
}
.toolbar-item.elements .toolbar-icon {
@@ -238,7 +349,7 @@ body.attached #search-results-matches {
background-position: 0 0;
background-color: transparent;
border: 0 none transparent;
- margin: 5px 0;
+ margin-top: 9px;
}
#close-button-left:hover, #close-button-right:hover {
@@ -249,6 +360,10 @@ body.attached #search-results-matches {
background-position: 28px 0;
}
+.close-left {
+ float: left;
+}
+
body.detached .toolbar-item.close-left, body.detached .toolbar-item.close-right {
display: none;
}
diff --git a/Source/WebCore/inspector/front-end/inspector.html b/Source/WebCore/inspector/front-end/inspector.html
index 0435dc3..d6c810e 100644
--- a/Source/WebCore/inspector/front-end/inspector.html
+++ b/Source/WebCore/inspector/front-end/inspector.html
@@ -142,8 +142,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ProfileView.js"></script>
<script type="text/javascript" src="HeapSnapshot.js"></script>
<script type="text/javascript" src="HeapSnapshotView.js"></script>
+ <script type="text/javascript" src="DetailedHeapshotGridNodes.js"></script>
<script type="text/javascript" src="DetailedHeapshotView.js"></script>
<script type="text/javascript" src="DebuggerModel.js"></script>
+ <script type="text/javascript" src="DebuggerPresentationModel.js"></script>
<script type="text/javascript" src="DOMAgent.js"></script>
<script type="text/javascript" src="TimelineAgent.js"></script>
<script type="text/javascript" src="TimelinePanel.js"></script>
@@ -154,14 +156,18 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<script type="text/javascript" src="ShortcutsHelp.js"></script>
<script type="text/javascript" src="HAREntry.js"></script>
<script type="text/javascript" src="CookieParser.js"></script>
+ <script type="text/javascript" src="Toolbar.js"></script>
+ <script type="text/javascript" src="SearchController.js"></script>
</head>
<body class="detached">
<div id="toolbar">
<div class="toolbar-item close-left"><button id="close-button-left"></button></div>
- <div class="toolbar-item flexable-space"></div>
- <div class="toolbar-item hidden" id="search-results-matches"></div>
- <div class="toolbar-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
- <div class="toolbar-item close-right"><button id="close-button-right"></button></div>
+ <div id="toolbar-controls">
+ <div class="toolbar-item"><button id="toolbar-dropdown-arrow" class="toolbar-label">&raquo;</button></div>
+ <div class="toolbar-item hidden" id="search-results-matches"></div>
+ <div class="toolbar-item toolbar-search-item"><input id="search" type="search" incremental results="0"><div id="search-toolbar-label" class="toolbar-label"></div></div>
+ <div class="toolbar-item close-right"><button id="close-button-right"></button></div>
+ </div>
</div>
<div id="main">
<div id="main-panels" spellcheck="false"></div>
diff --git a/Source/WebCore/inspector/front-end/inspector.js b/Source/WebCore/inspector/front-end/inspector.js
index 0959289..b4c3fda 100644
--- a/Source/WebCore/inspector/front-end/inspector.js
+++ b/Source/WebCore/inspector/front-end/inspector.js
@@ -138,6 +138,12 @@ var WebInspector = {
this._previousFocusElement.blur();
},
+ resetFocusElement: function()
+ {
+ this.currentFocusElement = null;
+ this._previousFocusElement = null;
+ },
+
get currentPanel()
{
return this._currentPanel;
@@ -153,30 +159,10 @@ var WebInspector = {
this._currentPanel = x;
- this.updateSearchLabel();
-
if (x) {
x.show();
-
- if (this.currentQuery) {
- if (x.performSearch) {
- function performPanelSearch()
- {
- this.updateSearchMatchesCount();
-
- x.currentQuery = this.currentQuery;
- x.performSearch(this.currentQuery);
- }
-
- // Perform the search on a timeout so the panel switches fast.
- setTimeout(performPanelSearch.bind(this), 0);
- } else {
- // Update to show Not found for panels that can't be searched.
- this.updateSearchMatchesCount();
- }
- }
+ WebInspector.searchController.activePanelChanged();
}
-
for (var panelName in WebInspector.panels) {
if (WebInspector.panels[panelName] === x) {
WebInspector.settings.lastActivePanel = panelName;
@@ -248,8 +234,6 @@ var WebInspector = {
this._attached = x;
- this.updateSearchLabel();
-
var dockToggleButton = document.getElementById("dock-status-bar-item");
var body = document.body;
@@ -262,8 +246,11 @@ var WebInspector = {
body.addStyleClass("detached");
dockToggleButton.title = WebInspector.UIString("Dock to main window.");
}
- if (this.drawer)
- this.drawer.resize();
+
+ // This may be called before onLoadedDone, hence the bulk of inspector objects may
+ // not be created yet.
+ if (WebInspector.searchController)
+ WebInspector.searchController.updateSearchLabel();
},
get errors()
@@ -360,9 +347,9 @@ var WebInspector = {
this._highlightedDOMNodeId = nodeId;
if (nodeId)
- InspectorBackend.highlightDOMNode(nodeId);
+ InspectorAgent.highlightDOMNode(nodeId);
else
- InspectorBackend.hideDOMNodeHighlight();
+ InspectorAgent.hideDOMNodeHighlight();
},
highlightDOMNodeForTwoSeconds: function(nodeId)
@@ -492,17 +479,16 @@ WebInspector.doLoadedDone = function()
this.debuggerModel = new WebInspector.DebuggerModel();
this.breakpointManager = new WebInspector.BreakpointManager();
+ this.searchController = new WebInspector.SearchController();
this.panels = {};
this._createPanels();
this._panelHistory = new WebInspector.PanelHistory();
-
- var toolbarElement = document.getElementById("toolbar");
- var previousToolbarItem = toolbarElement.children[0];
+ this.toolbar = new WebInspector.Toolbar();
this.panelOrder = [];
for (var panelName in this.panels)
- previousToolbarItem = WebInspector.addPanelToolbarIcon(toolbarElement, this.panels[panelName], previousToolbarItem);
+ this.addPanel(this.panels[panelName]);
this.Tips = {
ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
@@ -534,15 +520,6 @@ WebInspector.doLoadedDone = function()
errorWarningCount.addEventListener("click", this.showConsole.bind(this), false);
this._updateErrorAndWarningCounts();
- var searchField = document.getElementById("search");
- searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied
- searchField.addEventListener("mousedown", this._searchFieldManualFocus.bind(this), false); // when the search field is manually selected
- searchField.addEventListener("keydown", this._searchKeyDown.bind(this), true);
-
- toolbarElement.addEventListener("mousedown", this.toolbarDragStart, true);
- document.getElementById("close-button-left").addEventListener("click", this.close, true);
- document.getElementById("close-button-right").addEventListener("click", this.close, true);
-
this.extensionServer.initExtensions();
function onPopulateScriptObjects()
@@ -550,35 +527,29 @@ WebInspector.doLoadedDone = function()
if (!WebInspector.currentPanel)
WebInspector.showPanel(WebInspector.settings.lastActivePanel);
}
- InspectorBackend.populateScriptObjects(onPopulateScriptObjects);
+ InspectorAgent.populateScriptObjects(onPopulateScriptObjects);
if (Preferences.debuggerAlwaysEnabled || WebInspector.settings.debuggerEnabled)
this.debuggerModel.enableDebugger();
if (Preferences.profilerAlwaysEnabled || WebInspector.settings.profilerEnabled)
- InspectorBackend.enableProfiler();
+ InspectorAgent.enableProfiler();
if (WebInspector.settings.monitoringXHREnabled)
- InspectorBackend.setMonitoringXHREnabled(true);
+ ConsoleAgent.setMonitoringXHREnabled(true);
- InspectorBackend.setConsoleMessagesEnabled(true);
+ ConsoleAgent.setConsoleMessagesEnabled(true);
function propertyNamesCallback(names)
{
WebInspector.cssNameCompletions = new WebInspector.CSSCompletions(names);
}
// As a DOMAgent method, this needs to happen after the frontend has loaded and the agent is available.
- InspectorBackend.getSupportedCSSProperties(propertyNamesCallback);
+ CSSAgent.getSupportedCSSProperties(propertyNamesCallback);
}
-WebInspector.addPanelToolbarIcon = function(toolbarElement, panel, previousToolbarItem)
+WebInspector.addPanel = function(panel)
{
- var panelToolbarItem = panel.toolbarItem;
this.panelOrder.push(panel);
- panelToolbarItem.addEventListener("click", this._toolbarItemClicked.bind(this));
- if (previousToolbarItem)
- toolbarElement.insertBefore(panelToolbarItem, previousToolbarItem.nextSibling);
- else
- toolbarElement.insertBefore(panelToolbarItem, toolbarElement.firstChild);
- return panelToolbarItem;
+ this.toolbar.addPanel(panel);
}
var windowLoaded = function()
@@ -599,16 +570,19 @@ var windowLoaded = function()
window.addEventListener("DOMContentLoaded", windowLoaded, false);
+// We'd like to enforce asynchronous interaction between the inspector controller and the frontend.
+// It is needed to prevent re-entering the backend code.
+// Also, native dispatches do not guarantee setTimeouts to be serialized, so we
+// enforce serialization using 'messagesToDispatch' queue. It is also important that JSC debugger
+// tests require that each command was dispatch within individual timeout callback, so we don't batch them.
+
+var messagesToDispatch = [];
+
WebInspector.dispatch = function(message) {
- // We'd like to enforce asynchronous interaction between the inspector controller and the frontend.
- // This is important to LayoutTests.
- function delayDispatch()
- {
- InspectorBackend.dispatch(message);
- WebInspector.pendingDispatches--;
- }
- WebInspector.pendingDispatches++;
- setTimeout(delayDispatch, 0);
+ messagesToDispatch.push(message);
+ setTimeout(function() {
+ InspectorBackend.dispatch(messagesToDispatch.shift());
+ }, 0);
}
WebInspector.dispatchMessageFromBackend = function(messageObject)
@@ -621,6 +595,7 @@ WebInspector.windowResize = function(event)
if (this.currentPanel)
this.currentPanel.resize();
this.drawer.resize();
+ this.toolbar.resize();
}
WebInspector.windowFocused = function(event)
@@ -727,7 +702,7 @@ WebInspector.openResource = function(resourceURL, inResourcesPanel)
WebInspector.panels.resources.showResource(resource);
WebInspector.showPanel("resources");
} else
- InspectorBackend.openInInspectedWindow(resource ? resource.url : resourceURL);
+ InspectorAgent.openInInspectedWindow(resource ? resource.url : resourceURL);
}
WebInspector._registerShortcuts = function()
@@ -783,6 +758,12 @@ WebInspector.documentKeyDown = function(event)
}
}
+ WebInspector.searchController.handleShortcut(event);
+ if (event.handled) {
+ event.preventDefault();
+ return;
+ }
+
var isMac = WebInspector.isMac();
switch (event.keyIdentifier) {
case "Left":
@@ -809,36 +790,6 @@ WebInspector.documentKeyDown = function(event)
this.drawer.visible = !this.drawer.visible;
break;
- case "U+0046": // F key
- if (isMac)
- var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
- else
- var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;
-
- if (isFindKey) {
- WebInspector.focusSearchField();
- event.preventDefault();
- }
- break;
-
- case "F3":
- if (!isMac) {
- WebInspector.focusSearchField();
- event.preventDefault();
- }
- break;
-
- case "U+0047": // G key
- if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) {
- if (event.shiftKey) {
- if (this.currentPanel.jumpToPreviousSearchResult)
- this.currentPanel.jumpToPreviousSearchResult();
- } else if (this.currentPanel.jumpToNextSearchResult)
- this.currentPanel.jumpToNextSearchResult();
- event.preventDefault();
- }
- break;
-
// Windows and Mac have two different definitions of [, so accept both.
case "U+005B":
case "U+00DB": // [ key
@@ -875,13 +826,13 @@ WebInspector.documentKeyDown = function(event)
case "U+0052": // R key
if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) {
- InspectorBackend.reloadPage(event.shiftKey);
+ InspectorAgent.reloadPage(event.shiftKey);
event.preventDefault();
}
break;
case "F5":
if (!isMac)
- InspectorBackend.reloadPage(event.ctrlKey || event.shiftKey);
+ InspectorAgent.reloadPage(event.ctrlKey || event.shiftKey);
break;
}
}
@@ -1005,27 +956,6 @@ WebInspector.animateStyle = function(animations, duration, callback)
};
}
-WebInspector.updateSearchLabel = function()
-{
- if (!this.currentPanel)
- return;
-
- var newLabel = WebInspector.UIString("Search %s", this.currentPanel.toolbarItemLabel);
- if (this.attached)
- document.getElementById("search").setAttribute("placeholder", newLabel);
- else {
- document.getElementById("search").removeAttribute("placeholder");
- document.getElementById("search-toolbar-label").textContent = newLabel;
- }
-}
-
-WebInspector.focusSearchField = function()
-{
- var searchField = document.getElementById("search");
- searchField.focus();
- searchField.select();
-}
-
WebInspector.toggleAttach = function()
{
if (!this.attached)
@@ -1034,58 +964,6 @@ WebInspector.toggleAttach = function()
InspectorFrontendHost.requestDetachWindow();
}
-WebInspector.toolbarDragStart = function(event)
-{
- if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
- return;
-
- var target = event.target;
- if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
- return;
-
- var toolbar = document.getElementById("toolbar");
- if (target !== toolbar && !target.hasStyleClass("toolbar-item"))
- return;
-
- toolbar.lastScreenX = event.screenX;
- toolbar.lastScreenY = event.screenY;
-
- WebInspector.elementDragStart(toolbar, WebInspector.toolbarDrag, WebInspector.toolbarDragEnd, event, (WebInspector.attached ? "row-resize" : "default"));
-}
-
-WebInspector.toolbarDragEnd = function(event)
-{
- var toolbar = document.getElementById("toolbar");
-
- WebInspector.elementDragEnd(event);
-
- delete toolbar.lastScreenX;
- delete toolbar.lastScreenY;
-}
-
-WebInspector.toolbarDrag = function(event)
-{
- var toolbar = document.getElementById("toolbar");
-
- if (WebInspector.attached) {
- var height = window.innerHeight - (event.screenY - toolbar.lastScreenY);
-
- InspectorFrontendHost.setAttachedWindowHeight(height);
- } else {
- var x = event.screenX - toolbar.lastScreenX;
- var y = event.screenY - toolbar.lastScreenY;
-
- // We cannot call window.moveBy here because it restricts the movement
- // of the window at the edges.
- InspectorFrontendHost.moveWindowBy(x, y);
- }
-
- toolbar.lastScreenX = event.screenX;
- toolbar.lastScreenY = event.screenY;
-
- event.preventDefault();
-}
-
WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
{
if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
@@ -1307,6 +1185,23 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) {
g.fill();
}
+WebInspector.inspect = function(objectId, hints)
+{
+ var object = WebInspector.RemoteObject.fromPayload(objectId);
+ if (object.type === "node") {
+ // Request node from backend and focus it.
+ object.pushNodeToFrontend(WebInspector.updateFocusedNode.bind(WebInspector));
+ } else if (hints.databaseId) {
+ WebInspector.currentPanel = WebInspector.panels.resources;
+ WebInspector.panels.resources.selectDatabase(hints.databaseId);
+ } else if (hints.domStorageId) {
+ WebInspector.currentPanel = WebInspector.panels.resources;
+ WebInspector.panels.resources.selectDOMStorage(hints.domStorageId);
+ }
+
+ RuntimeAgent.releaseObject(objectId);
+}
+
WebInspector.updateFocusedNode = function(nodeId)
{
this._updateFocusedNode(nodeId);
@@ -1518,156 +1413,12 @@ WebInspector.addMainEventListeners = function(doc)
doc.addEventListener("click", this.documentClick.bind(this), true);
}
-WebInspector._searchFieldManualFocus = function(event)
-{
- this.currentFocusElement = event.target;
- this._previousFocusElement = event.target;
-}
-
-WebInspector._searchKeyDown = function(event)
-{
- // Escape Key will clear the field and clear the search results
- if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
- // If focus belongs here and text is empty - nothing to do, return unhandled.
- if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
- return;
- event.preventDefault();
- event.stopPropagation();
- // When search was selected manually and is currently blank, we'd like Esc stay unhandled
- // and hit console drawer handler.
- event.target.value = "";
-
- this.performSearch(event);
- this.currentFocusElement = this.previousFocusElement;
- if (this.currentFocusElement === event.target)
- this.currentFocusElement.select();
- return false;
- }
-
- if (!isEnterKey(event))
- return false;
-
- // Select all of the text so the user can easily type an entirely new query.
- event.target.select();
-
- // Only call performSearch if the Enter key was pressed. Otherwise the search
- // performance is poor because of searching on every key. The search field has
- // the incremental attribute set, so we still get incremental searches.
- this.performSearch(event);
-
- // Call preventDefault since this was the Enter key. This prevents a "search" event
- // from firing for key down. This stops performSearch from being called twice in a row.
- event.preventDefault();
-}
-
-WebInspector.performSearch = function(event)
-{
- var forceSearch = event.keyIdentifier === "Enter";
- this.doPerformSearch(event.target.value, forceSearch, event.shiftKey, false);
-}
-
-WebInspector.cancelSearch = function()
-{
- document.getElementById("search").value = "";
- this.doPerformSearch("");
-}
-
-WebInspector.doPerformSearch = function(query, forceSearch, isBackwardSearch, repeatSearch)
-{
- var isShortSearch = (query.length < 3);
-
- // Clear a leftover short search flag due to a non-conflicting forced search.
- if (isShortSearch && this.shortSearchWasForcedByKeyEvent && this.currentQuery !== query)
- delete this.shortSearchWasForcedByKeyEvent;
-
- // Indicate this was a forced search on a short query.
- if (isShortSearch && forceSearch)
- this.shortSearchWasForcedByKeyEvent = true;
-
- if (!query || !query.length || (!forceSearch && isShortSearch)) {
- // Prevent clobbering a short search forced by the user.
- if (this.shortSearchWasForcedByKeyEvent) {
- delete this.shortSearchWasForcedByKeyEvent;
- return;
- }
-
- delete this.currentQuery;
-
- for (var panelName in this.panels) {
- var panel = this.panels[panelName];
- var hadCurrentQuery = !!panel.currentQuery;
- delete panel.currentQuery;
- if (hadCurrentQuery && panel.searchCanceled)
- panel.searchCanceled();
- }
-
- this.updateSearchMatchesCount();
-
- return;
- }
-
- if (!repeatSearch && query === this.currentPanel.currentQuery && this.currentPanel.currentQuery === this.currentQuery) {
- // When this is the same query and a forced search, jump to the next
- // search result for a good user experience.
- if (forceSearch) {
- if (!isBackwardSearch && this.currentPanel.jumpToNextSearchResult)
- this.currentPanel.jumpToNextSearchResult();
- else if (isBackwardSearch && this.currentPanel.jumpToPreviousSearchResult)
- this.currentPanel.jumpToPreviousSearchResult();
- }
- return;
- }
-
- this.currentQuery = query;
-
- this.updateSearchMatchesCount();
-
- if (!this.currentPanel.performSearch)
- return;
-
- this.currentPanel.currentQuery = query;
- this.currentPanel.performSearch(query);
-}
-
WebInspector.frontendReused = function()
{
- this.networkManager.reset();
+ this.networkManager.frontendReused();
this.reset();
}
-WebInspector.addNodesToSearchResult = function(nodeIds)
-{
- WebInspector.panels.elements.addNodesToSearchResult(nodeIds);
-}
-
-WebInspector.updateSearchMatchesCount = function(matches, panel)
-{
- if (!panel)
- panel = this.currentPanel;
-
- panel.currentSearchMatches = matches;
-
- if (panel !== this.currentPanel)
- return;
-
- if (!this.currentPanel.currentQuery) {
- document.getElementById("search-results-matches").addStyleClass("hidden");
- return;
- }
-
- if (matches) {
- if (matches === 1)
- var matchesString = WebInspector.UIString("1 match");
- else
- var matchesString = WebInspector.UIString("%d matches", matches);
- } else
- var matchesString = WebInspector.UIString("Not Found");
-
- var matchesToolbarElement = document.getElementById("search-results-matches");
- matchesToolbarElement.removeStyleClass("hidden");
- matchesToolbarElement.textContent = matchesString;
-}
-
WebInspector.UIString = function(string)
{
if (window.localizedStrings && string in window.localizedStrings)
@@ -1675,7 +1426,7 @@ WebInspector.UIString = function(string)
else {
if (!(string in WebInspector.missingLocalizedStrings)) {
if (!WebInspector.InspectorBackendStub)
- console.error("Localized string \"" + string + "\" not found.");
+ console.warn("Localized string \"" + string + "\" not found.");
WebInspector.missingLocalizedStrings[string] = true;
}
diff --git a/Source/WebCore/inspector/front-end/networkPanel.css b/Source/WebCore/inspector/front-end/networkPanel.css
index c750323..2711347 100644
--- a/Source/WebCore/inspector/front-end/networkPanel.css
+++ b/Source/WebCore/inspector/front-end/networkPanel.css
@@ -22,7 +22,7 @@
-webkit-background-size: 1px 42px;
}
-.network-sidebar .data-grid td:not(.network-summary) {
+.network-sidebar .data-grid td {
line-height: 17px;
height: 37px;
border-right: 1px solid rgb(210, 210, 210);
@@ -496,34 +496,34 @@
/* Summary */
+.network-sidebar tr.filler td {
+ padding-bottom: 20px !important;
+}
+
.network-summary-bar {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin-right: -14px;
background-color: rgb(101, 111, 130);
+}
+
+.network-sidebar .data-grid .network-summary-bar td {
color: white;
height: 20px;
+ border: none;
font-size: 11px;
font-weight: bold;
- padding-top: 3px;
- padding-left: 10px;
- z-index: 2000;
+ padding: 0 0 0 8px;
white-space: pre;
overflow : hidden;
text-overflow : ellipsis;
}
-.network-summary-bar-bottom {
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- padding-top: 3px;
-}
-
-.data-grid td .network-summary-bar {
- white-space: pre;
-}
-
-.network-sidebar .data-grid td.network-summary {
- padding: 0;
+.network-summary-bar img {
+ vertical-align: middle;
+ padding-right: 8px;
}
/* Viewer */
diff --git a/Source/WebCore/inspector/front-end/textViewer.css b/Source/WebCore/inspector/front-end/textViewer.css
index f6aa65e..59f2a43 100644
--- a/Source/WebCore/inspector/front-end/textViewer.css
+++ b/Source/WebCore/inspector/front-end/textViewer.css
@@ -15,6 +15,9 @@
bottom: 0;
overflow: hidden;
-webkit-user-select: none;
+ background-color: rgb(240, 240, 240);
+ border-right: 1px solid rgb(187, 187, 187);
+ min-width: 19px;
}
.text-editor-contents {
@@ -27,6 +30,15 @@
-webkit-user-select: text;
}
+.text-editor-contents .inner-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: auto;
+ bottom: auto;
+ min-width: 100%;
+}
+
.text-editor-editable {
-webkit-user-modify: read-write-plaintext-only;
}
@@ -80,8 +92,6 @@
.webkit-line-number {
color: rgb(128, 128, 128);
- background-color: rgb(240, 240, 240);
- border-right: 1px solid rgb(187, 187, 187);
text-align: right;
vertical-align: top;
word-break: normal;
diff --git a/Source/WebCore/inspector/front-end/utilities.js b/Source/WebCore/inspector/front-end/utilities.js
index 5ed9a8c..31a5f0c 100644
--- a/Source/WebCore/inspector/front-end/utilities.js
+++ b/Source/WebCore/inspector/front-end/utilities.js
@@ -218,7 +218,8 @@ Element.prototype.pruneEmptyTextNodes = function()
Element.prototype.isScrolledToBottom = function()
{
- return this.scrollTop === this.scrollHeight - this.offsetHeight;
+ // This code works only for 0-width border
+ return this.scrollTop + this.clientHeight === this.scrollHeight;
}
Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
@@ -399,6 +400,15 @@ String.prototype.findAll = function(string)
return matches;
}
+String.prototype.lineEndings = function()
+{
+ if (!this._lineEndings) {
+ this._lineEndings = this.findAll("\n");
+ this._lineEndings.push(this.length);
+ }
+ return this._lineEndings;
+}
+
String.prototype.asParsedURL = function()
{
// RegExp groups:
@@ -1010,52 +1020,91 @@ function isEnterKey(event) {
return event.keyCode !== 229 && event.keyIdentifier === "Enter";
}
-
function highlightSearchResult(element, offset, length)
{
+ var result = highlightSearchResults(element, [{offset: offset, length: length }]);
+ return result.length ? result[0] : null;
+}
+
+function highlightSearchResults(element, resultRanges)
+{
+ var highlightNodes = [];
var lineText = element.textContent;
- var endOffset = offset + length;
- var highlightNode = document.createElement("span");
- highlightNode.className = "webkit-search-result";
- highlightNode.textContent = lineText.substring(offset, endOffset);
-
- var boundary = element.rangeBoundaryForOffset(offset);
- var textNode = boundary.container;
- var text = textNode.textContent;
-
- if (boundary.offset + length < text.length) {
- // Selection belong to a single split mode.
- textNode.textContent = text.substring(boundary.offset + length);
- textNode.parentElement.insertBefore(highlightNode, textNode);
- var prefixNode = document.createTextNode(text.substring(0, boundary.offset));
- textNode.parentElement.insertBefore(prefixNode, highlightNode);
- return highlightNode;
- }
+ var textNodeSnapshot = document.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+
+ var snapshotLength = textNodeSnapshot.snapshotLength;
+ var snapshotNodeOffset = 0;
+ var currentSnapshotItem = 0;
+
+ for (var i = 0; i < resultRanges.length; ++i) {
+ var resultLength = resultRanges[i].length;
+ var startOffset = resultRanges[i].offset;
+ var endOffset = startOffset + resultLength;
+ var length = resultLength;
+ var textNode;
+ var textNodeOffset;
+ var found;
+
+ while (currentSnapshotItem < snapshotLength) {
+ textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
+ var textNodeLength = textNode.nodeValue.length;
+ if (snapshotNodeOffset + textNodeLength >= startOffset) {
+ textNodeOffset = startOffset - snapshotNodeOffset;
+ snapshotNodeOffset += textNodeLength;
+ found = true;
+ break;
+ }
+ snapshotNodeOffset += textNodeLength;
+ }
- var parentElement = textNode.parentElement;
- var anchorElement = textNode.nextSibling;
+ if (!found) {
+ textNode = element;
+ textNodeOffset = 0;
+ }
- length -= text.length - boundary.offset;
- textNode.textContent = text.substring(0, boundary.offset);
- textNode = textNode.traverseNextTextNode(element);
+ var highlightNode = document.createElement("span");
+ highlightNode.className = "webkit-search-result";
+ highlightNode.textContent = lineText.substring(startOffset, endOffset);
- while (textNode) {
var text = textNode.textContent;
- if (length < text.length) {
- textNode.textContent = text.substring(length);
- break;
+ if (textNodeOffset + resultLength < text.length) {
+ // Selection belongs to a single split mode.
+ textNode.textContent = text.substring(textNodeOffset + resultLength);
+ textNode.parentElement.insertBefore(highlightNode, textNode);
+ var prefixNode = document.createTextNode(text.substring(0, textNodeOffset));
+ textNode.parentElement.insertBefore(prefixNode, highlightNode);
+
+ highlightNodes.push(highlightNode);
+ continue;
+ }
+
+ var parentElement = textNode.parentElement;
+ var anchorElement = textNode.nextSibling;
+
+ length -= text.length - textNodeOffset;
+ textNode.textContent = text.substring(0, textNodeOffset);
+
+ while (currentSnapshotItem < snapshotLength) {
+ textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
+ snapshotNodeOffset += textNode.nodeValue.length;
+ var text = textNode.textContent;
+ if (length < text.length) {
+ textNode.textContent = text.substring(length);
+ break;
+ }
+
+ length -= text.length;
+ textNode.textContent = "";
}
- length -= text.length;
- textNode.textContent = "";
- textNode = textNode.traverseNextTextNode(element);
+ parentElement.insertBefore(highlightNode, anchorElement);
+ highlightNodes.push(highlightNode);
}
- parentElement.insertBefore(highlightNode, anchorElement);
- return highlightNode;
+ return highlightNodes;
}
-function createSearchRegex(query)
+function createSearchRegex(query, extraFlags)
{
var regex = "";
for (var i = 0; i < query.length; ++i) {
@@ -1064,7 +1113,7 @@ function createSearchRegex(query)
char = "\\]";
regex += "[" + char + "]";
}
- return new RegExp(regex, "i");
+ return new RegExp(regex, "i" + (extraFlags || ""));
}
function offerFileForDownload(contents)