diff options
author | Ben Murdoch <benm@google.com> | 2011-06-02 12:07:03 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-06-10 10:47:21 +0100 |
commit | 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch) | |
tree | e4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebCore/inspector/front-end | |
parent | 87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff) | |
download | external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2 |
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebCore/inspector/front-end')
60 files changed, 3456 insertions, 2491 deletions
diff --git a/Source/WebCore/inspector/front-end/AuditRules.js b/Source/WebCore/inspector/front-end/AuditRules.js index ddab1df..19a2c24 100644 --- a/Source/WebCore/inspector/front-end/AuditRules.js +++ b/Source/WebCore/inspector/front-end/AuditRules.js @@ -63,18 +63,6 @@ WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, nee return domainToResourcesMap; } -WebInspector.AuditRules.evaluateInTargetWindow = function(func, args, callback) -{ - function mycallback(error, result) - { - if (!error && 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"); @@ -322,7 +310,7 @@ WebInspector.AuditRules.UnusedCssRule.prototype = { for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) { var rule = styleSheet.rules[curRule]; // Exact computation whenever source ranges are available. - var textLength = (rule.selectorRange && rule.style.properties.endOffset) ? rule.style.properties.endOffset - rule.selectorRange.start + 1 : 0; + var textLength = (rule.selectorRange && rule.style.range && rule.style.range.end) ? rule.style.range.end - rule.selectorRange.start + 1 : 0; if (!textLength && rule.style.cssText) textLength = rule.style.cssText.length + rule.selectorText.length; stylesheetSize += textLength; @@ -360,21 +348,21 @@ WebInspector.AuditRules.UnusedCssRule.prototype = { callback(result); } - function routine(selectorArray) + var foundSelectors = {}; + function queryCallback(boundSelectorsCallback, selector, styleSheets, testedSelectors, nodeId) { - var result = {}; - for (var i = 0; i < selectorArray.length; ++i) { - try { - if (document.querySelector(selectorArray[i])) - result[selectorArray[i]] = true; - } catch(e) { - // Ignore and mark as unused. - } - } - return result; + if (nodeId) + foundSelectors[selector] = true; + if (boundSelectorsCallback) + boundSelectorsCallback(foundSelectors); } - WebInspector.AuditRules.evaluateInTargetWindow(routine, [selectors], selectorsCallback.bind(null, callback, styleSheets, testedSelectors)); + function documentLoaded(selectors, document) { + for (var i = 0; i < selectors.length; ++i) + WebInspector.domAgent.querySelector(document.id, selectors[i], queryCallback.bind(null, i === selectors.length - 1 ? selectorsCallback.bind(null, callback, styleSheets, testedSelectors) : null, selectors[i], styleSheets, testedSelectors)); + } + + WebInspector.domAgent.requestDocument(documentLoaded.bind(null, selectors)); } function styleSheetCallback(styleSheets, sourceURL, continuation, styleSheet) @@ -721,20 +709,22 @@ WebInspector.AuditRules.ImageDimensionsRule.prototype = { doneCallback(); } - function getStyles(error, nodeIds) + function getStyles(nodeIds) { - if (error) + if (!nodeIds) { + console.error("Failed to get styles"); return; + } for (var i = 0; i < nodeIds.length; ++i) WebInspector.cssModel.getStylesAsync(nodeIds[i], imageStylesReady.bind(this, nodeIds[i], i === nodeIds.length - 1)); } - function getImages() + function onDocumentAvailable(root) { - DOMAgent.querySelectorAll(0, "img[src]", true, getStyles); + WebInspector.domAgent.querySelectorAll(root.id, "img[src]", getStyles); } - WebInspector.domAgent.requestDocument(getImages); + WebInspector.domAgent.requestDocument(onDocumentAvailable); } } @@ -771,46 +761,35 @@ WebInspector.AuditRules.CssInHeadRule.prototype = { callback(result); } - function routine() + function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds) { - function allViews() { - var views = [document.defaultView]; - var curView = 0; - while (curView < views.length) { - var view = views[curView]; - var frames = view.frames; - for (var i = 0; i < frames.length; ++i) { - if (frames[i] !== view) - views.push(frames[i]); - } - ++curView; + var externalStylesheetNodeIds = nodeIds; + var result = null; + if (inlineStyleNodeIds.length || externalStylesheetNodeIds.length) { + var urlToViolationsArray = {}; + var externalStylesheetHrefs = []; + for (var j = 0; j < externalStylesheetNodeIds.length; ++j) { + var linkNode = WebInspector.domAgent.nodeForId(externalStylesheetNodeIds[j]); + var completeHref = WebInspector.completeURL(linkNode.ownerDocument.documentURL, linkNode.getAttribute("href")); + externalStylesheetHrefs.push(completeHref || "<empty>"); } - return views; + urlToViolationsArray[root.documentURL] = [inlineStyleNodeIds.length, externalStylesheetHrefs]; + result = urlToViolationsArray; } + evalCallback(result); + } - var views = allViews(); - var urlToViolationsArray = {}; - var found = false; - for (var i = 0; i < views.length; ++i) { - var view = views[i]; - if (!view.document) - continue; - - var inlineStyles = view.document.querySelectorAll("body style"); - var inlineStylesheets = view.document.querySelectorAll("body link[rel~='stylesheet'][href]"); - if (!inlineStyles.length && !inlineStylesheets.length) - continue; + function inlineStylesReceived(root, nodeIds) + { + WebInspector.domAgent.querySelectorAll(root.id, "body link[rel~='stylesheet'][href]", externalStylesheetsReceived.bind(null, root, nodeIds)); + } - found = true; - var inlineStylesheetHrefs = []; - for (var j = 0; j < inlineStylesheets.length; ++j) - inlineStylesheetHrefs.push(inlineStylesheets[j].href); - urlToViolationsArray[view.location.href] = [inlineStyles.length, inlineStylesheetHrefs]; - } - return found ? urlToViolationsArray : null; + function onDocumentAvailable(root) + { + WebInspector.domAgent.querySelectorAll(root.id, "body style", inlineStylesReceived.bind(null, root)); } - WebInspector.AuditRules.evaluateInTargetWindow(routine, [], evalCallback); + WebInspector.domAgent.requestDocument(onDocumentAvailable); } } @@ -844,20 +823,34 @@ WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { callback(result); } - function routine() + function cssBeforeInlineReceived(lateStyleIds, nodeIds) + { + var cssBeforeInlineCount = nodeIds.length; + var result = null; + if (lateStyleIds.length || cssBeforeInlineCount) { + var lateStyleUrls = []; + for (var i = 0; i < lateStyleIds.length; ++i) { + var lateStyleNode = WebInspector.domAgent.nodeForId(lateStyleIds[i]); + var completeHref = WebInspector.completeURL(lateStyleNode.ownerDocument.documentURL, lateStyleNode.getAttribute("href")); + lateStyleUrls.push(completeHref || "<empty>"); + } + result = [ lateStyleUrls, cssBeforeInlineCount ]; + } + + evalCallback(result); + } + + function lateStylesReceived(root, nodeIds) + { + WebInspector.domAgent.querySelectorAll(root.id, "head link[rel~='stylesheet'][href] ~ script:not([src])", cssBeforeInlineReceived.bind(null, nodeIds)); + } + + function onDocumentAvailable(root) { - var lateStyles = document.querySelectorAll("head script[src] ~ link[rel~='stylesheet'][href]"); - var cssBeforeInlineCount = document.querySelectorAll("head link[rel~='stylesheet'][href] ~ script:not([src])").length; - if (!lateStyles.length && !cssBeforeInlineCount) - return null; - - var lateStyleUrls = []; - for (var i = 0; i < lateStyles.length; ++i) - lateStyleUrls.push(lateStyles[i].href); - return [ lateStyleUrls, cssBeforeInlineCount ]; + WebInspector.domAgent.querySelectorAll(root.id, "head script[src] ~ link[rel~='stylesheet'][href]", lateStylesReceived.bind(null, root)); } - WebInspector.AuditRules.evaluateInTargetWindow(routine, [], evalCallback.bind(this)); + WebInspector.domAgent.requestDocument(onDocumentAvailable); } } diff --git a/Source/WebCore/inspector/front-end/Breakpoint.js b/Source/WebCore/inspector/front-end/Breakpoint.js deleted file mode 100644 index ebc6029..0000000 --- a/Source/WebCore/inspector/front-end/Breakpoint.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * Copyright (C) 2010 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.Breakpoint = function(id, url, sourceID, lineNumber, columnNumber, condition, enabled) -{ - this.id = id; - this.url = url; - this.sourceID = sourceID; - this.lineNumber = lineNumber; - this.columnNumber = columnNumber; - this.condition = condition; - this.enabled = enabled; - this.locations = []; -} - -WebInspector.Breakpoint.prototype = { - addLocation: function(sourceID, lineNumber, columnNumber) - { - this.locations.push({ sourceID: sourceID, lineNumber: lineNumber, columnNumber: columnNumber }); - } -} diff --git a/Source/WebCore/inspector/front-end/BreakpointManager.js b/Source/WebCore/inspector/front-end/BreakpointManager.js deleted file mode 100644 index 76348ff..0000000 --- a/Source/WebCore/inspector/front-end/BreakpointManager.js +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (C) 2010 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.BreakpointManager = function() -{ - this._stickyBreakpoints = {}; - var breakpoints = WebInspector.settings.findSettingForAllProjects("nativeBreakpoints"); - for (var projectId in breakpoints) - this._stickyBreakpoints[projectId] = this._validateBreakpoints(breakpoints[projectId]); - - this._breakpoints = {}; - this._domBreakpointsRestored = false; - - WebInspector.settings.addEventListener(WebInspector.Settings.Events.ProjectChanged, this._projectChanged, this); - WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); - WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this); -} - -WebInspector.BreakpointManager.BreakpointTypes = { - DOM: "DOM", - EventListener: "EventListener", - XHR: "XHR" -} - -WebInspector.BreakpointManager.Events = { - DOMBreakpointAdded: "dom-breakpoint-added", - ProjectChanged: "project-changed" -} - -WebInspector.BreakpointManager.prototype = { - createDOMBreakpoint: function(nodeId, type) - { - this._createDOMBreakpoint(nodeId, type, true, false); - }, - - _createDOMBreakpoint: function(nodeId, type, enabled, restored) - { - var node = WebInspector.domAgent.nodeForId(nodeId); - if (!node) - return; - - var breakpointId = this._createDOMBreakpointId(nodeId, type); - if (breakpointId in this._breakpoints) - return; - - var breakpoint = new WebInspector.DOMBreakpoint(node, type); - this._setBreakpoint(breakpointId, breakpoint, enabled, restored); - if (enabled && restored) - breakpoint._enable(); - - breakpoint.view = new WebInspector.DOMBreakpointView(this, breakpointId, enabled, node, type); - this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.DOMBreakpointAdded, breakpoint.view); - }, - - _setBreakpoint: function(breakpointId, breakpoint, enabled, restored) - { - this._breakpoints[breakpointId] = breakpoint; - breakpoint.enabled = enabled; - if (restored) - return; - if (enabled) - breakpoint._enable(); - this._saveBreakpoints(); - }, - - _setBreakpointEnabled: function(breakpointId, enabled) - { - var breakpoint = this._breakpoints[breakpointId]; - if (breakpoint.enabled === enabled) - return; - if (enabled) - breakpoint._enable(); - else - breakpoint._disable(); - breakpoint.enabled = enabled; - this._saveBreakpoints(); - }, - - _removeBreakpoint: function(breakpointId) - { - var breakpoint = this._breakpoints[breakpointId]; - if (breakpoint.enabled) - breakpoint._disable(); - delete this._breakpoints[breakpointId]; - this._saveBreakpoints(); - }, - - breakpointViewForEventData: function(eventData) - { - var breakpointId; - if (eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.DOM) - breakpointId = this._createDOMBreakpointId(eventData.nodeId, eventData.type); - else - return; - - var breakpoint = this._breakpoints[breakpointId]; - if (breakpoint) - return breakpoint.view; - }, - - _debuggerPaused: function(event) - { - var eventType = event.data.eventType; - var eventData = event.data.eventData; - - if (eventType !== WebInspector.DebuggerEventTypes.NativeBreakpoint) - return; - - var breakpointView = this.breakpointViewForEventData(eventData); - if (!breakpointView) - return; - - breakpointView.hit = true; - this._lastHitBreakpointView = breakpointView; - }, - - _debuggerResumed: function(event) - { - if (!this._lastHitBreakpointView) - return; - this._lastHitBreakpointView.hit = false; - delete this._lastHitBreakpointView; - }, - - _projectChanged: function(event) - { - this._breakpoints = {}; - this._domBreakpointsRestored = false; - this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.ProjectChanged); - }, - - restoreDOMBreakpoints: function() - { - function didPushNodeByPathToFrontend(path, nodeId) - { - if (!nodeId) - return; - - pathToNodeId[path] = nodeId; - pendingCalls -= 1; - if (pendingCalls) - return; - for (var i = 0; i < breakpoints.length; ++i) { - var breakpoint = breakpoints[i]; - if (breakpoint.type !== WebInspector.BreakpointManager.BreakpointTypes.DOM) - continue; - var nodeId = pathToNodeId[breakpoint.condition.path]; - if (nodeId) - this._createDOMBreakpoint(nodeId, breakpoint.condition.type, breakpoint.enabled, true); - } - this._domBreakpointsRestored = true; - this._saveBreakpoints(); - } - - var breakpoints = this._stickyBreakpoints[WebInspector.settings.projectId] || []; - var pathToNodeId = {}; - var pendingCalls = 0; - for (var i = 0; i < breakpoints.length; ++i) { - if (breakpoints[i].type !== WebInspector.BreakpointManager.BreakpointTypes.DOM) - continue; - var path = breakpoints[i].condition.path; - if (path in pathToNodeId) - continue; - pathToNodeId[path] = 0; - pendingCalls += 1; - WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path)); - } - if (!pendingCalls) - this._domBreakpointsRestored = true; - }, - - _saveBreakpoints: function() - { - var breakpoints = []; - for (var breakpointId in this._breakpoints) { - var breakpoint = this._breakpoints[breakpointId]; - var persistentBreakpoint = breakpoint._serializeToJSON(); - persistentBreakpoint.enabled = breakpoint.enabled; - breakpoints.push(persistentBreakpoint); - } - if (!this._domBreakpointsRestored) { - var stickyBreakpoints = this._stickyBreakpoints[WebInspector.settings.projectId] || []; - for (var i = 0; i < stickyBreakpoints.length; ++i) { - if (stickyBreakpoints[i].type === WebInspector.BreakpointManager.BreakpointTypes.DOM) - breakpoints.push(stickyBreakpoints[i]); - } - } - WebInspector.settings.nativeBreakpoints = breakpoints; - - this._stickyBreakpoints[WebInspector.settings.projectId] = breakpoints; - }, - - _validateBreakpoints: function(persistentBreakpoints) - { - var breakpoints = []; - var breakpointsSet = {}; - for (var i = 0; i < persistentBreakpoints.length; ++i) { - var breakpoint = persistentBreakpoints[i]; - if (!("type" in breakpoint && "enabled" in breakpoint && "condition" in breakpoint)) - continue; - var id = breakpoint.type + ":"; - var condition = breakpoint.condition; - if (breakpoint.type === WebInspector.BreakpointManager.BreakpointTypes.DOM) { - if (typeof condition.path !== "string" || typeof condition.type !== "number") - continue; - id += condition.path + ":" + condition.type; - } else - continue; - - if (id in breakpointsSet) - continue; - breakpointsSet[id] = true; - breakpoints.push(breakpoint); - } - return breakpoints; - }, - - _createDOMBreakpointId: function(nodeId, type) - { - return "dom:" + nodeId + ":" + type; - } -} - -WebInspector.BreakpointManager.prototype.__proto__ = WebInspector.Object.prototype; - -WebInspector.DOMBreakpoint = function(node, type) -{ - this._nodeId = node.id; - this._path = node.path(); - this._type = type; -} - -WebInspector.DOMBreakpoint.prototype = { - _enable: function() - { - BrowserDebuggerAgent.setDOMBreakpoint(this._nodeId, this._type); - }, - - _disable: function() - { - BrowserDebuggerAgent.removeDOMBreakpoint(this._nodeId, this._type); - }, - - _serializeToJSON: function() - { - var type = WebInspector.BreakpointManager.BreakpointTypes.DOM; - return { type: type, condition: { path: this._path, type: this._type } }; - } -} - -WebInspector.NativeBreakpointView = function(manager, id, enabled) -{ - this._manager = manager; - this._id = id; - this._enabled = enabled; - this._hit = false; -} - -WebInspector.NativeBreakpointView.prototype = { - get enabled() - { - return this._enabled; - }, - - set enabled(enabled) - { - this._manager._setBreakpointEnabled(this._id, enabled); - this._enabled = enabled; - this.dispatchEventToListeners("enable-changed"); - }, - - get hit() - { - return this._hit; - }, - - set hit(hit) - { - this._hit = hit; - this.dispatchEventToListeners("hit-state-changed"); - }, - - remove: function() - { - this._manager._removeBreakpoint(this._id); - this._onRemove(); - this.dispatchEventToListeners("removed"); - }, - - _compare: function(x, y) - { - if (x !== y) - return x < y ? -1 : 1; - return 0; - }, - - _onRemove: function() - { - } -} - -WebInspector.NativeBreakpointView.prototype.__proto__ = WebInspector.Object.prototype; - -WebInspector.DOMBreakpointView = function(manager, id, enabled, node, type) -{ - WebInspector.NativeBreakpointView.call(this, manager, id, enabled); - this._node = node; - this._nodeId = node.id; - this._type = type; - node.breakpoints[this._type] = this; -} - -WebInspector.DOMBreakpointView.prototype = { - compareTo: function(other) - { - return this._compare(this._type, other._type); - }, - - populateLabelElement: function(element) - { - // FIXME: this should belong to the view, not the manager. - var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(this._nodeId); - linkifiedNode.addStyleClass("monospace"); - element.appendChild(linkifiedNode); - var description = document.createElement("div"); - description.className = "source-text"; - description.textContent = WebInspector.domBreakpointTypeLabel(this._type); - element.appendChild(description); - }, - - 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; - - targetNodeObject.release(); - 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) - { - return substitution; - } - }; - function append(a, b) - { - if (typeof b === "string") - b = document.createTextNode(b); - element.appendChild(b); - } - WebInspector.formatLocalized(message, substitutions, formatters, "", append); - }, - - _onRemove: function() - { - delete this._node.breakpoints[this._type]; - } -} - -WebInspector.DOMBreakpointView.prototype.__proto__ = WebInspector.NativeBreakpointView.prototype; - -WebInspector.DOMBreakpointTypes = { - SubtreeModified: 0, - AttributeModified: 1, - NodeRemoved: 2 -}; - -WebInspector.domBreakpointTypeLabel = function(type) -{ - if (!WebInspector._DOMBreakpointTypeLabels) { - WebInspector._DOMBreakpointTypeLabels = {}; - WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified"); - WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified"); - WebInspector._DOMBreakpointTypeLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed"); - } - return WebInspector._DOMBreakpointTypeLabels[type]; -} - -WebInspector.domBreakpointTypeContextMenuLabel = function(type) -{ - if (!WebInspector._DOMBreakpointTypeContextMenuLabels) { - WebInspector._DOMBreakpointTypeContextMenuLabels = {}; - WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.SubtreeModified] = WebInspector.UIString("Break on Subtree Modifications"); - WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.AttributeModified] = WebInspector.UIString("Break on Attributes Modifications"); - WebInspector._DOMBreakpointTypeContextMenuLabels[WebInspector.DOMBreakpointTypes.NodeRemoved] = WebInspector.UIString("Break on Node Removal"); - } - return WebInspector._DOMBreakpointTypeContextMenuLabels[type]; -} diff --git a/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js index 63a6e2a..d2d7257 100644 --- a/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js +++ b/Source/WebCore/inspector/front-end/BreakpointsSidebarPane.js @@ -23,11 +23,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.JavaScriptBreakpointsSidebarPane = function(model) +WebInspector.JavaScriptBreakpointsSidebarPane = function(model, showSourceLineDelegate) { WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints")); this._model = model; + this._showSourceLineDelegate = showSourceLineDelegate; this.listElement = document.createElement("ol"); this.listElement.className = "breakpoint-list"; @@ -123,7 +124,7 @@ WebInspector.JavaScriptBreakpointsSidebarPane.prototype = { _breakpointClicked: function(breakpoint, event) { - WebInspector.panels.scripts.showSourceLine(breakpoint.sourceFileId, breakpoint.lineNumber + 1); + this._showSourceLineDelegate(breakpoint.sourceFileId, breakpoint.lineNumber); }, _breakpointCheckboxClicked: function(breakpoint, event) @@ -203,41 +204,9 @@ WebInspector.NativeBreakpointsSidebarPane = function(title) this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); this.bodyElement.appendChild(this.emptyElement); - - WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this); } WebInspector.NativeBreakpointsSidebarPane.prototype = { - addBreakpointItem: function(breakpointItem) - { - var element = breakpointItem.element; - element._breakpointItem = breakpointItem; - - breakpointItem.addEventListener("breakpoint-hit", this.expand, this); - breakpointItem.addEventListener("removed", this._removeListElement.bind(this, element), this); - - var currentElement = this.listElement.firstChild; - while (currentElement) { - if (currentElement._breakpointItem && currentElement._breakpointItem.compareTo(element._breakpointItem) > 0) - break; - currentElement = currentElement.nextSibling; - } - this._addListElement(element, currentElement); - - if (breakpointItem.click) { - element.addStyleClass("cursor-pointer"); - element.addEventListener("click", breakpointItem.click.bind(breakpointItem), false); - } - element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this, breakpointItem), true); - }, - - _contextMenuEventFired: function(breakpointItem, event) - { - var contextMenu = new WebInspector.ContextMenu(); - contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), breakpointItem.remove.bind(breakpointItem)); - contextMenu.show(event); - }, - _addListElement: function(element, beforeElement) { if (beforeElement) @@ -260,7 +229,7 @@ WebInspector.NativeBreakpointsSidebarPane.prototype = { } }, - _projectChanged: function() + _reset: function() { this.listElement.removeChildren(); if (this.listElement.parentElement) { @@ -377,9 +346,9 @@ WebInspector.XHRBreakpointsSidebarPane.prototype = { _checkboxClicked: function(url, event) { if (event.target.checked) - WebInspector.breakpointManager.setXHRBreakpoint(url); + BrowserDebuggerAgent.setXHRBreakpoint(url); else - WebInspector.breakpointManager.removeXHRBreakpoint(url); + BrowserDebuggerAgent.removeXHRBreakpoint(url); this._saveBreakpoints(); }, @@ -443,98 +412,11 @@ WebInspector.XHRBreakpointsSidebarPane.prototype = { if (breakpoint && typeof breakpoint.url === "string") this._setBreakpoint(breakpoint.url, breakpoint.enabled); } - }, - - _projectChanged: function() - { } } WebInspector.XHRBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype; -WebInspector.BreakpointItem = function(breakpoint) -{ - this._breakpoint = breakpoint; - - this._element = document.createElement("li"); - - var checkboxElement = document.createElement("input"); - checkboxElement.className = "checkbox-elem"; - checkboxElement.type = "checkbox"; - checkboxElement.checked = this._breakpoint.enabled; - checkboxElement.addEventListener("click", this._checkboxClicked.bind(this), false); - this._element.appendChild(checkboxElement); - - this._createLabelElement(); - - this._breakpoint.addEventListener("enable-changed", this._enableChanged, this); - this._breakpoint.addEventListener("hit-state-changed", this._hitStateChanged, this); - this._breakpoint.addEventListener("label-changed", this._labelChanged, this); - this._breakpoint.addEventListener("removed", this.dispatchEventToListeners.bind(this, "removed")); - if (breakpoint.click) - this.click = breakpoint.click.bind(breakpoint); -} - -WebInspector.BreakpointItem.prototype = { - get element() - { - return this._element; - }, - - compareTo: function(other) - { - return this._breakpoint.compareTo(other._breakpoint); - }, - - populateEditElement: function(element) - { - this._breakpoint.populateEditElement(element); - }, - - remove: function() - { - this._breakpoint.remove(); - }, - - _checkboxClicked: function(event) - { - this._breakpoint.enabled = !this._breakpoint.enabled; - - // Breakpoint element may have it's own click handler. - event.stopPropagation(); - }, - - _enableChanged: function(event) - { - var checkbox = this._element.firstChild; - checkbox.checked = this._breakpoint.enabled; - }, - - _hitStateChanged: function(event) - { - if (event.target.hit) { - this._element.addStyleClass("breakpoint-hit"); - this.dispatchEventToListeners("breakpoint-hit"); - } else - this._element.removeStyleClass("breakpoint-hit"); - }, - - _labelChanged: function(event) - { - this._element.removeChild(this._labelElement); - this._createLabelElement(); - }, - - _createLabelElement: function() - { - this._labelElement = document.createElement("span"); - this._breakpoint.populateLabelElement(this._labelElement); - this._element.appendChild(this._labelElement); - } -} - -WebInspector.BreakpointItem.prototype.__proto__ = WebInspector.Object.prototype; - WebInspector.EventListenerBreakpointsSidebarPane = function() { WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints")); diff --git a/Source/WebCore/inspector/front-end/CSSStyleModel.js b/Source/WebCore/inspector/front-end/CSSStyleModel.js index 148bfd8..7596bc4 100644 --- a/Source/WebCore/inspector/front-end/CSSStyleModel.js +++ b/Source/WebCore/inspector/front-end/CSSStyleModel.js @@ -30,6 +30,7 @@ WebInspector.CSSStyleModel = function() { + new WebInspector.CSSStyleModelResourceBinding(this); } WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray) @@ -40,6 +41,10 @@ WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray) return result; } +WebInspector.CSSStyleModel.Events = { + StyleSheetChanged: 0 +} + WebInspector.CSSStyleModel.prototype = { getStylesAsync: function(nodeId, userCallback) { @@ -124,7 +129,7 @@ WebInspector.CSSStyleModel.prototype = { var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0); var rule = WebInspector.CSSRule.parsePayload(rulePayload); successCallback(rule, doesAffectSelectedNode); - this._styleSheetChanged(rule.id.styleSheetId, true); + this._fireStyleSheetChanged(rule.id.styleSheetId, true); } function callback(nodeId, successCallback, failureCallback, error, newSelector, rulePayload) @@ -133,7 +138,7 @@ WebInspector.CSSStyleModel.prototype = { if (error) failureCallback(); else - DOMAgent.querySelectorAll(nodeId, newSelector, true, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); + WebInspector.domAgent.querySelectorAll(nodeId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); } CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback, newSelector)); @@ -146,7 +151,7 @@ WebInspector.CSSStyleModel.prototype = { var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0); var rule = WebInspector.CSSRule.parsePayload(rulePayload); successCallback(rule, doesAffectSelectedNode); - this._styleSheetChanged(rule.id.styleSheetId, true); + this._fireStyleSheetChanged(rule.id.styleSheetId, true); } function callback(successCallback, failureCallback, selector, error, rulePayload) @@ -155,39 +160,39 @@ WebInspector.CSSStyleModel.prototype = { // Invalid syntax for a selector failureCallback(); } else - DOMAgent.querySelectorAll(nodeId, selector, true, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); + WebInspector.domAgent.querySelectorAll(nodeId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); } CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector)); }, - _styleSheetChanged: function(styleSheetId, majorChange) + _fireStyleSheetChanged: function(styleSheetId, majorChange, callback) { - if (!majorChange || !styleSheetId) + callback = callback || function() {}; + + if (!majorChange || !styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged)) { + callback(); return; + } - function callback(error, href, content) + function mycallback(error, content) { - if (error) - return; - var resource = WebInspector.resourceForURL(href); - if (resource && resource.type === WebInspector.Resource.Type.Stylesheet) { - resource.setContent(content, this._onRevert.bind(this, styleSheetId)); - this.dispatchEventToListeners("stylesheet changed"); - } + if (!error) + this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, content: content, majorChange: majorChange }); + callback(); } - CSSAgent.getStyleSheetText(styleSheetId, callback.bind(this)); + + CSSAgent.getStyleSheetText(styleSheetId, mycallback.bind(this)); }, - _onRevert: function(styleSheetId, contentToRevertTo) + setStyleSheetText: function(styleSheetId, newText, majorChange, userCallback) { - function callback(error, success) + function callback(error) { - if (error) - return; - this._styleSheetChanged(styleSheetId, true); + if (!error) + this._fireStyleSheetChanged(styleSheetId, majorChange, userCallback ? userCallback.bind(this, error) : null); } - CSSAgent.setStyleSheetText(styleSheetId, contentToRevertTo, callback.bind(this)); + CSSAgent.setStyleSheetText(styleSheetId, newText, callback.bind(this)); } } @@ -196,8 +201,10 @@ WebInspector.CSSStyleModel.prototype.__proto__ = WebInspector.Object.prototype; WebInspector.CSSStyleDeclaration = function(payload) { this.id = payload.styleId; - this.properties = payload.properties; - this._shorthandValues = payload.shorthandValues; + this.width = payload.width; + this.height = payload.height; + this.range = payload.range; + this._shorthandValues = WebInspector.CSSStyleDeclaration.buildShorthandValueMap(payload.shorthandEntries); this._livePropertyMap = {}; // LIVE properties (source-based or style-based) : { name -> CSSProperty } this._allProperties = []; // ALL properties: [ CSSProperty ] this._longhandProperties = {}; // shorthandName -> [ CSSProperty ] @@ -232,6 +239,14 @@ WebInspector.CSSStyleDeclaration = function(payload) this.cssText = payload.cssText; } +WebInspector.CSSStyleDeclaration.buildShorthandValueMap = function(shorthandEntries) +{ + var result = {}; + for (var i = 0; i < shorthandEntries.length; ++i) + result[shorthandEntries[i].name] = shorthandEntries[i].value; + return result; +} + WebInspector.CSSStyleDeclaration.parsePayload = function(payload) { return new WebInspector.CSSStyleDeclaration(payload); @@ -351,11 +366,12 @@ WebInspector.CSSStyleDeclaration.prototype = { if (!userCallback) return; - if (error) + if (error) { + console.error(JSON.stringify(error)); userCallback(null); - else { + } else { userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload)); - WebInspector.cssModel._styleSheetChanged(this.id.styleSheetId, true); + WebInspector.cssModel._fireStyleSheetChanged(this.id.styleSheetId, true); } } @@ -476,14 +492,14 @@ WebInspector.CSSProperty.prototype = { function enabledCallback(style) { if (style) - WebInspector.cssModel._styleSheetChanged(style.id.styleSheetId, majorChange); + WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange); if (userCallback) userCallback(style); } function callback(error, stylePayload) { - if (!error && stylePayload) { + if (!error) { this.text = propertyText; var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload); var newProperty = style.allProperties[this.index]; @@ -491,11 +507,11 @@ WebInspector.CSSProperty.prototype = { if (newProperty && this.disabled && !propertyText.match(/^\s*$/)) { newProperty.setDisabled(false, enabledCallback); return; - } else - WebInspector.cssModel._styleSheetChanged(style.id.styleSheetId, majorChange); - if (userCallback) - userCallback(style); + } + + WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange, userCallback.bind(this, style)); } else { + console.error(JSON.stringify(error)); if (userCallback) userCallback(null); } @@ -530,7 +546,7 @@ WebInspector.CSSProperty.prototype = { else { var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload); userCallback(style); - WebInspector.cssModel._styleSheetChanged(this.ownerStyle.id.styleSheetId, false); + WebInspector.cssModel._fireStyleSheetChanged(this.ownerStyle.id.styleSheetId, false); } } @@ -571,16 +587,109 @@ WebInspector.CSSStyleSheet.prototype = { return this._text; }, - setText: function(newText, userCallback) + setText: function(newText, majorChange, userCallback) { - function callback(error, isChangeSuccessful) + function callback(error) { if (userCallback) - userCallback(isChangeSuccessful); - if (isChangeSuccessful) - WebInspector.cssModel._styleSheetChanged(this.id, true); + userCallback(error); + if (!error) + WebInspector.cssModel._fireStyleSheetChanged(this.id, majorChange); } CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this)); } } + +WebInspector.CSSStyleModelResourceBinding = function(cssModel) +{ + this._cssModel = cssModel; + this._urlToStyleSheetId = {}; + this._styleSheetIdToURL = {}; + this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); + WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Stylesheet, this); +} + +WebInspector.CSSStyleModelResourceBinding.prototype = { + setContent: function(resource, content, majorChange, userCallback) + { + if (this._urlToStyleSheetId[resource.url]) { + this._innerSetContent(resource.url, content, majorChange, userCallback); + return; + } + this._loadStyleSheetHeaders(this._innerSetContent.bind(this, resource.url, content, majorChange, userCallback)); + }, + + _frameNavigated: function(event) + { + var frameId = event.data; + if (!frameId) { + // Main frame navigation - clear history. + this._urlToStyleSheetId = {}; + this._styleSheetIdToURL = {}; + } + }, + + _innerSetContent: function(url, content, majorChange, userCallback, error) + { + if (error) { + userCallback(error); + return; + } + + var styleSheetId = this._urlToStyleSheetId[url]; + if (!styleSheetId) { + if (userCallback) + userCallback("No stylesheet found: " + url); + return; + } + this._cssModel.setStyleSheetText(styleSheetId, content, majorChange, userCallback); + }, + + _loadStyleSheetHeaders: function(callback) + { + function didGetAllStyleSheets(error, infos) + { + if (error) { + callback(error); + return; + } + + for (var i = 0; i < infos.length; ++i) { + var info = infos[i]; + this._urlToStyleSheetId[info.sourceURL] = info.styleSheetId; + this._styleSheetIdToURL[info.styleSheetId] = info.sourceURL; + } + callback(); + } + CSSAgent.getAllStyleSheets(didGetAllStyleSheets.bind(this)); + }, + + _styleSheetChanged: function(event) + { + var styleSheetId = event.data.styleSheetId; + function setContent() + { + var url = this._styleSheetIdToURL[styleSheetId]; + if (!url) + return; + + var resource = WebInspector.resourceForURL(url); + if (!resource) + return; + + var majorChange = event.data.majorChange; + if (majorChange) + resource.addRevision(event.data.content); + } + + if (!this._styleSheetIdToURL[styleSheetId]) { + this._loadStyleSheetHeaders(setContent.bind(this)); + return; + } + setContent.call(this); + } +} + +WebInspector.CSSStyleModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype; diff --git a/Source/WebCore/inspector/front-end/CallStackSidebarPane.js b/Source/WebCore/inspector/front-end/CallStackSidebarPane.js index 3d71101..80187ea 100644 --- a/Source/WebCore/inspector/front-end/CallStackSidebarPane.js +++ b/Source/WebCore/inspector/front-end/CallStackSidebarPane.js @@ -46,20 +46,9 @@ WebInspector.CallStackSidebarPane.prototype = { return; } - var title; - var subtitle; - var script; - for (var i = 0; i < callFrames.length; ++i) { var callFrame = callFrames[i]; - switch (callFrame.type) { - case "function": - title = callFrame.functionName || WebInspector.UIString("(anonymous function)"); - break; - case "program": - title = WebInspector.UIString("(program)"); - break; - } + var title = callFrame.functionName || WebInspector.UIString("(anonymous function)"); var subtitle; if (!callFrame.isInternalScript) @@ -71,7 +60,7 @@ WebInspector.CallStackSidebarPane.prototype = { placard.callFrame = callFrame; placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false); - function didGetSourceLocation(placard, sourceFileId, lineNumber, columnNumber) + function didGetSourceLine(placard, sourceFileId, lineNumber) { if (placard.subtitle) placard.subtitle += ":" + (lineNumber + 1); @@ -79,16 +68,11 @@ WebInspector.CallStackSidebarPane.prototype = { placard.subtitle = WebInspector.UIString("line %d", lineNumber + 1); placard._text = WebInspector.UIString("%s() at %s", placard.title, placard.subtitle); } - callFrame.sourceLocation(didGetSourceLocation.bind(this, placard)); + callFrame.sourceLine(didGetSourceLine.bind(this, placard)); this.placards.push(placard); this.bodyElement.appendChild(placard.element); } - - if (details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint) { - if (details.eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.DOM) - this._domBreakpointHit(details.eventData); - } }, set selectedCallFrame(x) @@ -187,19 +171,10 @@ WebInspector.CallStackSidebarPane.prototype = { { var statusMessageElement = document.createElement("div"); statusMessageElement.className = "info"; - statusMessageElement.textContent = status; - this.bodyElement.appendChild(statusMessageElement); - }, - - _domBreakpointHit: function(eventData) - { - var breakpoint = WebInspector.breakpointManager.breakpointViewForEventData(eventData); - if (!breakpoint) - return; - - var statusMessageElement = document.createElement("div"); - statusMessageElement.className = "info"; - breakpoint.populateStatusMessageElement(statusMessageElement, eventData); + if (typeof status === "string") + statusMessageElement.textContent = status; + else + statusMessageElement.appendChild(status); this.bodyElement.appendChild(statusMessageElement); } } diff --git a/Source/WebCore/inspector/front-end/ConsoleView.js b/Source/WebCore/inspector/front-end/ConsoleView.js index f3e3425..4ab16d9e 100644 --- a/Source/WebCore/inspector/front-end/ConsoleView.js +++ b/Source/WebCore/inspector/front-end/ConsoleView.js @@ -105,7 +105,7 @@ WebInspector.ConsoleView.prototype = { _registerConsoleDomainDispatcher: function() { var console = this; var dispatcher = { - consoleMessage: function(payload) + messageAdded: function(payload) { var consoleMessage = new WebInspector.ConsoleMessage( payload.source, @@ -114,14 +114,14 @@ WebInspector.ConsoleView.prototype = { payload.line, payload.url, payload.repeatCount, - payload.message, + payload.text, payload.parameters, payload.stackTrace, - payload.requestId); + payload.networkIdentifier); console.addMessage(consoleMessage); }, - consoleMessageRepeatCountUpdated: function(count) + messageRepeatCountUpdated: function(count) { var msg = console.previousMessage; var prevRepeatCount = msg.totalRepeatCount; @@ -140,7 +140,7 @@ WebInspector.ConsoleView.prototype = { } }, - consoleMessagesCleared: function() + messagesCleared: function() { console.clearMessages(); }, @@ -362,7 +362,7 @@ WebInspector.ConsoleView.prototype = { { if (!result) return; - result.getProperties(true, false, evaluatedProperties.bind(this)); + result.getAllProperties(evaluatedProperties.bind(this)); } function evaluatedProperties(properties) @@ -623,7 +623,7 @@ WebInspector.ConsoleView.prototype = { _formatarray: function(arr, elem) { - arr.getOwnProperties(false, this._printArray.bind(this, elem)); + arr.getOwnProperties(this._printArray.bind(this, elem)); }, _formatstring: function(output, elem) @@ -691,7 +691,7 @@ WebInspector.ConsoleMessage = function(source, type, level, line, url, repeatCou if (stackTrace && stackTrace.length) { var topCallFrame = stackTrace[0]; if (!this.url) - this.url = topCallFrame.scriptName; + this.url = topCallFrame.url; if (!this.line) this.line = topCallFrame.lineNumber; } @@ -923,7 +923,7 @@ WebInspector.ConsoleMessage.prototype = { messageTextElement.appendChild(document.createTextNode(functionName)); content.appendChild(messageTextElement); - var urlElement = WebInspector.linkifyResourceAsNode(frame.scriptName, "scripts", frame.lineNumber, "console-message-url"); + var urlElement = WebInspector.linkifyResourceAsNode(frame.url, "scripts", frame.lineNumber, "console-message-url"); content.appendChild(urlElement); var treeElement = new TreeElement(content); @@ -1027,10 +1027,10 @@ WebInspector.ConsoleMessage.prototype = { var l = this._stackTrace; var r = msg._stackTrace; for (var i = 0; i < l.length; i++) { - if (l[i].scriptName !== r[i].scriptName || + if (l[i].url !== r[i].url || l[i].functionName !== r[i].functionName || l[i].lineNumber !== r[i].lineNumber || - l[i].column !== r[i].column) + l[i].columnNumber !== r[i].columnNumber) return false; } } @@ -1047,33 +1047,33 @@ WebInspector.ConsoleMessage.prototype = { // Note: Keep these constants in sync with the ones in Console.h WebInspector.ConsoleMessage.MessageSource = { - HTML: 0, - WML: 1, - XML: 2, - JS: 3, - CSS: 4, - Other: 5 + HTML: "html", + WML: "wml", + XML: "xml", + JS: "javascript", + CSS: "css", + Other: "other" } WebInspector.ConsoleMessage.MessageType = { - Log: 0, - Object: 1, - Trace: 2, - StartGroup: 3, - StartGroupCollapsed: 4, - EndGroup: 5, - Assert: 6, - UncaughtException: 7, - NetworkError:8, - Result: 9 + Log: "log", + Object: "other", + Trace: "trace", + StartGroup: "startGroup", + StartGroupCollapsed: "startGroupCollapsed", + EndGroup: "endGroup", + Assert: "assert", + UncaughtException: "uncaughtException", + NetworkError: "networkError", + Result: "result" } WebInspector.ConsoleMessage.MessageLevel = { - Tip: 0, - Log: 1, - Warning: 2, - Error: 3, - Debug: 4 + Tip: "tip", + Log: "log", + Warning: "warning", + Error: "error", + Debug: "debug" } WebInspector.ConsoleCommand = function(command) diff --git a/Source/WebCore/inspector/front-end/DOMAgent.js b/Source/WebCore/inspector/front-end/DOMAgent.js index a2a9c2d..5889320 100644 --- a/Source/WebCore/inspector/front-end/DOMAgent.js +++ b/Source/WebCore/inspector/front-end/DOMAgent.js @@ -59,8 +59,6 @@ WebInspector.DOMNode = function(doc, payload) { this.style = null; this._matchedCSSRules = []; - this.breakpoints = {}; - if (this._nodeType === Node.ELEMENT_NODE) { // HTML and BODY from internal iframes should not overwrite top-level ones. if (!this.ownerDocument.documentElement && this._nodeName === "HTML") @@ -223,6 +221,28 @@ WebInspector.DOMNode.prototype = { return path.join(","); }, + appropriateSelectorFor: function(justSelector) + { + var lowerCaseName = this.localName() || node.nodeName().toLowerCase(); + + var id = this.getAttribute("id"); + if (id) { + var selector = "#" + id; + return (justSelector ? selector : lowerCaseName + selector); + } + + var className = this.getAttribute("class"); + if (className) { + var selector = "." + className.replace(/\s+/, "."); + return (justSelector ? selector : lowerCaseName + selector); + } + + if (lowerCaseName === "input" && this.getAttribute("type")) + return lowerCaseName + "[type=\"" + this.getAttribute("type") + "\"]"; + + return lowerCaseName; + }, + _setAttributesPayload: function(attrs) { this._attributes = []; @@ -328,52 +348,69 @@ WebInspector.DOMAgent.prototype = { return; } - function mycallback(error, root) + if (this._pendingDocumentRequestCallbacks) { + this._pendingDocumentRequestCallbacks.push(callback); + return; + } + + this._pendingDocumentRequestCallbacks = [callback]; + + function onDocumentAvailable(error, root) { if (!error) this._setDocument(root); - if (callback) - callback(this._document); + for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) { + var callback = this._pendingDocumentRequestCallbacks[i]; + if (callback) + callback(this._document); + } + delete this._pendingDocumentRequestCallbacks; } - DOMAgent.getDocument(mycallback.bind(this)); + + DOMAgent.getDocument(onDocumentAvailable.bind(this)); }, pushNodeToFrontend: function(objectId, callback) { - function callbackWrapper(error, nodeId) - { - if (callback) - callback(error ? 0 : nodeId); - } - - function mycallback() - { - if (this._document) - DOMAgent.pushNodeToFrontend(objectId, callbackWrapper); - else - callbackWrapper("No document"); - } - - this.requestDocument(mycallback.bind(this)); + this._dispatchWhenDocumentAvailable(DOMAgent.pushNodeToFrontend.bind(DOMAgent), objectId, callback); }, pushNodeByPathToFrontend: function(path, callback) { - function callbackWrapper(error, nodeId) + this._dispatchWhenDocumentAvailable(DOMAgent.pushNodeByPathToFrontend.bind(DOMAgent), path, callback); + }, + + _wrapClientCallback: function(callback) + { + if (!callback) + return; + return function(error, result) { - if (callback) - callback(error ? 0 : nodeId); + callback(error ? null : result); } + }, - function mycallback() + _dispatchWhenDocumentAvailable: function(action) + { + var requestArguments = Array.prototype.slice.call(arguments, 1); + var callbackWrapper; + + if (typeof requestArguments[requestArguments.length - 1] === "function") { + var callback = requestArguments.pop(); + callbackWrapper = this._wrapClientCallback(callback); + requestArguments.push(callbackWrapper); + } + function onDocumentAvailable() { if (this._document) - DOMAgent.pushNodeByPathToFrontend(path, callbackWrapper); - else - callbackWrapper("No document"); + action.apply(null, requestArguments); + else { + if (callbackWrapper) + callbackWrapper("No document"); + } } - this.requestDocument(mycallback.bind(this)); + this.requestDocument(onDocumentAvailable.bind(this)); }, _attributesUpdated: function(nodeId, attrsArray) @@ -465,17 +502,8 @@ WebInspector.DOMAgent.prototype = { parent.removeChild_(node); this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node:node, parent:parent}); delete this._idToDOMNode[nodeId]; - this._removeBreakpoints(node); - }, - - _removeBreakpoints: function(node) - { - for (var type in node.breakpoints) - node.breakpoints[type].remove(); - if (!node.children) - return; - for (var i = 0; i < node.children.length; ++i) - this._removeBreakpoints(node.children[i]); + if (Preferences.nativeInstrumentationEnabled) + WebInspector.panels.elements.sidebarPanes.domBreakpoints.nodeRemoved(node); }, performSearch: function(query, searchResultCollector, searchSynchronously) @@ -488,6 +516,16 @@ WebInspector.DOMAgent.prototype = { { delete this._searchResultCollector; DOMAgent.cancelSearch(); + }, + + querySelector: function(nodeId, selectors, callback) + { + DOMAgent.querySelector(nodeId, selectors, this._wrapClientCallback(callback)); + }, + + querySelectorAll: function(nodeId, selectors, callback) + { + DOMAgent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback)); } } diff --git a/Source/WebCore/inspector/front-end/DOMBreakpointsSidebarPane.js b/Source/WebCore/inspector/front-end/DOMBreakpointsSidebarPane.js new file mode 100644 index 0000000..df31f96 --- /dev/null +++ b/Source/WebCore/inspector/front-end/DOMBreakpointsSidebarPane.js @@ -0,0 +1,308 @@ +/* + * 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.DOMBreakpointsSidebarPane = function() +{ + WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("DOM Breakpoints")); + + this._breakpointElements = {}; + + this._breakpointTypes = { + SubtreeModified: 0, + AttributeModified: 1, + NodeRemoved: 2 + }; + this._breakpointTypeLabels = [ + WebInspector.UIString("Subtree Modified"), + WebInspector.UIString("Attribute Modified"), + WebInspector.UIString("Node Removed") + ]; + this._contextMenuLabels = [ + WebInspector.UIString("Break on Subtree Modifications"), + WebInspector.UIString("Break on Attributes Modifications"), + WebInspector.UIString("Break on Node Removal") + ]; +} + +WebInspector.DOMBreakpointsSidebarPane.prototype = { + setInspectedURL: function(url) + { + this._reset(); + this._inspectedURL = url.removeURLFragment(); + }, + + populateNodeContextMenu: function(node, contextMenu) + { + var nodeBreakpoints = {}; + for (var id in this._breakpointElements) { + var element = this._breakpointElements[id]; + if (element._node === node) + nodeBreakpoints[element._type] = true; + } + + function toggleBreakpoint(type) + { + if (!nodeBreakpoints[type]) + this._setBreakpoint(node, type, true); + else + this._removeBreakpoint(node, type); + this._saveBreakpoints(); + } + + for (var type = 0; type < 3; ++type) { + var label = this._contextMenuLabels[type]; + contextMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints[type]); + } + }, + + createBreakpointHitStatusMessage: function(eventData, callback) + { + if (eventData.type === this._breakpointTypes.SubtreeModified) { + var targetNodeObject = WebInspector.RemoteObject.fromPayload(eventData.targetNode); + function didPushNodeToFrontend(targetNodeId) + { + if (targetNodeId) + targetNodeObject.release(); + this._doCreateBreakpointHitStatusMessage(eventData, targetNodeId, callback); + } + targetNodeObject.pushNodeToFrontend(didPushNodeToFrontend.bind(this)); + } else + this._doCreateBreakpointHitStatusMessage(eventData, null, callback); + }, + + _doCreateBreakpointHitStatusMessage: function (eventData, targetNodeId, callback) + { + var message; + var typeLabel = this._breakpointTypeLabels[eventData.type]; + var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(eventData.nodeId); + var substitutions = [typeLabel, linkifiedNode]; + var targetNode = ""; + if (targetNodeId) + targetNode = WebInspector.panels.elements.linkifyNodeById(targetNodeId); + + if (eventData.type === this._breakpointTypes.SubtreeModified) { + if (eventData.insertion) { + if (targetNodeId !== eventData.nodeId) { + message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s."; + substitutions.push(targetNode); + } else + message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node."; + } else { + message = "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed."; + substitutions.push(targetNode); + } + } else + message = "Paused on a \"%s\" breakpoint set on %s."; + + var element = document.createElement("span"); + var formatters = { + s: function(substitution) + { + return substitution; + } + }; + function append(a, b) + { + if (typeof b === "string") + b = document.createTextNode(b); + element.appendChild(b); + } + WebInspector.formatLocalized(message, substitutions, formatters, "", append); + + callback(element); + }, + + nodeRemoved: function(node) + { + this._removeBreakpointsForNode(node); + if (!node.children) + return; + for (var i = 0; i < node.children.length; ++i) + this._removeBreakpointsForNode(node.children[i]); + this._saveBreakpoints(); + }, + + _removeBreakpointsForNode: function(node) + { + for (var id in this._breakpointElements) { + var element = this._breakpointElements[id]; + if (element._node === node) + this._removeBreakpoint(element._node, element._type); + } + }, + + _setBreakpoint: function(node, type, enabled) + { + var breakpointId = this._createBreakpointId(node.id, type); + if (breakpointId in this._breakpointElements) + return; + + var element = document.createElement("li"); + element._node = node; + element._type = type; + element.addEventListener("contextmenu", this._contextMenu.bind(this, node, type), true); + + var checkboxElement = document.createElement("input"); + checkboxElement.className = "checkbox-elem"; + checkboxElement.type = "checkbox"; + checkboxElement.checked = enabled; + checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, node, type), false); + element._checkboxElement = checkboxElement; + element.appendChild(checkboxElement); + + var labelElement = document.createElement("span"); + element.appendChild(labelElement); + + var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(node.id); + linkifiedNode.addStyleClass("monospace"); + labelElement.appendChild(linkifiedNode); + + var description = document.createElement("div"); + description.className = "source-text"; + description.textContent = this._breakpointTypeLabels[type]; + labelElement.appendChild(description); + + var currentElement = this.listElement.firstChild; + while (currentElement) { + if (currentElement._type && currentElement._type < element._type) + break; + currentElement = currentElement.nextSibling; + } + this._addListElement(element, currentElement); + this._breakpointElements[breakpointId] = element; + if (enabled) + BrowserDebuggerAgent.setDOMBreakpoint(node.id, type); + }, + + _removeBreakpoint: function(node, type) + { + var breakpointId = this._createBreakpointId(node.id, type); + var element = this._breakpointElements[breakpointId]; + if (!element) + return; + + this._removeListElement(element); + delete this._breakpointElements[breakpointId]; + if (element._checkboxElement.checked) + BrowserDebuggerAgent.removeDOMBreakpoint(node.id, type); + }, + + _contextMenu: function(node, type, event) + { + var contextMenu = new WebInspector.ContextMenu(); + function removeBreakpoint() + { + this._removeBreakpoint(node, type); + this._saveBreakpoints(); + } + contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this)); + contextMenu.show(event); + }, + + _checkboxClicked: function(node, type, event) + { + if (event.target.checked) + BrowserDebuggerAgent.setDOMBreakpoint(node.id, type); + else + BrowserDebuggerAgent.removeDOMBreakpoint(node.id, type); + this._saveBreakpoints(); + }, + + highlightBreakpoint: function(eventData) + { + var breakpointId = this._createBreakpointId(eventData.nodeId, eventData.type); + var element = this._breakpointElements[breakpointId]; + if (!element) + return; + this.expanded = true; + element.addStyleClass("breakpoint-hit"); + this._highlightedElement = element; + }, + + clearBreakpointHighlight: function() + { + if (this._highlightedElement) { + this._highlightedElement.removeStyleClass("breakpoint-hit"); + delete this._highlightedElement; + } + }, + + _createBreakpointId: function(nodeId, type) + { + return nodeId + ":" + type; + }, + + _saveBreakpoints: function() + { + var breakpoints = []; + var storedBreakpoints = WebInspector.settings.domBreakpoints; + for (var i = 0; i < storedBreakpoints.length; ++i) { + var breakpoint = storedBreakpoints[i]; + if (breakpoint.url !== this._inspectedURL) + breakpoints.push(breakpoint); + } + for (var id in this._breakpointElements) { + var element = this._breakpointElements[id]; + breakpoints.push({ url: this._inspectedURL, path: element._node.path(), type: element._type, enabled: element._checkboxElement.checked }); + } + WebInspector.settings.domBreakpoints = breakpoints; + }, + + restoreBreakpoints: function() + { + var pathToBreakpoints = {}; + + function didPushNodeByPathToFrontend(path, nodeId) + { + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + return; + + var breakpoints = pathToBreakpoints[path]; + for (var i = 0; i < breakpoints.length; ++i) + this._setBreakpoint(node, breakpoints[i].type, breakpoints[i].enabled); + } + + var breakpoints = WebInspector.settings.domBreakpoints; + for (var i = 0; i < breakpoints.length; ++i) { + var breakpoint = breakpoints[i]; + if (breakpoint.url !== this._inspectedURL) + continue; + var path = breakpoint.path; + if (!pathToBreakpoints[path]) { + pathToBreakpoints[path] = []; + WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path)); + } + pathToBreakpoints[path].push(breakpoint); + } + } +} + +WebInspector.DOMBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype; diff --git a/Source/WebCore/inspector/front-end/DataGrid.js b/Source/WebCore/inspector/front-end/DataGrid.js index 6d54941..7d7109a 100644 --- a/Source/WebCore/inspector/front-end/DataGrid.js +++ b/Source/WebCore/inspector/front-end/DataGrid.js @@ -133,6 +133,7 @@ WebInspector.DataGrid = function(columns, editCallback, deleteCallback) this._columnsArray = []; for (var columnIdentifier in columns) { columns[columnIdentifier].ordinal = this._columnsArray.length; + columns[columnIdentifier].identifier = columnIdentifier; this._columnsArray.push(columns[columnIdentifier]); } diff --git a/Source/WebCore/inspector/front-end/DebuggerModel.js b/Source/WebCore/inspector/front-end/DebuggerModel.js index c1d59b1..a33d69b 100644 --- a/Source/WebCore/inspector/front-end/DebuggerModel.js +++ b/Source/WebCore/inspector/front-end/DebuggerModel.js @@ -31,7 +31,6 @@ WebInspector.DebuggerModel = function() { this._debuggerPausedDetails = {}; - this._breakpoints = {}; this._scripts = {}; InspectorBackend.registerDomainDispatcher("Debugger", new WebInspector.DebuggerDispatcher(this)); @@ -66,16 +65,15 @@ WebInspector.DebuggerModel.prototype = { _debuggerWasDisabled: function() { - this._breakpoints = {}; this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasDisabled); }, - continueToLocation: function(sourceID, lineNumber, columnNumber) + continueToLocation: function(location) { - DebuggerAgent.continueToLocation(sourceID, lineNumber, columnNumber); + DebuggerAgent.continueToLocation(location); }, - setBreakpoint: function(url, lineNumber, columnNumber, condition, enabled, callback) + setBreakpoint: function(url, lineNumber, columnNumber, condition, callback) { // Adjust column if needed. var minColumnNumber = 0; @@ -88,62 +86,35 @@ WebInspector.DebuggerModel.prototype = { function didSetBreakpoint(error, breakpointId, locations) { - var breakpoint; - if (!error && breakpointId) { - breakpoint = new WebInspector.Breakpoint(breakpointId, url, "", lineNumber, columnNumber, condition, enabled); - breakpoint.locations = locations; - this._breakpoints[breakpointId] = breakpoint; - } if (callback) - callback(breakpoint); + callback(error ? null : breakpointId, locations); } - DebuggerAgent.setBreakpointByUrl(url, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this)); + DebuggerAgent.setBreakpointByUrl(url, lineNumber, columnNumber, condition, didSetBreakpoint.bind(this)); }, - setBreakpointBySourceId: function(sourceID, lineNumber, columnNumber, condition, enabled, callback) + setBreakpointBySourceId: function(location, condition, callback) { - function didSetBreakpoint(error, breakpointId, actualLineNumber, actualColumnNumber) + function didSetBreakpoint(error, breakpointId, actualLocation) { - var breakpoint; - if (!error && breakpointId) { - breakpoint = new WebInspector.Breakpoint(breakpointId, "", sourceID, lineNumber, columnNumber, condition, enabled); - breakpoint.addLocation(sourceID, actualLineNumber, actualColumnNumber); - this._breakpoints[breakpointId] = breakpoint; - } if (callback) - callback(breakpoint); + callback(error ? null : breakpointId, [actualLocation]); } - DebuggerAgent.setBreakpoint(sourceID, lineNumber, columnNumber, condition, enabled, didSetBreakpoint.bind(this)); + DebuggerAgent.setBreakpoint(location, condition, didSetBreakpoint.bind(this)); }, - removeBreakpoint: function(breakpointId) + removeBreakpoint: function(breakpointId, callback) { - DebuggerAgent.removeBreakpoint(breakpointId); - delete this._breakpoints[breakpointId]; + DebuggerAgent.removeBreakpoint(breakpointId, callback); }, - _breakpointResolved: function(breakpointId, sourceID, lineNumber, columnNumber) + _breakpointResolved: function(breakpointId, location) { - var breakpoint = this._breakpoints[breakpointId]; - breakpoint.addLocation(sourceID, lineNumber, columnNumber); - this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, breakpoint); - }, - - get breakpoints() - { - return this._breakpoints; + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, {breakpointId: breakpointId, location: location}); }, reset: function() { this._debuggerPausedDetails = {}; - for (var id in this._breakpoints) { - var breakpoint = this._breakpoints[id]; - if (!breakpoint.url) - delete this._breakpoints[id]; - else - breakpoint.locations = []; - } this._scripts = {}; this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Reset); }, @@ -176,16 +147,14 @@ WebInspector.DebuggerModel.prototype = { editScriptSource: function(sourceID, newSource, callback) { - DebuggerAgent.editScriptSource(sourceID, newSource, this._didEditScriptSource.bind(this, sourceID, callback)); + this._scripts[sourceID].editSource(newSource, this._didEditScriptSource.bind(this, sourceID, newSource, callback)); }, - _didEditScriptSource: function(sourceID, callback, error, newBody, callFrames) + _didEditScriptSource: function(sourceID, newSource, callback, error, callFrames) { - callback(!error, error || newBody); - if (error) - return; - this._scripts[sourceID].source = newBody; - this._debuggerPausedDetails.callFrames = callFrames; + if (!error && callFrames && callFrames.length) + this._debuggerPausedDetails.callFrames = callFrames; + callback(error); }, get callFrames() @@ -210,16 +179,16 @@ WebInspector.DebuggerModel.prototype = { this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed); }, - _parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType) + _parsedScriptSource: function(sourceID, sourceURL, lineOffset, columnOffset, length, isContentScript) { - var script = new WebInspector.Script(sourceID, sourceURL, "", lineOffset, columnOffset, length, undefined, undefined, scriptWorldType); + var script = new WebInspector.Script(sourceID, sourceURL, lineOffset, columnOffset, length, undefined, undefined, isContentScript); this._scripts[sourceID] = script; this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script); }, _failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage) { - var script = new WebInspector.Script(null, sourceURL, source, startingLine, errorLine, errorMessage, undefined); + var script = new WebInspector.Script(null, sourceURL, startingLine, errorLine, errorMessage, undefined); this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script); } } @@ -258,9 +227,9 @@ WebInspector.DebuggerDispatcher.prototype = { this._debuggerModel._debuggerWasDisabled(); }, - scriptParsed: function(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType) + scriptParsed: function(sourceID, sourceURL, lineOffset, columnOffset, length, isContentScript) { - this._debuggerModel._parsedScriptSource(sourceID, sourceURL, lineOffset, columnOffset, length, scriptWorldType); + this._debuggerModel._parsedScriptSource(sourceID, sourceURL, lineOffset, columnOffset, length, isContentScript); }, scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage) diff --git a/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js b/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js index d12affe..106d62f 100644 --- a/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js +++ b/Source/WebCore/inspector/front-end/DebuggerPresentationModel.js @@ -32,7 +32,9 @@ WebInspector.DebuggerPresentationModel = function() { this._sourceFiles = {}; this._messages = []; - this._presentationBreakpoints = {}; + this._breakpointsByDebuggerId = {}; + this._breakpointsWithoutSourceFile = {}; + this._presentationCallFrames = []; this._selectedCallFrameIndex = 0; @@ -42,7 +44,9 @@ WebInspector.DebuggerPresentationModel = function() WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this); WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this); - WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.Reset, this._reset, this); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.Reset, this._debuggerReset, this); + + new WebInspector.DebuggerPresentationModelResourceBinding(this); } WebInspector.DebuggerPresentationModel.Events = { @@ -59,7 +63,7 @@ WebInspector.DebuggerPresentationModel.Events = { WebInspector.DebuggerPresentationModel.prototype = { _debuggerWasEnabled: function() { - this._restoreBreakpoints(); + this._restoreBreakpointsFromSettings(); }, sourceFile: function(sourceFileId) @@ -67,6 +71,11 @@ WebInspector.DebuggerPresentationModel.prototype = { return this._sourceFiles[sourceFileId]; }, + sourceFileForScriptURL: function(scriptURL) + { + return this._sourceFiles[scriptURL]; + }, + requestSourceFileContent: function(sourceFileId, callback) { this._sourceFiles[sourceFileId].requestContent(callback); @@ -75,18 +84,16 @@ WebInspector.DebuggerPresentationModel.prototype = { _parsedScriptSource: function(event) { this._addScript(event.data); - this._refreshBreakpoints(); }, _failedToParseScriptSource: function(event) { this._addScript(event.data); - this._refreshBreakpoints(); }, _addScript: function(script) { - var sourceFileId = script.sourceURL || script.sourceID; + var sourceFileId = this._createSourceFileId(script.sourceURL, script.sourceID); var sourceFile = this._sourceFiles[sourceFileId]; if (sourceFile) { sourceFile.addScript(script); @@ -100,65 +107,74 @@ WebInspector.DebuggerPresentationModel.prototype = { if (!this._formatSourceFiles) sourceFile = new WebInspector.SourceFile(sourceFileId, script, contentChanged.bind(this)); else - sourceFile = new WebInspector.FormattedSourceFile(sourceFileId, script, contentChanged.bind(this), this._formatter); + sourceFile = new WebInspector.FormattedSourceFile(sourceFileId, script, contentChanged.bind(this), this._formatter()); this._sourceFiles[sourceFileId] = sourceFile; + + this._restoreBreakpoints(sourceFile); + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.SourceFileAdded, sourceFile); }, - _refreshBreakpoints: function() + _restoreBreakpoints: function(sourceFile) { - var breakpoints = WebInspector.debuggerModel.breakpoints; - for (var id in breakpoints) { - if (!(id in this._presentationBreakpoints)) - this._breakpointAdded(breakpoints[id]); + var pendingBreakpoints = this._breakpointsWithoutSourceFile[sourceFile.id]; + for (var i = 0; pendingBreakpoints && i < pendingBreakpoints.length; ++i) { + var breakpointData = pendingBreakpoints[i]; + if ("debuggerId" in breakpointData) { + var breakpoint = new WebInspector.PresentationBreakpoint(sourceFile, breakpointData.lineNumber, breakpointData.condition, breakpointData.enabled); + this._bindDebuggerId(breakpoint, breakpointData.debuggerId); + this._breakpointAdded(breakpoint); + } else + this.setBreakpoint(sourceFile.id, breakpointData.lineNumber, breakpointData.condition, breakpointData.enabled, true); } + delete this._breakpointsWithoutSourceFile[sourceFile.id]; }, canEditScriptSource: function(sourceFileId) { - if (!Preferences.canEditScriptSource) + if (!Preferences.canEditScriptSource || this._formatSourceFiles) return false; var script = this._scriptForSourceFileId(sourceFileId); - return !script.lineOffset && !script.columnOffset; + return !script.lineOffset && !script.columnOffset; }, - editScriptSource: function(sourceFileId, text, callback) + editScriptSource: function(sourceFileId, newSource, callback) { var script = this._scriptForSourceFileId(sourceFileId); var sourceFile = this._sourceFiles[sourceFileId]; - var oldSource = sourceFile.content; - function didEditScriptSource(success, newBodyOrErrorMessage) - { - if (!success) { - callback(false, newBodyOrErrorMessage); - return; - } - var newSource = newBodyOrErrorMessage; - this._updateBreakpointsAfterLiveEdit(sourceFileId, oldSource, newSource); + function didEditScriptSource(oldSource, error) + { + if (!error) { + sourceFile.content = newSource; - var resource = WebInspector.resourceForURL(script.sourceURL); - if (resource) { - var revertHandle = this.editScriptSource.bind(this, sourceFileId, oldSource, sourceFile.reload.bind(sourceFile)); - resource.setContent(newSource, revertHandle); + var resource = WebInspector.resourceForURL(sourceFile.url); + if (resource) + resource.addRevision(newSource); } - callback(true, newSource); + callback(error); - if (WebInspector.debuggerModel.callFrames) + if (!error && WebInspector.debuggerModel.callFrames) this._debuggerPaused(); } - WebInspector.debuggerModel.editScriptSource(script.sourceID, text, didEditScriptSource.bind(this)); + + var oldSource = sourceFile.requestContent(didReceiveSource.bind(this)); + function didReceiveSource(oldSource) + { + WebInspector.debuggerModel.editScriptSource(script.sourceID, newSource, didEditScriptSource.bind(this, oldSource)); + } }, _updateBreakpointsAfterLiveEdit: function(sourceFileId, oldSource, newSource) { + var sourceFile = this._sourceFiles[sourceFileId]; + // Clear and re-create breakpoints according to text diff. var diff = Array.diff(oldSource.split("\n"), newSource.split("\n")); - for (var id in this._presentationBreakpoints) { - var breakpoint = this._presentationBreakpoints[id]; - if (breakpoint.sourceFileId !== sourceFileId) - continue; + for (var lineNumber in sourceFile.breakpoints) { + var breakpoint = sourceFile.breakpoints[lineNumber]; + var lineNumber = breakpoint.lineNumber; this.removeBreakpoint(sourceFileId, lineNumber); @@ -184,13 +200,15 @@ WebInspector.DebuggerPresentationModel.prototype = { toggleFormatSourceFiles: function() { this._formatSourceFiles = !this._formatSourceFiles; - if (this._formatSourceFiles && !this._formatter) - this._formatter = new WebInspector.ScriptFormatter(); + + for (var id in this._sourceFiles) { + var sourceFile = this._sourceFiles[id]; + for (var line in sourceFile.breakpoints) + this._removeBreakpointFromDebugger(sourceFile.breakpoints[line]); + } var messages = this._messages; - this._sourceFiles = {}; - this._messages = []; - this._presentationBreakpoints = {}; + this._reset(); var scripts = WebInspector.debuggerModel.scripts; for (var id in scripts) @@ -199,17 +217,27 @@ WebInspector.DebuggerPresentationModel.prototype = { for (var i = 0; i < messages.length; ++i) this.addConsoleMessage(messages[i]); - this._refreshBreakpoints(); - if (WebInspector.debuggerModel.callFrames) this._debuggerPaused(); }, + formatSourceFilesToggled: function() + { + return this._formatSourceFiles; + }, + + _formatter: function() + { + if (!this._scriptFormatter) + this._scriptFormatter = new WebInspector.ScriptFormatter(); + return this._scriptFormatter; + }, + addConsoleMessage: function(message) { this._messages.push(message); - var sourceFile = this._sourceFileForScriptURL(message.url); + var sourceFile = this._sourceFileForScript(message.url); if (!sourceFile) return; @@ -217,7 +245,7 @@ WebInspector.DebuggerPresentationModel.prototype = { { var presentationMessage = {}; presentationMessage.sourceFileId = sourceFile.id; - presentationMessage.lineNumber = mapping.scriptLocationToSourceLocation(message.line - 1, 0).lineNumber; + presentationMessage.lineNumber = mapping.scriptLocationToSourceLine({lineNumber:message.line - 1, columnNumber:0}); presentationMessage.originalMessage = message; sourceFile.messages.push(presentationMessage); this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, presentationMessage); @@ -236,8 +264,8 @@ WebInspector.DebuggerPresentationModel.prototype = { { function didRequestSourceMapping(mapping) { - var location = mapping.sourceLocationToScriptLocation(lineNumber, 0); - WebInspector.debuggerModel.continueToLocation(location.scriptId, location.lineNumber, location.columnNumber); + var location = mapping.sourceLineToScriptLocation(lineNumber); + WebInspector.debuggerModel.continueToLocation(location); } this._sourceFiles[sourceFileId].requestSourceMapping(didRequestSourceMapping.bind(this)); }, @@ -253,32 +281,104 @@ WebInspector.DebuggerPresentationModel.prototype = { return breakpoints; }, - setBreakpoint: function(sourceFileId, lineNumber, condition, enabled) + setBreakpoint: function(sourceFileId, lineNumber, condition, enabled, dontSaveBreakpoints) { - function didSetBreakpoint(breakpoint) + var sourceFile = this._sourceFiles[sourceFileId]; + if (!sourceFile) + return; + + var breakpoint = new WebInspector.PresentationBreakpoint(sourceFile, lineNumber, condition, enabled); + if (!enabled) { + this._breakpointAdded(breakpoint); + if (!dontSaveBreakpoints) + this._saveBreakpoints(); + return; + } + + function callback() { - if (breakpoint) { - this._breakpointAdded(breakpoint); + this._breakpointAdded(breakpoint); + if (!dontSaveBreakpoints) this._saveBreakpoints(); - } + } + this._setBreakpointInDebugger(breakpoint, callback.bind(this)); + }, + + _setBreakpointInDebugger: function(breakpoint, callback) + { + function didSetBreakpoint(breakpointId, locations) + { + if (!breakpointId) + return; + + this._bindDebuggerId(breakpoint, breakpointId); + breakpoint.location = locations[0]; + callback(); } function didRequestSourceMapping(mapping) { - var location = mapping.sourceLocationToScriptLocation(lineNumber, 0); - var script = WebInspector.debuggerModel.scriptForSourceID(location.scriptId); + var location = mapping.sourceLineToScriptLocation(breakpoint.lineNumber); + var script = WebInspector.debuggerModel.scriptForSourceID(location.sourceID); if (script.sourceURL) - WebInspector.debuggerModel.setBreakpoint(script.sourceURL, location.lineNumber, location.columnNumber, condition, enabled, didSetBreakpoint.bind(this)); - else - WebInspector.debuggerModel.setBreakpointBySourceId(script.sourceID, location.lineNumber, location.columnNumber, condition, enabled, didSetBreakpoint.bind(this)); + WebInspector.debuggerModel.setBreakpoint(script.sourceURL, location.lineNumber, location.columnNumber, breakpoint.condition, didSetBreakpoint.bind(this)); + else { + location.sourceID = script.sourceID; + WebInspector.debuggerModel.setBreakpointBySourceId(location, breakpoint.condition, didSetBreakpoint.bind(this)); + } } - this._sourceFiles[sourceFileId].requestSourceMapping(didRequestSourceMapping.bind(this)); + breakpoint.sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this)); + }, + + _removeBreakpointFromDebugger: function(breakpoint, callback) + { + if (!("debuggerId" in breakpoint)) { + if (callback) + callback(); + return; + } + + function didRemoveBreakpoint() + { + this._unbindDebuggerId(breakpoint); + if (callback) + callback(); + } + WebInspector.debuggerModel.removeBreakpoint(breakpoint.debuggerId, didRemoveBreakpoint.bind(this)); + }, + + _bindDebuggerId: function(breakpoint, debuggerId) + { + breakpoint.debuggerId = debuggerId; + this._breakpointsByDebuggerId[debuggerId] = breakpoint; + }, + + _unbindDebuggerId: function(breakpoint) + { + delete this._breakpointsByDebuggerId[breakpoint.debuggerId]; + delete breakpoint.debuggerId; }, setBreakpointEnabled: function(sourceFileId, lineNumber, enabled) { - var breakpoint = this.removeBreakpoint(sourceFileId, lineNumber); - this.setBreakpoint(sourceFileId, lineNumber, breakpoint.condition, enabled); + var breakpoint = this.findBreakpoint(sourceFileId, lineNumber); + if (!breakpoint) + return; + + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint); + + breakpoint.enabled = enabled; + + function afterUpdate() + { + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, breakpoint); + this._saveBreakpoints(); + } + + if (!enabled) + this._removeBreakpointFromDebugger(breakpoint, afterUpdate.call(this)); + else + this._setBreakpointInDebugger(breakpoint, afterUpdate.bind(this)); }, updateBreakpoint: function(sourceFileId, lineNumber, condition, enabled) @@ -290,10 +390,15 @@ WebInspector.DebuggerPresentationModel.prototype = { removeBreakpoint: function(sourceFileId, lineNumber) { var breakpoint = this.findBreakpoint(sourceFileId, lineNumber); - WebInspector.debuggerModel.removeBreakpoint(breakpoint._id); - this._breakpointRemoved(breakpoint._id); - this._saveBreakpoints(); - return breakpoint; + if (!breakpoint) + return; + + function callback() + { + this._breakpointRemoved(breakpoint); + this._saveBreakpoints(); + } + this._removeBreakpointFromDebugger(breakpoint, callback.bind(this)); }, findBreakpoint: function(sourceFileId, lineNumber) @@ -305,84 +410,96 @@ WebInspector.DebuggerPresentationModel.prototype = { _breakpointAdded: function(breakpoint) { - var script; - if (breakpoint.url) - script = WebInspector.debuggerModel.scriptsForURL(breakpoint.url)[0]; - else - script = WebInspector.debuggerModel.scriptForSourceID(breakpoint.sourceID); - if (!script) + var sourceFile = breakpoint.sourceFile; + if (!sourceFile) return; function didRequestSourceMapping(mapping) { - var scriptLocation = breakpoint.locations.length ? breakpoint.locations[0] : breakpoint; - var sourceLocation = mapping.scriptLocationToSourceLocation(scriptLocation.lineNumber, scriptLocation.columnNumber); - var lineNumber = sourceLocation.lineNumber; + // Refine line number based on resolved location. + if (breakpoint.location) + breakpoint.lineNumber = mapping.scriptLocationToSourceLine(breakpoint.location); - if (this.findBreakpoint(sourceFile.id, lineNumber)) { + var existingBreakpoint = this.findBreakpoint(sourceFile.id, breakpoint.lineNumber); + if (existingBreakpoint) { // We can't show more than one breakpoint on a single source file line. - WebInspector.debuggerModel.removeBreakpoint(breakpoint.id); + this._removeBreakpointFromDebugger(breakpoint); return; } - - var presentationBreakpoint = new WebInspector.PresentationBreakpoint(breakpoint, sourceFile, lineNumber); - presentationBreakpoint._id = breakpoint.id; - this._presentationBreakpoints[breakpoint.id] = presentationBreakpoint; - sourceFile.breakpoints[lineNumber] = presentationBreakpoint; - this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, presentationBreakpoint); + sourceFile.breakpoints[breakpoint.lineNumber] = breakpoint; + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, breakpoint); } - var sourceFile = this._sourceFileForScript(script); sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this)); }, - _breakpointRemoved: function(breakpointId) + _breakpointRemoved: function(breakpoint) { - var breakpoint = this._presentationBreakpoints[breakpointId]; - delete this._presentationBreakpoints[breakpointId]; - var sourceFile = this.sourceFile(breakpoint.sourceFileId); - delete sourceFile.breakpoints[breakpoint.lineNumber]; - this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint); + var sourceFile = breakpoint.sourceFile; + if (sourceFile.breakpoints[breakpoint.lineNumber] === breakpoint) { + // There can already be a newer breakpoint; + delete sourceFile.breakpoints[breakpoint.lineNumber]; + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint); + } }, _breakpointResolved: function(event) { - var breakpoint = event.data; - if (!(breakpoint.id in this._presentationBreakpoints)) + var debuggerId = event.data.breakpointId; + if (!(debuggerId in this._breakpointsByDebuggerId)) return; - this._breakpointRemoved(breakpoint.id); + var breakpoint = this._breakpointsByDebuggerId[debuggerId]; + + this._breakpointRemoved(breakpoint); + breakpoint.location = event.data.location; this._breakpointAdded(breakpoint); }, - _restoreBreakpoints: function() + _restoreBreakpointsFromSettings: function() { - function didSetBreakpoint(breakpoint) - { - if (breakpoint) - this._breakpointAdded(breakpoint); - } var breakpoints = WebInspector.settings.breakpoints; for (var i = 0; i < breakpoints.length; ++i) { - var breakpoint = breakpoints[i]; - WebInspector.debuggerModel.setBreakpoint(breakpoint.url, breakpoint.lineNumber, breakpoint.columnNumber, breakpoint.condition, breakpoint.enabled, didSetBreakpoint.bind(this)); + var breakpointData = breakpoints[i]; + var sourceFileId = breakpointData.sourceFileId; + if (!sourceFileId) + continue; + var sourceFile = this._sourceFiles[sourceFileId]; + if (sourceFile) { + this.setBreakpoint(sourceFileId, breakpointData.lineNumber, breakpointData.condition, breakpointData.enabled); + continue; + } + + // Add breakpoint once source file becomes available. + var pendingBreakpoints = this._breakpointsWithoutSourceFile[sourceFileId]; + if (!pendingBreakpoints) { + pendingBreakpoints = []; + this._breakpointsWithoutSourceFile[sourceFileId] = pendingBreakpoints; + } + pendingBreakpoints.push(breakpointData); } }, _saveBreakpoints: function() { var serializedBreakpoints = []; - var breakpoints = WebInspector.debuggerModel.breakpoints; - for (var id in breakpoints) { - var breakpoint = breakpoints[id]; - if (!breakpoint.url) + + // Store added breakpoints. + for (var sourceFileId in this._sourceFiles) { + var sourceFile = this._sourceFiles[sourceFileId]; + if (!sourceFile.url) continue; - var serializedBreakpoint = {}; - serializedBreakpoint.url = breakpoint.url; - serializedBreakpoint.lineNumber = breakpoint.lineNumber; - serializedBreakpoint.columnNumber = breakpoint.columnNumber; - serializedBreakpoint.condition = breakpoint.condition; - serializedBreakpoint.enabled = breakpoint.enabled; - serializedBreakpoints.push(serializedBreakpoint); + + for (var lineNumber in sourceFile.breakpoints) + serializedBreakpoints.push(sourceFile.breakpoints[lineNumber].serialize()); } + + // Store not added breakpoints. + for (var sourceFileId in this._breakpointsWithoutSourceFile) + serializedBreakpoints = serializedBreakpoints.concat(this._breakpointsWithoutSourceFile[sourceFileId]); + + // Sanitize debugger ids. + for (var i = 0; i < serializedBreakpoints.length; ++i) + delete serializedBreakpoints[i].debuggerId; + WebInspector.settings.breakpoints = serializedBreakpoints; }, @@ -393,9 +510,9 @@ WebInspector.DebuggerPresentationModel.prototype = { for (var i = 0; i < callFrames.length; ++i) { var callFrame = callFrames[i]; var sourceFile; - var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.sourceID); + var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.sourceID); if (script) - sourceFile = this._sourceFileForScript(script); + sourceFile = this._sourceFileForScript(script.sourceURL, script.sourceID); this._presentationCallFrames.push(new WebInspector.PresenationCallFrame(callFrame, i, sourceFile)); } var details = WebInspector.debuggerModel.debuggerPausedDetails; @@ -423,30 +540,48 @@ WebInspector.DebuggerPresentationModel.prototype = { return this._presentationCallFrames[this._selectedCallFrameIndex]; }, - _sourceFileForScript: function(script) + _sourceFileForScript: function(sourceURL, sourceID) { - return this._sourceFiles[script.sourceURL || script.sourceID]; - }, - - _sourceFileForScriptURL: function(scriptURL) - { - return this._sourceFiles[scriptURL]; + return this._sourceFiles[this._createSourceFileId(sourceURL, sourceID)]; }, _scriptForSourceFileId: function(sourceFileId) { function filter(script) { - return (script.sourceURL || script.sourceID) === sourceFileId; + return this._createSourceFileId(script.sourceURL, script.sourceID) === sourceFileId; } - return WebInspector.debuggerModel.queryScripts(filter)[0]; + return WebInspector.debuggerModel.queryScripts(filter.bind(this))[0]; + }, + + _createSourceFileId: function(sourceURL, sourceID) + { + var prefix = this._formatSourceFiles ? "deobfuscated:" : ""; + return prefix + (sourceURL || sourceID); }, _reset: function() { + for (var id in this._sourceFiles) { + var sourceFile = this._sourceFiles[id]; + for (var line in sourceFile.breakpoints) { + var breakpoints = this._breakpointsWithoutSourceFile[sourceFile.id]; + if (!breakpoints) { + breakpoints = []; + this._breakpointsWithoutSourceFile[sourceFile.id] = breakpoints; + } + breakpoints.push(sourceFile.breakpoints[line].serialize()); + } + } + this._sourceFiles = {}; this._messages = []; - this._presentationBreakpoints = {}; + this._breakpointsByDebuggerId = {}; + }, + + _debuggerReset: function() + { + this._reset(); this._presentationCallFrames = []; this._selectedCallFrameIndex = 0; } @@ -454,42 +589,24 @@ WebInspector.DebuggerPresentationModel.prototype = { WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype; -WebInspector.PresentationBreakpoint = function(breakpoint, sourceFile, lineNumber) +WebInspector.PresentationBreakpoint = function(sourceFile, lineNumber, condition, enabled) { - this._breakpoint = breakpoint; - this._sourceFile = sourceFile; - this._lineNumber = lineNumber; + this.sourceFile = sourceFile; + this.sourceFileId = sourceFile.id; + this.lineNumber = lineNumber; + this.condition = condition; + this.enabled = enabled; } WebInspector.PresentationBreakpoint.prototype = { - get sourceFileId() - { - return this._sourceFile.id; - }, - - get lineNumber() - { - return this._lineNumber; - }, - - get condition() - { - return this._breakpoint.condition; - }, - - get enabled() - { - return this._breakpoint.enabled; - }, - get url() { - return this._sourceFile.url; + return this.sourceFile.url; }, get resolved() { - return !!this._breakpoint.locations.length + return !!this.location; }, loadSnippet: function(callback) @@ -502,7 +619,22 @@ WebInspector.PresentationBreakpoint.prototype = { snippet = content.substring(lineEndings[this.lineNumber - 1], lineEndings[this.lineNumber]); callback(snippet); } - this._sourceFile.requestContent(didRequestContent.bind(this)); + if (!this.sourceFile) { + callback(WebInspector.UIString("N/A")); + return; + } + this.sourceFile.requestContent(didRequestContent.bind(this)); + }, + + serialize: function() + { + var serializedBreakpoint = {}; + serializedBreakpoint.sourceFileId = this.sourceFile.id; + serializedBreakpoint.lineNumber = this.lineNumber; + serializedBreakpoint.condition = this.condition; + serializedBreakpoint.enabled = this.enabled; + serializedBreakpoint.debuggerId = this.debuggerId; + return serializedBreakpoint; } } @@ -511,7 +643,7 @@ WebInspector.PresenationCallFrame = function(callFrame, index, sourceFile) this._callFrame = callFrame; this._index = index; this._sourceFile = sourceFile; - this._script = WebInspector.debuggerModel.scriptForSourceID(callFrame.sourceID); + this._script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.sourceID); } WebInspector.PresenationCallFrame.prototype = { @@ -561,18 +693,63 @@ WebInspector.PresenationCallFrame.prototype = { DebuggerAgent.evaluateOnCallFrame(this._callFrame.id, code, objectGroup, includeCommandLineAPI, didEvaluateOnCallFrame.bind(this)); }, - sourceLocation: function(callback) + sourceLine: function(callback) { if (!this._sourceFile) { - callback(undefined, this._callFrame.line, this._callFrame.column); + callback(undefined, this._callFrame.location.lineNumber); return; } function didRequestSourceMapping(mapping) { - var sourceLocation = mapping.scriptLocationToSourceLocation(this._callFrame.line, this._callFrame.column); - callback(this._sourceFile.id, sourceLocation.lineNumber, sourceLocation.columnNumber); + callback(this._sourceFile.id, mapping.scriptLocationToSourceLine(this._callFrame.location)); } this._sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this)); } } + +WebInspector.DebuggerPresentationModelResourceBinding = function(model) +{ + this._presentationModel = model; + WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Script, this); +} + +WebInspector.DebuggerPresentationModelResourceBinding.prototype = { + canSetContent: function(resource) + { + var sourceFile = this._presentationModel._sourceFileForScript(resource.url) + if (!sourceFile) + return false; + return this._presentationModel.canEditScriptSource(sourceFile.id); + }, + + setContent: function(resource, content, majorChange, userCallback) + { + if (!majorChange) + return; + + var sourceFile = this._presentationModel._sourceFileForScript(resource.url); + if (!sourceFile) { + userCallback("Resource is not editable"); + return; + } + + resource.requestContent(this._setContentWithInitialContent.bind(this, sourceFile, content, userCallback)); + }, + + _setContentWithInitialContent: function(sourceFile, content, userCallback, oldContent) + { + function callback(error) + { + if (userCallback) + userCallback(error); + if (!error) { + this._presentationModel._updateBreakpointsAfterLiveEdit(sourceFile.id, oldContent, content); + sourceFile.reload(); + } + } + this._presentationModel.editScriptSource(sourceFile.id, content, callback.bind(this)); + } +} + +WebInspector.DebuggerPresentationModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype; diff --git a/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js b/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js index 4fc1844..e706e1d 100644 --- a/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js +++ b/Source/WebCore/inspector/front-end/DetailedHeapshotGridNodes.js @@ -28,10 +28,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.HeapSnapshotGridNode = function(tree, hasChildren, populateCount) +WebInspector.HeapSnapshotGridNode = function(tree, hasChildren) { WebInspector.DataGridNode.call(this, null, hasChildren); - this._defaultPopulateCount = populateCount; + this._defaultPopulateCount = tree._defaultPopulateCount; this._provider = null; this.addEventListener("populate", this._populate, this); } @@ -51,20 +51,24 @@ WebInspector.HeapSnapshotGridNode.prototype = { function doPopulate() { - this._provider.sort(this.comparator()); - this._provider.first(); - this.populateChildren(); this.removeEventListener("populate", this._populate, this); + function sorted(ignored) + { + this.populateChildren(); + } + this._provider.sortAndRewind(this.comparator(), sorted.bind(this)); } }, - populateChildren: function(provider, howMany, atIndex) + populateChildren: function(provider, howMany, atIndex, afterPopulate, suppressNotifyAboutCompletion) { if (!howMany && provider) { howMany = provider.instanceCount; provider.instanceCount = 0; } provider = provider || this._provider; + if (!("instanceCount" in provider)) + provider.instanceCount = 0; howMany = howMany || this._defaultPopulateCount; atIndex = atIndex || this.children.length; var haveSavedChildren = !!this._savedChildren; @@ -75,19 +79,35 @@ WebInspector.HeapSnapshotGridNode.prototype = { break; } } - for ( ; howMany > 0 && provider.hasNext(); provider.next(), ++provider.instanceCount, --howMany) { - var item = provider.item; - if (haveSavedChildren) { - var hash = this._childHashForEntity(item); - if (hash in this._savedChildren) { - this.insertChild(this._savedChildren[hash], atIndex++); - continue; + + function childrenRetrieved(items, hasNext, length) + { + for (var i = 0, l = items.length; i < l; ++i) { + var item = items[i]; + if (haveSavedChildren) { + var hash = this._childHashForEntity(item); + if (hash in this._savedChildren) { + this.insertChild(this._savedChildren[hash], atIndex++); + continue; + } + } + this.insertChild(this._createChildNode(item, provider), atIndex++); + } + provider.instanceCount += items.length; + + if (hasNext) + this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, length), atIndex++); + if (afterPopulate) + afterPopulate(); + if (!suppressNotifyAboutCompletion) { + function notify() + { + this.dispatchEventToListeners("populate complete"); } + setTimeout(notify.bind(this), 0); } - this.insertChild(this._createChildNode(provider), atIndex++); } - if (provider.hasNext()) - this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, provider.length), atIndex++); + provider.getNextItems(howMany, childrenRetrieved.bind(this)); }, _saveChildren: function() @@ -102,31 +122,38 @@ WebInspector.HeapSnapshotGridNode.prototype = { 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(); + function afterSort(sorted) + { + if (!sorted) + return; + this._saveChildren(); + this.removeChildren(); + + function afterPopulate() + { + for (var i = 0, l = this.children.length; i < l; ++i) { + var child = this.children[i]; + if (child.expanded) + child.sort(); + } + this.dataGrid.dispatchEventToListeners("sorting complete"); + } + this.populateChildren(this._provider, null, null, afterPopulate.bind(this)); } + this._provider.sortAndRewind(this.comparator(), afterSort.bind(this)); } + this.dataGrid.dispatchEventToListeners("start sorting"); + WebInspector.PleaseWaitMessage.prototype.startAction(this.dataGrid.element, doSort.bind(this)); } }; WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; -WebInspector.HeapSnapshotGenericObjectNode = function(tree, node, hasChildren, populateCount) +WebInspector.HeapSnapshotGenericObjectNode = function(tree, node) { - WebInspector.HeapSnapshotGridNode.call(this, tree, hasChildren, populateCount); + WebInspector.HeapSnapshotGridNode.call(this, tree, false); this._name = node.name; this._type = node.type; this._shallowSize = node.selfSize; @@ -167,7 +194,7 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = { get _countPercent() { - return this._count / this.tree.snapshot.nodeCount * 100.0; + return this._count / this.dataGrid.snapshot.nodeCount * 100.0; }, get data() @@ -216,6 +243,15 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype = { get _shallowSizePercent() { return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0; + }, + + _updateHasChildren: function() + { + function isEmptyCallback(isEmpty) + { + this.hasChildren = !isEmpty; + } + this._provider.isEmpty(isEmptyCallback.bind(this)); } } @@ -223,24 +259,23 @@ WebInspector.HeapSnapshotGenericObjectNode.prototype.__proto__ = WebInspector.He WebInspector.HeapSnapshotObjectNode = function(tree, edge) { - var provider = this._createProvider(tree.snapshot, edge.nodeIndex); - WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node, !provider.isEmpty, 100); + WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node); this._referenceName = edge.name; this._referenceType = edge.type; - this._provider = provider; + this._provider = this._createProvider(tree.snapshot, edge.nodeIndex); + this._updateHasChildren(); } WebInspector.HeapSnapshotObjectNode.prototype = { - _createChildNode: function(provider) + _createChildNode: function(item) { - return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item); + return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, item); }, _createProvider: function(snapshot, nodeIndex) { var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData; - return new WebInspector.HeapSnapshotEdgesProvider( - snapshot, + return snapshot.createEdgesProvider( nodeIndex, function(edge) { return !edge.isInvisible @@ -312,23 +347,22 @@ WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnaps WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node) { - var provider = this._createProvider(baseSnapshot || snapshot, node.nodeIndex); - WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node, !provider.isEmpty, 100); + WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node); this._isDeletedNode = !!baseSnapshot; - this._provider = provider; + this._provider = this._createProvider(baseSnapshot || snapshot, node.nodeIndex); + this._updateHasChildren(); }; WebInspector.HeapSnapshotInstanceNode.prototype = { - _createChildNode: function(provider) + _createChildNode: function(item) { - return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, provider.item); + return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, item); }, _createProvider: function(snapshot, nodeIndex) { var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData; - return new WebInspector.HeapSnapshotEdgesProvider( - snapshot, + return snapshot.createEdgesProvider( nodeIndex, function(edge) { return !edge.isInvisible @@ -387,7 +421,7 @@ WebInspector.HeapSnapshotInstanceNode.prototype.__proto__ = WebInspector.HeapSna WebInspector.HeapSnapshotConstructorNode = function(tree, className, aggregate) { - WebInspector.HeapSnapshotGridNode.call(this, tree, aggregate.count > 0, 100); + WebInspector.HeapSnapshotGridNode.call(this, tree, aggregate.count > 0); this._name = className; this._count = aggregate.count; this._shallowSize = aggregate.self; @@ -396,15 +430,14 @@ WebInspector.HeapSnapshotConstructorNode = function(tree, className, aggregate) } WebInspector.HeapSnapshotConstructorNode.prototype = { - _createChildNode: function(provider) + _createChildNode: function(item) { - return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, provider.item); + return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, item); }, _createNodesProvider: function(snapshot, nodeType, nodeClassName) { - return new WebInspector.HeapSnapshotNodesProvider( - snapshot, + return snapshot.createNodesProvider( function (node) { return node.type === nodeType && (nodeClassName === null || node.className === nodeClassName); @@ -469,97 +502,94 @@ WebInspector.HeapSnapshotIteratorsTuple = function(it1, it2) } WebInspector.HeapSnapshotIteratorsTuple.prototype = { - first: function() + sortAndRewind: function(comparator, callback) { - this._it1.first(); - this._it2.first(); - }, - - sort: function(comparator) - { - this._it1.sort(comparator); - this._it2.sort(comparator); + function afterSort(ignored) + { + this._it2.sortAndRewind(comparator, callback); + } + this._it1.sortAndRewind(comparator, afterSort.bind(this)); } }; WebInspector.HeapSnapshotDiffNode = function(tree, className, 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); + WebInspector.HeapSnapshotGridNode.call(this, tree, true); this._name = className; - this._calculateDiff(tree.baseSnapshot, tree.snapshot, baseAggregate.idxs, aggregate.idxs); - this._provider = this._createNodesProvider(tree.baseSnapshot, tree.snapshot, aggregate.type, className); + this._baseIndexes = baseAggregate ? baseAggregate.idxs : []; + this._indexes = aggregate ? aggregate.idxs : []; + this._provider = this._createNodesProvider(tree.baseSnapshot, tree.snapshot, aggregate ? aggregate.type : baseAggregate.type, className); } 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]; - } + calculateDiff: function(dataGrid, callback) + { + var diff = dataGrid.snapshot.createDiff(this._name); + + function diffCalculated(diffResult) + { + this._diff = diffResult; + this._baseIndexes = null; + this._indexes = null; + callback(this._diff.addedSize === 0 && this._diff.removedSize === 0); + } + function baseSelfSizesReceived(baseSelfSizes) + { + diff.pushBaseSelfSizes(baseSelfSizes); + diff.calculate(diffCalculated.bind(this)); } - while (i < l) { - this._removedCount++; - this._removedSize += nodeA.selfSize; - nodeA.nodeIndex = baseIndexes[++i]; + function baseIdsReceived(baseIds) + { + diff.pushBaseIds(dataGrid.baseSnapshot.uid, baseIds); + dataGrid.snapshot.pushBaseIds(dataGrid.baseSnapshot.uid, this._name, baseIds); + dataGrid.baseSnapshot.nodeFieldValuesByIndex("selfSize", this._baseIndexes, baseSelfSizesReceived.bind(this)); } - while (j < m) { - this._addedCount++; - this._addedSize += nodeB.selfSize; - nodeB.nodeIndex = currentIndexes[++j]; + function idsReceived(ids) + { + dataGrid.baseSnapshot.pushBaseIds(dataGrid.snapshot.uid, this._name, ids); } - this._countDelta = this._addedCount - this._removedCount; - this._sizeDelta = this._addedSize - this._removedSize; + dataGrid.baseSnapshot.nodeFieldValuesByIndex("id", this._baseIndexes, baseIdsReceived.bind(this)); + dataGrid.snapshot.nodeFieldValuesByIndex("id", this._indexes, idsReceived.bind(this)); }, - _createChildNode: function(provider) + _createChildNode: function(item, provider) { if (provider === this._provider._it1) - return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, provider.item); + return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, item); else - return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, provider.item); + return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, item); }, _createNodesProvider: function(baseSnapshot, snapshot, nodeType, nodeClassName) { + var className = this._name; return new WebInspector.HeapSnapshotIteratorsTuple( createProvider(snapshot, baseSnapshot), createProvider(baseSnapshot, snapshot)); function createProvider(snapshot, otherSnapshot) { - return new WebInspector.HeapSnapshotNodesProvider( - snapshot, + var otherSnapshotId = otherSnapshot.uid; + var provider = snapshot.createNodesProvider( function (node) { return node.type === nodeType && (nodeClassName === null || node.className === nodeClassName) - && !otherSnapshot.hasId(node.id); + && !this.baseSnapshotHasNode(otherSnapshotId, className, node.id); }); + provider.snapshot = snapshot; + return provider; } }, + _childHashForEntity: function(node) + { + return node.id; + }, + + _childHashForNode: function(childNode) + { + return childNode.snapshotNodeId; + }, + comparator: function() { var sortAscending = this.dataGrid.sortOrder === "ascending"; @@ -576,16 +606,22 @@ WebInspector.HeapSnapshotDiffNode.prototype = { return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields); }, - populateChildren: function(provider, howMany, atIndex) + populateChildren: function(provider, howMany, atIndex, afterPopulate) { 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); + var firstProviderPopulated = function() + { + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount, atIndex, afterPopulate); + }; + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount, atIndex, firstProviderPopulated.bind(this), true); } else if (!howMany) { - WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1); - WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2); + var firstProviderPopulated = function() + { + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, null, atIndex, afterPopulate); + }; + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, null, atIndex, firstProviderPopulated.bind(this), true); } else - WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex); + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex, afterPopulate); }, _signForDelta: function(delta) @@ -602,19 +638,16 @@ WebInspector.HeapSnapshotDiffNode.prototype = { { 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))); + data["addedCount"] = this._diff.addedCount; + data["removedCount"] = this._diff.removedCount; + var countDelta = this._diff.countDelta; + data["countDelta"] = WebInspector.UIString("%s%d", this._signForDelta(countDelta), Math.abs(countDelta)); + data["addedSize"] = Number.bytesToString(this._diff.addedSize); + data["removedSize"] = Number.bytesToString(this._diff.removedSize); + var sizeDelta = this._diff.sizeDelta; + data["sizeDelta"] = WebInspector.UIString("%s%s", this._signForDelta(sizeDelta), Number.bytesToString(Math.abs(sizeDelta))); return data; - }, - - get zeroDiff() - { - return this._addedCount === 0 && this._removedCount === 0; } }; @@ -622,22 +655,21 @@ WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapsho 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.HeapSnapshotGenericObjectNode.call(this, tree, node); + this._provider = this._createProvider(tree.snapshot, node.nodeIndex); + this._updateHasChildren(); }; WebInspector.HeapSnapshotDominatorObjectNode.prototype = { - _createChildNode: function(provider) + _createChildNode: function(item) { - return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, provider.item); + return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, item); }, _createProvider: function(snapshot, nodeIndex) { var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData; - return new WebInspector.HeapSnapshotNodesProvider( - snapshot, + return snapshot.createNodesProvider( function (node) { var dominatorIndex = node.dominatorIndex; return dominatorIndex === nodeIndex diff --git a/Source/WebCore/inspector/front-end/DetailedHeapshotView.js b/Source/WebCore/inspector/front-end/DetailedHeapshotView.js index 21d0fa9..1e46b51 100644 --- a/Source/WebCore/inspector/front-end/DetailedHeapshotView.js +++ b/Source/WebCore/inspector/front-end/DetailedHeapshotView.js @@ -37,10 +37,11 @@ WebInspector.HeapSnapshotContainmentDataGrid = function() }; WebInspector.DataGrid.call(this, columns); this.addEventListener("sorting changed", this.sort, this); - this._defaultPopulateCount = 100; } WebInspector.HeapSnapshotContainmentDataGrid.prototype = { + _defaultPopulateCount: 100, + setDataSource: function(snapshotView, snapshot) { this.snapshotView = snapshotView; @@ -65,6 +66,10 @@ WebInspector.HeapSnapshotSortableDataGrid.prototype = { { var sortAscending = this.sortOrder === "ascending"; var sortColumnIdentifier = this.sortColumnIdentifier; + if (this._lastSortColumnIdentifier === sortColumnIdentifier && this._lastSortAscending === sortAscending) + return; + this._lastSortColumnIdentifier = sortColumnIdentifier; + this._lastSortAscending = sortAscending; var sortFields = this._sortFields(sortColumnIdentifier, sortAscending); function SortByTwoFields(nodeA, nodeB) @@ -89,6 +94,7 @@ WebInspector.HeapSnapshotSortableDataGrid.prototype = { _performSorting: function(sortFunction) { + this.dispatchEventToListeners("start sorting"); var children = this.children; this.removeChildren(); children.sort(sortFunction); @@ -98,6 +104,7 @@ WebInspector.HeapSnapshotSortableDataGrid.prototype = { if (child.expanded) child.sort(); } + this.dispatchEventToListeners("sorting complete"); } }; @@ -115,6 +122,8 @@ WebInspector.HeapSnapshotConstructorsDataGrid = function() } WebInspector.HeapSnapshotConstructorsDataGrid.prototype = { + _defaultPopulateCount: 100, + _sortFields: function(sortColumn, sortAscending) { return { @@ -130,14 +139,17 @@ WebInspector.HeapSnapshotConstructorsDataGrid.prototype = { 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])); + function aggregatesReceived(aggregates) + { + for (var constructor in aggregates) + this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor])); + this.sortingChanged(); + } + this.snapshot.aggregates(false, aggregatesReceived.bind(this)); } }; @@ -147,7 +159,6 @@ 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. @@ -160,6 +171,8 @@ WebInspector.HeapSnapshotDiffDataGrid = function() } WebInspector.HeapSnapshotDiffDataGrid.prototype = { + _defaultPopulateCount: 50, + _sortFields: function(sortColumn, sortAscending) { return { @@ -183,28 +196,41 @@ WebInspector.HeapSnapshotDiffDataGrid.prototype = { { this.baseSnapshot = baseSnapshot; this.removeChildren(); - if (this.baseSnapshot !== this.snapshot) { - this.populateChildren(); - this.sortingChanged(); - } + if (this.baseSnapshot === this.snapshot) + return; + this.populateChildren(); }, 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); + function baseAggregatesReceived(baseClasses) + { + function aggregatesReceived(classes) + { + var nodeCount = 0; + function addNodeIfNonZeroDiff(node, zeroDiff) + { + if (!zeroDiff) + this.appendChild(node); + if (!--nodeCount) + this.sortingChanged(); + } + for (var clss in baseClasses) { + var node = new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss]); + ++nodeCount; + node.calculateDiff(this, addNodeIfNonZeroDiff.bind(this, node)); + } + for (clss in classes) { + if (!(clss in baseClasses)) { + var node = new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss]); + ++nodeCount; + node.calculateDiff(this, addNodeIfNonZeroDiff.bind(this, node)); + } + } } + this.snapshot.aggregates(true, aggregatesReceived.bind(this)); } + this.baseSnapshot.aggregates(true, baseAggregatesReceived.bind(this)); } }; @@ -219,10 +245,11 @@ WebInspector.HeapSnapshotDominatorsDataGrid = function() }; WebInspector.DataGrid.call(this, columns); this.addEventListener("sorting changed", this.sort, this); - this._defaultPopulateCount = 25; } WebInspector.HeapSnapshotDominatorsDataGrid.prototype = { + _defaultPopulateCount: 25, + setDataSource: function(snapshotView, snapshot) { this.snapshotView = snapshotView; @@ -243,6 +270,7 @@ WebInspector.HeapSnapshotRetainingPathsList = function() len: { title: WebInspector.UIString("Length"), width: "90px", sortable: true, sort: "ascending" } }; WebInspector.HeapSnapshotSortableDataGrid.call(this, columns); + this._defaultPopulateCount = 100; } WebInspector.HeapSnapshotRetainingPathsList.prototype = { @@ -254,6 +282,14 @@ WebInspector.HeapSnapshotRetainingPathsList.prototype = { }[sortColumn]; }, + _resetPaths: function() + { + this._setRootChildrenForFinder(); + this.removeChildren(); + this._counter = 0; + this.showNext(this._defaultPopulateCount); + }, + setDataSource: function(snapshotView, snapshot, nodeIndex, prefix) { this.snapshotView = snapshotView; @@ -261,53 +297,49 @@ WebInspector.HeapSnapshotRetainingPathsList.prototype = { if (this.pathFinder) this.searchCancelled(); - - this.pathFinder = new WebInspector.HeapSnapshotPathFinder(snapshot, nodeIndex); - this._setRootChildrenForFinder(); - - this.removeChildren(); - - this._counter = 0; - this.showNext(100); + this.pathFinder = snapshot.createPathFinder(nodeIndex); + this._resetPaths(); }, refresh: function() { - this.removeChildren(); - this._counter = 0; delete this._cancel; - this._setRootChildrenForFinder(); - this.showNext(100); + this._resetPaths(); }, showNext: function(pathsCount) { WebInspector.PleaseWaitMessage.prototype.show(this.element, this.searchCancelled.bind(this, pathsCount)); - window.setTimeout(startSearching.bind(this), 500); + + function pathFound(result) + { + if (result === null) { + WebInspector.PleaseWaitMessage.prototype.hide(); + if (!this.children.length) + this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Can't find any paths."), 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; + } + setTimeout(startSearching.bind(this), 0); + } 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("Can't find any paths."), 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); + if (this._cancel === this.pathFinder) + return; + delete this._cancel; + if (this._counter < pathsCount) + this.pathFinder.findNext(pathFound.bind(this)); + else { + this.searchCancelled.call(this, pathsCount); + delete this._cancel; } - this._cancel = false; } + setTimeout(startSearching.bind(this), 0); }, searchCancelled: function(pathsCount) @@ -419,20 +451,17 @@ WebInspector.DetailedHeapshotView = function(parent, profile) 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 = [{title: "Summary", view: this.constructorsView, grid: this.constructorsDataGrid}, + {title: "Comparison", view: this.diffView, grid: this.diffDataGrid}, + {title: "Containment", view: this.containmentView, grid: this.containmentDataGrid}, + {title: "Dominators", view: this.dominatorView, grid: this.dominatorDataGrid}]; this.views.current = 0; + for (var i = 0; i < this.views.length; ++i) { + var view = this.views[i]; + var option = document.createElement("option"); + option.label = WebInspector.UIString(view.title); + this.viewSelectElement.appendChild(option); + } this._profileUid = profile.uid; @@ -450,12 +479,12 @@ WebInspector.DetailedHeapshotView = function(parent, profile) this._loadProfile(this._profileUid, profileCallback.bind(this)); - function profileCallback(profile) + function profileCallback() { var list = this._profiles(); var profileIndex; for (var i = 0; i < list.length; ++i) - if (list[i].uid === profile.uid) { + if (list[i].uid === this._profileUid) { profileIndex = i; break; } @@ -490,7 +519,7 @@ WebInspector.DetailedHeapshotView.prototype = { get profileWrapper() { if (!this._profileWrapper) - this._profileWrapper = new WebInspector.HeapSnapshot(this.profile); + this._profileWrapper = this.profile.proxy; return this._profileWrapper; }, @@ -501,34 +530,27 @@ WebInspector.DetailedHeapshotView.prototype = { get baseProfileWrapper() { - if (!this._baseProfileWrapper) { - if (this.baseProfile !== this.profile) - this._baseProfileWrapper = new WebInspector.HeapSnapshot(this.baseProfile); - else - this._baseProfileWrapper = this.profileWrapper; - } + if (!this._baseProfileWrapper) + this._baseProfileWrapper = this.baseProfile.proxy; return this._baseProfileWrapper; }, show: function(parentElement) { WebInspector.View.prototype.show.call(this, parentElement); - if (!this.profile._loaded) + if (!this.profileWrapper.loaded) this._loadProfile(this._profileUid, profileCallback1.bind(this)); else - profileCallback1.call(this, this.profile); + profileCallback1.call(this); - function profileCallback1(profile) { - this.profileWrapper.restore(profile); - if (this.baseProfile && !this.baseProfile._loaded) + function profileCallback1() { + if (this.baseProfile && !this.baseProfileWrapper.loaded) this._loadProfile(this._baseProfileUid, profileCallback2.bind(this)); else - profileCallback2.call(this, this.baseProfile); + profileCallback2.call(this); } - function profileCallback2(profile) { - if (profile) - this.baseProfileWrapper.restore(profile); + function profileCallback2() { this.currentView.show(); this.dataGrid.updateWidths(); } @@ -697,7 +719,7 @@ WebInspector.DetailedHeapshotView.prototype = { this._baseProfileUid = this._profiles()[this.baseSelectElement.selectedIndex].uid; this._loadProfile(this._baseProfileUid, baseProfileLoaded.bind(this)); - function baseProfileLoaded(profile) + function baseProfileLoaded() { delete this._baseProfileWrapper; this.baseProfile._lastShown = Date.now(); @@ -770,19 +792,9 @@ WebInspector.DetailedHeapshotView.prototype = { 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; - } + var view = this.views[this.views.current]; + this.currentView = view.view; + this.dataGrid = view.grid; this.currentView.show(); this.refreshVisibleData(); if (this.currentView === this.diffView) { diff --git a/Source/WebCore/inspector/front-end/ElementsPanel.js b/Source/WebCore/inspector/front-end/ElementsPanel.js index 724e0e2..1f6f56b 100644 --- a/Source/WebCore/inspector/front-end/ElementsPanel.js +++ b/Source/WebCore/inspector/front-end/ElementsPanel.js @@ -38,7 +38,7 @@ WebInspector.ElementsPanel = function() if (!WebInspector.settings.domWordWrap) this.contentElement.classList.add("nowrap"); - this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); + this.contentElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); this.treeOutline = new WebInspector.ElementsTreeOutline(); this.treeOutline.panel = this; @@ -79,7 +79,7 @@ WebInspector.ElementsPanel = function() this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane(); this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane(); if (Preferences.nativeInstrumentationEnabled) - this.sidebarPanes.domBreakpoints = WebInspector.createDOMBreakpointsSidebarPane(); + this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane; this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane(); this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this); @@ -153,6 +153,9 @@ WebInspector.ElementsPanel.prototype = { if (this.recentlyModifiedNodes.length) this.updateModifiedNodes(); + if (Preferences.nativeInstrumentationEnabled) + this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.eventListeners.element); + if (!this.rootDOMNode) WebInspector.domAgent.requestDocument(); }, @@ -199,8 +202,8 @@ WebInspector.ElementsPanel.prototype = { if (!inspectedRootDocument) return; - WebInspector.breakpointManager.restoreDOMBreakpoints(); - + if (Preferences.nativeInstrumentationEnabled) + this.sidebarPanes.domBreakpoints.restoreBreakpoints(); this.rootDOMNode = inspectedRootDocument; @@ -483,7 +486,7 @@ WebInspector.ElementsPanel.prototype = { nodeItem.updateTitle(); continue; } - + if (!parent) continue; @@ -768,13 +771,13 @@ WebInspector.ElementsPanel.prototype = { var i = 0; var crumb = crumbs.firstChild; while (crumb) { - // Find the selected crumb and index. + // Find the selected crumb and index. if (!selectedCrumb && crumb.hasStyleClass("selected")) { selectedCrumb = crumb; selectedIndex = i; } - // Find the focused crumb index. + // Find the focused crumb index. if (crumb === focusedCrumb) focusedIndex = i; @@ -883,7 +886,7 @@ WebInspector.ElementsPanel.prototype = { while (crumb) { var hidden = crumb.hasStyleClass("hidden"); if (!hidden) { - var collapsed = crumb.hasStyleClass("collapsed"); + var collapsed = crumb.hasStyleClass("collapsed"); if (collapsedRun && collapsed) { crumb.addStyleClass("hidden"); crumb.removeStyleClass("compact"); @@ -1120,15 +1123,14 @@ WebInspector.ElementsPanel.prototype = { this._nodeSearchButton.toggled = false; }, - _setSearchingForNode: function(error, enabled) + _setSearchingForNode: function(enabled) { - if (!error) - this._nodeSearchButton.toggled = enabled; + this._nodeSearchButton.toggled = enabled; }, setSearchingForNode: function(enabled) { - DOMAgent.setSearchingForNode(enabled, this._setSearchingForNode.bind(this)); + DOMAgent.setSearchingForNode(enabled, this._setSearchingForNode.bind(this, enabled)); }, toggleSearchingForNode: function() diff --git a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js index dd99db1..2ecc3f9 100644 --- a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -791,23 +791,8 @@ WebInspector.ElementsTreeElement.prototype = { if (Preferences.nativeInstrumentationEnabled) { // Add debbuging-related actions contextMenu.appendSeparator(); - - function handlerFunction(nodeId, breakType) - { - WebInspector.breakpointManager.createDOMBreakpoint(nodeId, breakType); - WebInspector.panels.elements.sidebarPanes.domBreakpoints.expand(); - } - var node = this.representedObject; - for (var key in WebInspector.DOMBreakpointTypes) { - var type = WebInspector.DOMBreakpointTypes[key]; - var label = WebInspector.domBreakpointTypeContextMenuLabel(type); - var breakpoint = node.breakpoints[type]; - if (!breakpoint) - var handler = handlerFunction.bind(this, node.id, type); - else - var handler = breakpoint.remove.bind(breakpoint); - contextMenu.appendCheckboxItem(label, handler, !!breakpoint); - } + var pane = WebInspector.panels.elements.sidebarPanes.domBreakpoints; + pane.populateNodeContextMenu(this.representedObject, contextMenu); } }, diff --git a/Source/WebCore/inspector/front-end/EventListenersSidebarPane.js b/Source/WebCore/inspector/front-end/EventListenersSidebarPane.js index 00576f1..2dce7ee 100644 --- a/Source/WebCore/inspector/front-end/EventListenersSidebarPane.js +++ b/Source/WebCore/inspector/front-end/EventListenersSidebarPane.js @@ -214,7 +214,7 @@ WebInspector.EventListenerBar.prototype = { } if (node.id === this._nodeId) { - this.titleElement.textContent = appropriateSelectorForNode(node); + this.titleElement.textContent = node.appropriateSelectorFor(); return; } diff --git a/Source/WebCore/inspector/front-end/ExtensionAPI.js b/Source/WebCore/inspector/front-end/ExtensionAPI.js index ea7324c..940e340 100644 --- a/Source/WebCore/inspector/front-end/ExtensionAPI.js +++ b/Source/WebCore/inspector/front-end/ExtensionAPI.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * 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 @@ -111,6 +111,7 @@ function Resources() this._fire(resource); } this.onFinished = new EventSink("resource-finished", resourceDispatch); + this.onNavigated = new EventSink("inspectedURLChanged"); } Resources.prototype = { @@ -182,6 +183,8 @@ Panels.prototype = { function PanelImpl(id) { this._id = id; + this.onShown = new EventSink("panel-shown-" + id); + this.onHidden = new EventSink("panel-hidden-" + id); } function PanelWithSidebarImpl(id) @@ -190,35 +193,18 @@ function PanelWithSidebarImpl(id) } PanelWithSidebarImpl.prototype = { - createSidebarPane: function(title, url, callback) + createSidebarPane: function(title, callback) { var id = "extension-sidebar-" + extensionServer.nextObjectId(); var request = { command: "createSidebarPane", panel: this._id, id: id, - title: title, - url: expandURL(url) - }; - function callbackWrapper() - { - callback(new ExtensionSidebarPane(id)); - } - extensionServer.sendRequest(request, callback && callbackWrapper); - }, - - createWatchExpressionSidebarPane: function(title, callback) - { - var id = "watch-sidebar-" + extensionServer.nextObjectId(); - var request = { - command: "createWatchExpressionSidebarPane", - panel: this._id, - id: id, title: title }; function callbackWrapper() { - callback(new WatchExpressionSidebarPane(id)); + callback(new ExtensionSidebarPane(id)); } extensionServer.sendRequest(request, callback && callbackWrapper); } @@ -242,39 +228,29 @@ function ExtensionPanel(id) function ExtensionSidebarPaneImpl(id) { this._id = id; + this.onUpdated = new EventSink("sidebar-updated-" + id); } ExtensionSidebarPaneImpl.prototype = { setHeight: function(height) { extensionServer.sendRequest({ command: "setSidebarHeight", id: this._id, height: height }); - } -} - -function WatchExpressionSidebarPaneImpl(id) -{ - ExtensionSidebarPaneImpl.call(this, id); - this.onUpdated = new EventSink("watch-sidebar-updated-" + id); -} + }, -WatchExpressionSidebarPaneImpl.prototype = { setExpression: function(expression, rootTitle) { - extensionServer.sendRequest({ command: "setWatchSidebarContent", id: this._id, expression: expression, rootTitle: rootTitle, evaluateOnPage: true }); + extensionServer.sendRequest({ command: "setSidebarContent", id: this._id, expression: expression, rootTitle: rootTitle, evaluateOnPage: true }); }, setObject: function(jsonObject, rootTitle) { - extensionServer.sendRequest({ command: "setWatchSidebarContent", id: this._id, expression: jsonObject, rootTitle: rootTitle }); - } -} - -WatchExpressionSidebarPaneImpl.prototype.__proto__ = ExtensionSidebarPaneImpl.prototype; + extensionServer.sendRequest({ command: "setSidebarContent", id: this._id, expression: jsonObject, rootTitle: rootTitle }); + }, -function WatchExpressionSidebarPane(id) -{ - var impl = new WatchExpressionSidebarPaneImpl(id); - ExtensionSidebarPane.call(this, id, impl); + setPage: function(url) + { + extensionServer.sendRequest({ command: "setSidebarPage", id: this._id, url: expandURL(url) }); + } } function Audits() @@ -381,9 +357,6 @@ AuditResultNode.prototype = { function InspectedWindow() { - this.onDOMContentLoaded = new EventSink("inspectedPageDOMContentLoaded"); - this.onLoaded = new EventSink("inspectedPageLoaded"); - this.onNavigated = new EventSink("inspectedURLChanged"); } InspectedWindow.prototype = { @@ -511,7 +484,6 @@ var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl); var Panel = declareInterfaceClass(PanelImpl); var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl); var Resource = declareInterfaceClass(ResourceImpl); -var WatchExpressionSidebarPane = declareInterfaceClass(WatchExpressionSidebarPaneImpl); var extensionServer = new ExtensionServerClient(); diff --git a/Source/WebCore/inspector/front-end/ExtensionAPISchema.json b/Source/WebCore/inspector/front-end/ExtensionAPISchema.json index 0aa7aa8..c4c8358 100755 --- a/Source/WebCore/inspector/front-end/ExtensionAPISchema.json +++ b/Source/WebCore/inspector/front-end/ExtensionAPISchema.json @@ -19,11 +19,6 @@ "description": "A text that is displayed in sidebar caption." }, { - "name": "url", - "type": "string", - "description": "An URL of the page that represents the sidebar." - }, - { "name": "callback", "type": "function", "description": "A callback invoked when sidebar is created", @@ -36,30 +31,6 @@ ] } ] - }, - { - "name": "createWatchExpressionSidebarPane", - "type": "function", - "description": "Creates a pane with an object property tree (similar to a watch sidebar pane).", - "parameters": [ - { - "name": "title", - "type": "string", - "description": "A text that is displayed in sidebar caption." - }, - { - "name": "callback", - "type": "function", - "description": "A callback invoked when sidebar is created", - "parameters": [ - { - "name": "result", - "description": "A WatchExpressionSidebarPane object for created sidebar pane", - "$ref": "WatchExpressionSidebarPane" - } - ] - } - ] } ] }, @@ -116,25 +87,6 @@ "description": "A CSS-like size specification, e.g. '10px' or '12pt'" } ] - } - ] - }, - { - "id": "WatchExpressionSidebarPane", - "type": "object", - "description": "A sidebar created by the extension.", - "functions": [ - { - "name": "setHeight", - "type": "function", - "description": "Sets the height of the sidebar.", - "parameters": [ - { - "name": "height", - "type": "string", - "description": "A CSS-like size specification, e.g. '10px' or '12pt'" - } - ] }, { "name": "setExpression", @@ -171,6 +123,18 @@ "description": "An optional title for the root of the expression tree." } ] + }, + { + "name": "setPage", + "type": "function", + "description": "Sets an HTML page to be displayed in the sidebar pane.", + "parameters": [ + { + "name": "url", + "type": "string", + "description": "An URL of an extension page to display within the sidebar." + } + ] } ] } @@ -201,12 +165,20 @@ "name": "pageURL", "type": "string", "description": "An URL of the page that represents this panel." + }, + { + "name": "callback", + "type": "function", + "description": "A function that is called upon request completion.", + "parameters": [ + { + "name": "panel", + "description": "An ExtensionPanel object representing the created panel.", + "$ref": "ExtensionPanel" + } + ] } - ], - "returns" : { - "$ref": "ExtensionPanel", - "description": "A panel that was created." - } + ] } ] }, @@ -274,6 +246,18 @@ "parameters": [ { "name": "resource", "$ref": "Resource" } ] + }, + { + "name": "onNavigation", + "type": "function", + "description": "Fired when an inspected window navigates to a new URL.", + "parameters": [ + { + "name": "url", + "type": "stirng", + "description": "URL of the new page." + } + ] } ] }, diff --git a/Source/WebCore/inspector/front-end/ExtensionPanel.js b/Source/WebCore/inspector/front-end/ExtensionPanel.js index 4249b2c..f09a720 100644 --- a/Source/WebCore/inspector/front-end/ExtensionPanel.js +++ b/Source/WebCore/inspector/front-end/ExtensionPanel.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google Inc. All rights reserved. + * 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 @@ -81,13 +81,13 @@ WebInspector.ExtensionPanel.prototype = { WebInspector.ExtensionPanel.prototype.__proto__ = WebInspector.Panel.prototype; -WebInspector.ExtensionWatchSidebarPane = function(title, id) +WebInspector.ExtensionSidebarPane = function(title, id) { WebInspector.SidebarPane.call(this, title); this._id = id; } -WebInspector.ExtensionWatchSidebarPane.prototype = { +WebInspector.ExtensionSidebarPane.prototype = { setObject: function(object, title) { this._setObject(WebInspector.RemoteObject.fromLocalObject(object), title); @@ -98,6 +98,14 @@ WebInspector.ExtensionWatchSidebarPane.prototype = { RuntimeAgent.evaluate(expression, "extension-watch", false, this._onEvaluate.bind(this, title)); }, + setPage: function(url) + { + this.bodyElement.removeChildren(); + WebInspector.extensionServer.createClientIframe(this.bodyElement, url); + // TODO: Consider doing this upon load event. + WebInspector.extensionServer.notifyExtensionSidebarUpdated(this._id); + }, + _onEvaluate: function(title, error, result) { if (!error) @@ -112,8 +120,8 @@ WebInspector.ExtensionWatchSidebarPane.prototype = { section.headerElement.addStyleClass("hidden"); section.expanded = true; this.bodyElement.appendChild(section.element); - WebInspector.extensionServer.notifyExtensionWatchSidebarUpdated(this._id); + WebInspector.extensionServer.notifyExtensionSidebarUpdated(this._id); } } -WebInspector.ExtensionWatchSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +WebInspector.ExtensionSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; diff --git a/Source/WebCore/inspector/front-end/ExtensionServer.js b/Source/WebCore/inspector/front-end/ExtensionServer.js index 9554dfa..2c95ef0 100644 --- a/Source/WebCore/inspector/front-end/ExtensionServer.js +++ b/Source/WebCore/inspector/front-end/ExtensionServer.js @@ -42,15 +42,15 @@ WebInspector.ExtensionServer = function() this._registerHandler("addAuditCategory", this._onAddAuditCategory.bind(this)); this._registerHandler("addAuditResult", this._onAddAuditResult.bind(this)); this._registerHandler("createPanel", this._onCreatePanel.bind(this)); - this._registerHandler("createSidebarPane", this._onCreateSidebar.bind(this)); - this._registerHandler("createWatchExpressionSidebarPane", this._onCreateWatchExpressionSidebarPane.bind(this)); + this._registerHandler("createSidebarPane", this._onCreateSidebarPane.bind(this)); this._registerHandler("evaluateOnInspectedPage", this._onEvaluateOnInspectedPage.bind(this)); this._registerHandler("getHAR", this._onGetHAR.bind(this)); this._registerHandler("getResourceContent", this._onGetResourceContent.bind(this)); this._registerHandler("log", this._onLog.bind(this)); this._registerHandler("reload", this._onReload.bind(this)); this._registerHandler("setSidebarHeight", this._onSetSidebarHeight.bind(this)); - this._registerHandler("setWatchSidebarContent", this._onSetWatchSidebarContent.bind(this)); + this._registerHandler("setSidebarContent", this._onSetSidebarContent.bind(this)); + this._registerHandler("setSidebarPage", this._onSetSidebarPage.bind(this)); this._registerHandler("stopAuditCategoryRun", this._onStopAuditCategoryRun.bind(this)); this._registerHandler("subscribe", this._onSubscribe.bind(this)); this._registerHandler("unsubscribe", this._onUnsubscribe.bind(this)); @@ -59,11 +59,6 @@ WebInspector.ExtensionServer = function() } WebInspector.ExtensionServer.prototype = { - notifyPanelShown: function(panelName) - { - this._postNotification("panel-shown-" + panelName); - }, - notifyObjectSelected: function(panelId, objectId) { this._postNotification("panel-objectSelected-" + panelId, objectId); @@ -74,19 +69,19 @@ WebInspector.ExtensionServer.prototype = { this._postNotification("panel-search-" + panelId, action, searchString); }, - notifyPageLoaded: function(milliseconds) + notifyPanelShown: function(panelId) { - this._postNotification("inspectedPageLoaded", milliseconds); + this._postNotification("panel-shown-" + panelId); }, - notifyPageDOMContentLoaded: function(milliseconds) + notifyPanelHidden: function(panelId) { - this._postNotification("inspectedPageDOMContentLoaded", milliseconds); + this._postNotification("panel-hidden-" + panelId); }, - notifyInspectedURLChanged: function() + notifyInspectedURLChanged: function(url) { - this._postNotification("inspectedURLChanged"); + this._postNotification("inspectedURLChanged", url); }, notifyInspectorReset: function() @@ -94,9 +89,9 @@ WebInspector.ExtensionServer.prototype = { this._postNotification("reset"); }, - notifyExtensionWatchSidebarUpdated: function(id) + notifyExtensionSidebarUpdated: function(id) { - this._postNotification("watch-sidebar-updated-" + id); + this._postNotification("sidebar-updated-" + id); }, startAuditRun: function(category, auditRun) @@ -195,27 +190,12 @@ WebInspector.ExtensionServer.prototype = { WebInspector.panels[id] = panel; WebInspector.addPanel(panel); - var iframe = this._createClientIframe(panel.element, message.url); + var iframe = this.createClientIframe(panel.element, message.url); iframe.style.height = "100%"; return this._status.OK(); }, - _onCreateSidebar: function(message) - { - var sidebar = this._createSidebar(message, WebInspector.SidebarPane); - if (sidebar.isError) - return sidebar; - this._createClientIframe(sidebar.bodyElement, message.url); - return this._status.OK(); - }, - - _onCreateWatchExpressionSidebarPane: function(message) - { - var sidebar = this._createSidebar(message, WebInspector.ExtensionWatchSidebarPane); - return sidebar.isError ? sidebar : this._status.OK(); - }, - - _createSidebar: function(message, constructor) + _onCreateSidebarPane: function(message, constructor) { var panel = WebInspector.panels[message.panel]; if (!panel) @@ -223,15 +203,15 @@ WebInspector.ExtensionServer.prototype = { if (!panel.sidebarElement || !panel.sidebarPanes) return this._status.E_NOTSUPPORTED(); var id = message.id; - var sidebar = new constructor(message.title, message.id); + var sidebar = new WebInspector.ExtensionSidebarPane(message.title, message.id); this._clientObjects[id] = sidebar; panel.sidebarPanes[id] = sidebar; panel.sidebarElement.appendChild(sidebar.element); - return sidebar; + return this._status.OK(); }, - _createClientIframe: function(parent, url, requestId, port) + createClientIframe: function(parent, url) { var iframe = document.createElement("iframe"); iframe.src = url; @@ -248,7 +228,7 @@ WebInspector.ExtensionServer.prototype = { sidebar.bodyElement.firstChild.style.height = message.height; }, - _onSetWatchSidebarContent: function(message) + _onSetSidebarContent: function(message) { var sidebar = this._clientObjects[message.id]; if (!sidebar) @@ -259,6 +239,14 @@ WebInspector.ExtensionServer.prototype = { sidebar.setObject(message.expression, message.rootTitle); }, + _onSetSidebarPage: function(message) + { + var sidebar = this._clientObjects[message.id]; + if (!sidebar) + return this._status.E_NOTFOUND(message.id); + sidebar.setPage(message.url); + }, + _onLog: function(message) { WebInspector.log(message.message); diff --git a/Source/WebCore/inspector/front-end/GoToLineDialog.js b/Source/WebCore/inspector/front-end/GoToLineDialog.js index 9f4504d..b2490e6 100644 --- a/Source/WebCore/inspector/front-end/GoToLineDialog.js +++ b/Source/WebCore/inspector/front-end/GoToLineDialog.js @@ -118,9 +118,9 @@ WebInspector.GoToLineDialog.prototype = { _highlightSelectedLine: function() { var value = this._input.value; - var lineNumber = parseInt(value, 10); - if (!isNaN(lineNumber) && lineNumber > 0) { - lineNumber = Math.min(lineNumber, this._view.textModel.linesCount); + var lineNumber = parseInt(value, 10) - 1; + if (!isNaN(lineNumber) && lineNumber >= 0) { + lineNumber = Math.min(lineNumber, this._view.textModel.linesCount - 1); this._view.highlightLine(lineNumber); } } diff --git a/Source/WebCore/inspector/front-end/HAREntry.js b/Source/WebCore/inspector/front-end/HAREntry.js index b5223b6..072a55b 100644 --- a/Source/WebCore/inspector/front-end/HAREntry.js +++ b/Source/WebCore/inspector/front-end/HAREntry.js @@ -31,6 +31,9 @@ // See http://groups.google.com/group/http-archive-specification/web/har-1-2-spec // for HAR specification. +// FIXME: Some fields are not yet supported due to back-end limitations. +// See https://bugs.webkit.org/show_bug.cgi?id=58127 for details. + WebInspector.HAREntry = function(resource) { this._resource = resource; @@ -45,7 +48,7 @@ WebInspector.HAREntry.prototype = { time: WebInspector.HAREntry._toMilliseconds(this._resource.duration), request: this._buildRequest(), response: this._buildResponse(), - // cache: {...}, -- Not supproted yet. + cache: { }, // Not supproted yet. timings: this._buildTimings() }; }, @@ -57,33 +60,29 @@ WebInspector.HAREntry.prototype = { url: this._resource.url, // httpVersion: "HTTP/1.1" -- Not available. headers: this._buildHeaders(this._resource.requestHeaders), + queryString: this._buildParameters(this._resource.queryParameters || []), + cookies: this._buildCookies(this._resource.requestCookies || []), headersSize: -1, // Not available. bodySize: -1 // Not available. }; - if (this._resource.queryParameters) - res.queryString = this._buildParameters(this._resource.queryParameters); if (this._resource.requestFormData) res.postData = this._buildPostData(); - if (this._resource.requestCookies) - res.cookies = this._buildCookies(this._resource.requestCookies); return res; }, _buildResponse: function() { - var res = { + return { status: this._resource.statusCode, statusText: this._resource.statusText, // "httpVersion": "HTTP/1.1" -- Not available. headers: this._buildHeaders(this._resource.responseHeaders), + cookies: this._buildCookies(this._resource.responseCookies || []), content: this._buildContent(), redirectURL: this._resource.responseHeaderValue("Location") || "", headersSize: -1, // Not available. bodySize: this._resource.resourceSize }; - if (this._resource.responseCookies) - res.cookies = this._buildCookies(this._resource.responseCookies); - return res; }, _buildContent: function() diff --git a/Source/WebCore/inspector/front-end/HeapSnapshot.js b/Source/WebCore/inspector/front-end/HeapSnapshot.js index c9d1e30..781a13b 100644 --- a/Source/WebCore/inspector/front-end/HeapSnapshot.js +++ b/Source/WebCore/inspector/front-end/HeapSnapshot.js @@ -482,7 +482,7 @@ WebInspector.HeapSnapshotNodeIterator.prototype = { WebInspector.HeapSnapshot = function(profile) { - this.uid = profile.uid; + this.uid = profile.snapshot.uid; this._nodes = profile.nodes; this._strings = profile.strings; @@ -534,6 +534,7 @@ WebInspector.HeapSnapshot.prototype = { delete this._aggregates; this._aggregatesWithIndexes = false; } + delete this._baseNodeIds; }, get _allNodes() @@ -552,10 +553,15 @@ WebInspector.HeapSnapshot.prototype = { return this._nodeCount; }, - restore: function(profile) + nodeFieldValuesByIndex: function(fieldName, indexes) { - this._nodes = profile.nodes; - this._strings = profile.strings; + var node = new WebInspector.HeapSnapshotNode(this); + var result = new Array(indexes.length); + for (var i = 0, l = indexes.length; i < l; ++i) { + node.nodeIndex = indexes[i]; + result[i] = node[fieldName]; + } + return result; }, get rootNode() @@ -762,6 +768,20 @@ WebInspector.HeapSnapshot.prototype = { _numbersComparator: function(a, b) { return a < b ? -1 : (a > b ? 1 : 0); + }, + + baseSnapshotHasNode: function(baseSnapshotId, className, nodeId) + { + return this._baseNodeIds[baseSnapshotId][className].binaryIndexOf(nodeId, this._numbersComparator) !== -1; + }, + + updateBaseNodeIds: function(baseSnapshotId, className, nodeIds) + { + if (!this._baseNodeIds) + this._baseNodeIds = []; + if (!this._baseNodeIds[baseSnapshotId]) + this._baseNodeIds[baseSnapshotId] = {}; + this._baseNodeIds[baseSnapshotId][className] = nodeIds; } }; @@ -1125,3 +1145,59 @@ WebInspector.HeapSnapshotPathFinder.prototype = { return sPath.join(""); } }; + +WebInspector.HeapSnapshotsDiff = function(snapshot, className) +{ + this._snapshot = snapshot; + this._className = className; +}; + +WebInspector.HeapSnapshotsDiff.prototype = { + set baseIds(baseIds) + { + this._baseIds = baseIds; + }, + + set baseSelfSizes(baseSelfSizes) + { + this._baseSelfSizes = baseSelfSizes; + }, + + calculate: function() + { + var indexes = this._snapshot.aggregates(true)[this._className].idxs; + var i = 0, l = this._baseIds.length; + var j = 0, m = indexes.length; + var diff = { addedCount: 0, removedCount: 0, addedSize: 0, removedSize: 0 }; + + var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot); + while (i < l && j < m) { + var nodeAId = this._baseIds[i]; + if (nodeAId < nodeB.id) { + diff.removedCount++; + diff.removedSize += this._baseSelfSizes[i]; + ++i; + } else if (nodeAId > nodeB.id) { + diff.addedCount++; + diff.addedSize += nodeB.selfSize; + nodeB.nodeIndex = indexes[++j]; + } else { + ++i; + nodeB.nodeIndex = indexes[++j]; + } + } + while (i < l) { + diff.removedCount++; + diff.removedSize += this._baseSelfSizes[i]; + ++i; + } + while (j < m) { + diff.addedCount++; + diff.addedSize += nodeB.selfSize; + nodeB.nodeIndex = indexes[++j]; + } + diff.countDelta = diff.addedCount - diff.removedCount; + diff.sizeDelta = diff.addedSize - diff.removedSize; + return diff; + } +}; diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotProxy.js b/Source/WebCore/inspector/front-end/HeapSnapshotProxy.js new file mode 100644 index 0000000..bb0a7ec --- /dev/null +++ b/Source/WebCore/inspector/front-end/HeapSnapshotProxy.js @@ -0,0 +1,287 @@ +/* + * 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 copyrightdd + * 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.HeapSnapshotProxy = function() +{ + this._snapshot = null; +} + +WebInspector.HeapSnapshotProxy.prototype = { + _invokeGetter: function(getterName, callback) + { + function returnResult() + { + callback(this._snapshot[getterName]); + } + setTimeout(returnResult.bind(this), 0); + }, + + aggregates: function(withNodeIndexes, callback) + { + function returnResult() + { + callback(this._snapshot.aggregates(withNodeIndexes)); + } + setTimeout(returnResult.bind(this), 0); + }, + + _extractEdgeData: function(edge) + { + return {name: edge.name, node: this._extractNodeData(edge.node), nodeIndex: edge.nodeIndex, type: edge.type}; + }, + + _extractNodeData: function(node) + { + return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: node.retainedSize, selfSize: node.selfSize, type: node.type}; + }, + + createDiff: function(className) + { + return new WebInspector.HeapSnapshotsDiffProxy(new WebInspector.HeapSnapshotsDiff(this._snapshot, className)); + }, + + createEdgesProvider: function(nodeIndex, filter) + { + function createProvider() + { + if (filter) + filter = filter.bind(this._snapshot); + return new WebInspector.HeapSnapshotEdgesProvider(this._snapshot, nodeIndex, filter); + } + return new WebInspector.HeapSnapshotProviderProxy(createProvider.bind(this), this._extractEdgeData.bind(this)); + }, + + createNodesProvider: function(filter) + { + function createProvider() + { + if (filter) + filter = filter.bind(this._snapshot); + return new WebInspector.HeapSnapshotNodesProvider(this._snapshot, filter); + } + return new WebInspector.HeapSnapshotProviderProxy(createProvider.bind(this), this._extractNodeData.bind(this)); + }, + + createPathFinder: function(targetNodeIndex) + { + return new WebInspector.HeapSnapshotPathFinderProxy(new WebInspector.HeapSnapshotPathFinder(this._snapshot, targetNodeIndex)); + }, + + dispose: function() + { + this._snapshot.dispose(); + }, + + finishLoading: function(callback) + { + if (this._snapshot || !this._isLoading) + return false; + function parse() { + var rawSnapshot = JSON.parse(this._json); + var loadCallbacks = this._onLoadCallbacks; + loadCallbacks.splice(0, 0, callback); + delete this._onLoadCallback; + delete this._json; + delete this._isLoading; + this._snapshot = new WebInspector.HeapSnapshot(rawSnapshot); + this._nodeCount = this._snapshot.nodeCount; + this._rootNodeIndex = this._snapshot._rootNodeIndex; + this._totalSize = this._snapshot.totalSize; + for (var i = 0; i < loadCallbacks.length; ++i) + loadCallbacks[i](); + } + setTimeout(parse.bind(this), 0); + return true; + }, + + get loaded() + { + return !!this._snapshot; + }, + + get nodeCount() + { + return this._nodeCount; + }, + + nodeFieldValuesByIndex: function(fieldName, indexes, callback) + { + function returnResult() + { + callback(this._snapshot.nodeFieldValuesByIndex(fieldName, indexes)); + } + setTimeout(returnResult.bind(this), 0); + }, + + nodeIds: function(callback) + { + this._invokeGetter("nodeIds", callback); + }, + + pushJSONChunk: function(chunk) + { + if (this.loaded || !this._isLoading) + return; + this._json += chunk; + }, + + pushBaseIds: function(snapshotId, className, nodeIds) + { + this._snapshot.updateBaseNodeIds(snapshotId, className, nodeIds); + }, + + get rootNodeIndex() + { + return this._rootNodeIndex; + }, + + startLoading: function(callback) + { + if (this._snapshot) { + function asyncInvoke() + { + callback(); + } + setTimeout(callback, 0); + return false; + } else if (this._isLoading) { + this._onLoadCallbacks.push(callback); + return false; + } else { + this._isLoading = true; + this._onLoadCallbacks = [callback]; + this._json = ""; + return true; + } + }, + + get totalSize() + { + return this._totalSize; + }, + + get uid() + { + return this._snapshot.uid; + } +}; + +WebInspector.HeapSnapshotProviderProxy = function(createProvider, extractData) +{ + this._provider = createProvider(); + this._extractData = extractData; +} + +WebInspector.HeapSnapshotProviderProxy.prototype = { + getNextItems: function(count, callback) + { + function returnResult() + { + var result = new Array(count); + for (var i = 0 ; i < count && this._provider.hasNext(); ++i, this._provider.next()) + result[i] = this._extractData(this._provider.item); + result.length = i; + callback(result, this._provider.hasNext(), this._provider.length); + } + setTimeout(returnResult.bind(this), 0); + }, + + isEmpty: function(callback) + { + function returnResult() + { + callback(this._provider.isEmpty); + } + setTimeout(returnResult.bind(this), 0); + }, + + sortAndRewind: function(comparator, callback) + { + function returnResult() + { + var result = this._provider.sort(comparator); + if (result) + this._provider.first(); + callback(result); + } + setTimeout(returnResult.bind(this), 0); + } +}; + +WebInspector.HeapSnapshotPathFinderProxy = function(pathFinder) +{ + this._pathFinder = pathFinder; +} + +WebInspector.HeapSnapshotPathFinderProxy.prototype = { + findNext: function(callback) + { + function returnResult() + { + callback(this._pathFinder.findNext()); + } + setTimeout(returnResult.bind(this), 0); + }, + + updateRoots: function(filter) + { + function asyncInvoke() + { + this._pathFinder.updateRoots(filter); + } + setTimeout(asyncInvoke.bind(this), 0); + } +}; + +WebInspector.HeapSnapshotsDiffProxy = function(diff) +{ + this._diff = diff; +} + +WebInspector.HeapSnapshotsDiffProxy.prototype = { + calculate: function(callback) + { + function returnResult() + { + callback(this._diff.calculate()); + } + setTimeout(returnResult.bind(this), 0); + }, + + pushBaseIds: function(baseSnapshotId, baseIds) + { + this._diff.baseIds = baseIds; + }, + + pushBaseSelfSizes: function(baseSelfSizes) + { + this._diff.baseSelfSizes = baseSelfSizes; + } +}; diff --git a/Source/WebCore/inspector/front-end/MetricsSidebarPane.js b/Source/WebCore/inspector/front-end/MetricsSidebarPane.js index 1288973..afa3839 100644 --- a/Source/WebCore/inspector/front-end/MetricsSidebarPane.js +++ b/Source/WebCore/inspector/front-end/MetricsSidebarPane.js @@ -61,11 +61,27 @@ WebInspector.MetricsSidebarPane.prototype = { WebInspector.cssModel.getInlineStyleAsync(node.id, inlineStyleCallback); }, + _getPropertyValueAsPx: function(style, propertyName) + { + return Number(style.getPropertyValue(propertyName).replace(/px$/, "") || 0); + }, + + _getBox: function(computedStyle, componentName) + { + var suffix = componentName === "border" ? "-width" : ""; + var left = this._getPropertyValueAsPx(computedStyle, componentName + "-left" + suffix); + var top = this._getPropertyValueAsPx(computedStyle, componentName + "-top" + suffix); + var right = this._getPropertyValueAsPx(computedStyle, componentName + "-right" + suffix); + var bottom = this._getPropertyValueAsPx(computedStyle, componentName + "-bottom" + suffix); + return { left: left, top: top, right: right, bottom: bottom }; + }, + _update: function(style) { // Updating with computed style. var metricsElement = document.createElement("div"); metricsElement.className = "metrics"; + var self = this; function createBoxPartElement(style, name, side, suffix) { @@ -84,6 +100,32 @@ WebInspector.MetricsSidebarPane.prototype = { return element; } + function getContentAreaWidthPx(style) + { + var width = style.getPropertyValue("width").replace(/px$/, ""); + if (style.getPropertyValue("box-sizing") === "border-box") { + var borderBox = self._getBox(style, "border"); + var paddingBox = self._getBox(style, "padding"); + + width = width - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right; + } + + return width; + } + + function getContentAreaHeightPx(style) + { + var height = style.getPropertyValue("height").replace(/px$/, ""); + if (style.getPropertyValue("box-sizing") === "border-box") { + var borderBox = self._getBox(style, "border"); + var paddingBox = self._getBox(style, "padding"); + + height = height - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom; + } + + return height; + } + // Display types for which margin is ignored. var noMarginDisplayType = { "table-cell": true, @@ -127,15 +169,13 @@ WebInspector.MetricsSidebarPane.prototype = { boxElement.className = name; if (name === "content") { - var width = style.getPropertyValue("width").replace(/px$/, ""); var widthElement = document.createElement("span"); - widthElement.textContent = width; - widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width"), false); + widthElement.textContent = getContentAreaWidthPx(style); + widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width", style), false); - var height = style.getPropertyValue("height").replace(/px$/, ""); var heightElement = document.createElement("span"); - heightElement.textContent = height; - heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height"), false); + heightElement.textContent = getContentAreaHeightPx(style); + heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height", style), false); boxElement.appendChild(widthElement); boxElement.appendChild(document.createTextNode(" \u00D7 ")); @@ -168,12 +208,12 @@ WebInspector.MetricsSidebarPane.prototype = { this.bodyElement.appendChild(metricsElement); }, - startEditing: function(targetElement, box, styleProperty) + startEditing: function(targetElement, box, styleProperty, computedStyle) { if (WebInspector.isBeingEdited(targetElement)) return; - var context = { box: box, styleProperty: styleProperty }; + var context = { box: box, styleProperty: styleProperty, computedStyle: computedStyle }; WebInspector.startEditing(targetElement, { context: context, @@ -202,10 +242,34 @@ WebInspector.MetricsSidebarPane.prototype = { else if (context.box === "position" && (!userInput || userInput === "\u2012")) userInput = "auto"; + userInput = userInput.toLowerCase(); // Append a "px" unit if the user input was just a number. if (/^\d+$/.test(userInput)) userInput += "px"; + var styleProperty = context.styleProperty; + var computedStyle = context.computedStyle; + + if (computedStyle.getPropertyValue("box-sizing") === "border-box" && (styleProperty === "width" || styleProperty === "height")) { + if (!userInput.match(/px$/)) { + WebInspector.log("For elements with box-sizing: border-box, only absolute content area dimensions can be applied", WebInspector.ConsoleMessage.MessageLevel.Error); + WebInspector.showConsole(); + return; + } + + var borderBox = this._getBox(computedStyle, "border"); + var paddingBox = this._getBox(computedStyle, "padding"); + var userValuePx = Number(userInput.replace(/px$/, "")); + if (isNaN(userValuePx)) + return; + if (styleProperty === "width") + userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right; + else + userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom; + + userInput = userValuePx + "px"; + } + var self = this; var callback = function(style) { if (!style) @@ -217,7 +281,7 @@ WebInspector.MetricsSidebarPane.prototype = { function setEnabledValueCallback(context, style) { - var property = style.getLiveProperty(context.styleProperty); + var property = style.getLiveProperty(styleProperty); if (!property) style.appendProperty(context.styleProperty, userInput, callback); else diff --git a/Source/WebCore/inspector/front-end/NetworkManager.js b/Source/WebCore/inspector/front-end/NetworkManager.js index 98aa060..b6d413f 100644 --- a/Source/WebCore/inspector/front-end/NetworkManager.js +++ b/Source/WebCore/inspector/front-end/NetworkManager.js @@ -85,16 +85,19 @@ WebInspector.NetworkDispatcher.prototype = { _updateResourceWithResponse: function(resource, response) { - if (!("status" in response)) + if (!response) return; resource.mimeType = response.mimeType; resource.statusCode = response.status; resource.statusText = response.statusText; resource.responseHeaders = response.headers; - // Raw request headers can be a part of response as well. + if (response.headersText) + resource.responseHeadersText = response.headersText; if (response.requestHeaders) resource.requestHeaders = response.requestHeaders; + if (response.requestHeadersText) + resource.requestHeadersText = response.requestHeadersText; resource.connectionReused = response.connectionReused; resource.connectionID = response.connectionID; @@ -112,14 +115,14 @@ WebInspector.NetworkDispatcher.prototype = { this._updateResourceWithResponse(resource, cachedResource.response); }, - requestWillBeSent: function(identifier, frameId, loaderId, documentURL, request, redirectResponse, time, callStack) + requestWillBeSent: function(identifier, frameId, loaderId, documentURL, request, time, stackTrace, redirectResponse) { var resource = this._inflightResourcesById[identifier]; if (resource) { this.responseReceived(identifier, time, "Other", redirectResponse); resource = this._appendRedirect(identifier, time, request.url); } else - resource = this._createResource(identifier, frameId, loaderId, request.url, documentURL, callStack); + resource = this._createResource(identifier, frameId, loaderId, request.url, documentURL, stackTrace); this._updateResourceWithRequest(resource, request); resource.startTime = time; @@ -150,15 +153,27 @@ WebInspector.NetworkDispatcher.prototype = { this._updateResource(resource); }, - dataReceived: function(identifier, time, dataLength, lengthReceived) + domContentEventFired: function(time) + { + if (WebInspector.panels.network) + WebInspector.panels.network.mainResourceDOMContentTime = time; + }, + + loadEventFired: function(time) + { + if (WebInspector.panels.network) + WebInspector.panels.network.mainResourceLoadTime = time; + }, + + dataReceived: function(identifier, time, dataLength, encodedDataLength) { var resource = this._inflightResourcesById[identifier]; if (!resource) return; resource.resourceSize += dataLength; - if (lengthReceived != -1) - resource.increaseTransferSize(lengthReceived); + if (encodedDataLength != -1) + resource.increaseTransferSize(encodedDataLength); resource.endTime = time; this._updateResource(resource); @@ -173,13 +188,14 @@ WebInspector.NetworkDispatcher.prototype = { this._finishResource(resource, finishTime); }, - loadingFailed: function(identifier, time, localizedDescription) + loadingFailed: function(identifier, time, localizedDescription, canceled) { var resource = this._inflightResourcesById[identifier]; if (!resource) return; resource.failed = true; + resource.canceled = canceled; resource.localizedFailDescription = localizedDescription; this._finishResource(resource, time); }, diff --git a/Source/WebCore/inspector/front-end/NetworkPanel.js b/Source/WebCore/inspector/front-end/NetworkPanel.js index 3c497d6..38be11a 100644 --- a/Source/WebCore/inspector/front-end/NetworkPanel.js +++ b/Source/WebCore/inspector/front-end/NetworkPanel.js @@ -827,14 +827,14 @@ WebInspector.NetworkPanel.prototype = { this._appendResource(resourcesToPreserve[i]); }, - canShowSourceLine: function(url, line) + canShowAnchorLocation: function(anchor) { - return !!this._resourcesByURL[url]; + return !!this._resourcesByURL[anchor.href]; }, - showSourceLine: function(url, line) + showAnchorLocation: function(anchor) { - this._showResource(this._resourcesByURL[url], line); + this._showResource(this._resourcesByURL[anchor.href], anchor.getAttribute("line_number") - 1); }, _showResource: function(resource, line) @@ -1506,6 +1506,15 @@ WebInspector.NetworkDataGridNode.prototype = { { this._statusCell.removeChildren(); + if (this._resource.failed) { + if (this._resource.canceled) + this._statusCell.textContent = WebInspector.UIString("(canceled)"); + else + this._statusCell.textContent = WebInspector.UIString("(failed)"); + this._statusCell.addStyleClass("network-dim-cell"); + return; + } + var fromCache = this._resource.cached; if (fromCache) { this._statusCell.textContent = WebInspector.UIString("(from cache)"); @@ -1520,8 +1529,11 @@ WebInspector.NetworkDataGridNode.prototype = { this._appendSubtitle(this._statusCell, this._resource.statusText); this._statusCell.title = this._resource.statusCode + " " + this._resource.statusText; } else { + if (this._resource.isDataURL() && this._resource.finished) + this._statusCell.textContent = WebInspector.UIString("(data url)"); + else + this._statusCell.textContent = WebInspector.UIString("Pending"); this._statusCell.addStyleClass("network-dim-cell"); - this._statusCell.textContent = WebInspector.UIString("Pending"); } }, diff --git a/Source/WebCore/inspector/front-end/Object.js b/Source/WebCore/inspector/front-end/Object.js index 5872b8b..53c20e2 100644 --- a/Source/WebCore/inspector/front-end/Object.js +++ b/Source/WebCore/inspector/front-end/Object.js @@ -57,6 +57,13 @@ WebInspector.Object.prototype = { delete this._listeners; }, + hasEventListeners: function(eventType) + { + if (!("_listeners" in this) || !(eventType in this._listeners)) + return false; + return true; + }, + dispatchEventToListeners: function(eventType, eventData) { if (!("_listeners" in this) || !(eventType in this._listeners)) diff --git a/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js b/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js index 1795843..b42bea3 100644 --- a/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -45,12 +45,16 @@ WebInspector.ObjectPropertiesSection.prototype = { update: function() { var self = this; - var callback = function(properties) { + function callback(properties) + { if (!properties) return; self.updateProperties(properties); - }; - this.object.getProperties(this.ignoreHasOwnProperty, true, callback); + } + if (this.ignoreHasOwnProperty) + this.object.getAllProperties(callback); + else + this.object.getOwnProperties(callback); }, updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer) @@ -155,7 +159,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i])); } }; - this.property.value.getOwnProperties(true, callback.bind(this)); + this.property.value.getOwnProperties(callback.bind(this)); }, ondblclick: function(event) @@ -183,9 +187,14 @@ WebInspector.ObjectPropertyTreeElement.prototype = { var description = this.property.value.description; // Render \n as a nice unicode cr symbol. - if (this.property.value.type === "string" && typeof description === "string") - description = "\"" + description.replace(/\n/g, "\u21B5") + "\""; - this.valueElement.textContent = description; + if (this.property.value.type === "string" && typeof description === "string") { + this.valueElement.textContent = "\"" + description.replace(/\n/g, "\u21B5") + "\""; + this.valueElement._originalTextContent = "\"" + description + "\""; + } else if (this.property.value.type === "function" && typeof description === "string") { + this.valueElement.textContent = /.*/.exec(description)[0].replace(/ +$/g, ""); + this.valueElement._originalTextContent = description; + } else + this.valueElement.textContent = description; if (this.property.isGetter) this.valueElement.addStyleClass("dimmed"); @@ -243,6 +252,10 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.listItemElement.addStyleClass("editing-sub-part"); + // Edit original source. + if (typeof this.valueElement._originalTextContent === "string") + this.valueElement.textContent = this.valueElement._originalTextContent; + WebInspector.startEditing(this.valueElement, { context: context, commitHandler: this.editingCommitted.bind(this), diff --git a/Source/WebCore/inspector/front-end/Panel.js b/Source/WebCore/inspector/front-end/Panel.js index 1b99dd4..49d7cc6 100644 --- a/Source/WebCore/inspector/front-end/Panel.js +++ b/Source/WebCore/inspector/front-end/Panel.js @@ -74,6 +74,7 @@ WebInspector.Panel.prototype = { this.restoreSidebarWidth(); this._restoreScrollPositions(); + WebInspector.extensionServer.notifyPanelShown(this.name); }, hide: function() @@ -86,6 +87,7 @@ WebInspector.Panel.prototype = { delete this._statusBarItemContainer; if ("_toolbarItem" in this) this._toolbarItem.removeStyleClass("toggled-on"); + WebInspector.extensionServer.notifyPanelHidden(this.name); }, reset: function() @@ -235,7 +237,7 @@ WebInspector.Panel.prototype = { if (currentView !== this.visibleView) { this.showView(currentView); - WebInspector.focusSearchField(); + WebInspector.searchController.focusSearchField(); } if (showFirstResult) @@ -268,7 +270,7 @@ WebInspector.Panel.prototype = { if (currentView !== this.visibleView) { this.showView(currentView); - WebInspector.focusSearchField(); + WebInspector.searchController.focusSearchField(); } if (showLastResult) @@ -384,12 +386,12 @@ WebInspector.Panel.prototype = { visibleView.resize(); }, - canShowSourceLine: function(url, line) + canShowAnchorLocation: function(anchor) { return false; }, - showSourceLine: function(url, line) + showAnchorLocation: function(anchor) { return false; }, diff --git a/Source/WebCore/inspector/front-end/PleaseWaitMessage.js b/Source/WebCore/inspector/front-end/PleaseWaitMessage.js index e1980a0..c5ddd49 100644 --- a/Source/WebCore/inspector/front-end/PleaseWaitMessage.js +++ b/Source/WebCore/inspector/front-end/PleaseWaitMessage.js @@ -86,7 +86,7 @@ WebInspector.PleaseWaitMessage.prototype = { var instance = WebInspector.PleaseWaitMessage.prototype.instance; var message = instance.element; if (message.parentNode === element) { - actionCallback(); + setTimeout(actionCallback, 0); return; } diff --git a/Source/WebCore/inspector/front-end/ProfilesPanel.js b/Source/WebCore/inspector/front-end/ProfilesPanel.js index ea5327b..d9a1178 100644 --- a/Source/WebCore/inspector/front-end/ProfilesPanel.js +++ b/Source/WebCore/inspector/front-end/ProfilesPanel.js @@ -211,11 +211,6 @@ WebInspector.ProfilesPanel.prototype = { 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; @@ -450,58 +445,84 @@ WebInspector.ProfilesPanel.prototype = { if (!profile) return; - if (profile._loaded) - callback(profile); - else if (profile._is_loading) - profile._callbacks.push(callback); - else { - profile._is_loading = true; - profile._callbacks = [callback]; - profile._json = ""; - profile.sideBarElement.subtitle = WebInspector.UIString("Loading…"); - ProfilerAgent.getProfile(profile.typeId, profile.uid); + if (!Preferences.detailedHeapProfiles) { + if (profile._loaded) + callback(profile); + else if (profile._is_loading) + profile._callbacks.push(callback); + else { + profile._is_loading = true; + profile._callbacks = [callback]; + profile._json = ""; + profile.sideBarElement.subtitle = WebInspector.UIString("Loading\u2026"); + ProfilerAgent.getProfile(profile.typeId, profile.uid); + } + } else { + if (!profile.proxy) + profile.proxy = new WebInspector.HeapSnapshotProxy(); + var proxy = profile.proxy; + if (proxy.startLoading(callback)) { + profile.sideBarElement.subtitle = WebInspector.UIString("Loading\u2026"); + ProfilerAgent.getProfile(profile.typeId, profile.uid); + } } }, _addHeapSnapshotChunk: function(uid, chunk) { var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)]; - if (!profile || profile._loaded || !profile._is_loading) + if (!profile) return; - - profile._json += chunk; + if (!Preferences.detailedHeapProfiles) { + if (profile._loaded || !profile._is_loading) + return; + profile._json += chunk; + } else { + if (!profile.proxy) + return; + profile.proxy.pushJSONChunk(chunk); + } }, _finishHeapSnapshot: function(uid) { var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)]; - if (!profile || profile._loaded || !profile._is_loading) + if (!profile) return; - - var callbacks = profile._callbacks; - delete profile._callbacks; - profile.sideBarElement.subtitle = WebInspector.UIString("Parsing…"); - window.setTimeout(doParse, 0); - - function doParse() - { - var loadedSnapshot = JSON.parse(profile._json); - delete profile._json; - delete profile._is_loading; - profile._loaded = true; - profile.sideBarElement.subtitle = ""; - - if (!Preferences.detailedHeapProfiles && WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) { - WebInspector.panels.profiles._enableDetailedHeapProfiles(false); + if (!Preferences.detailedHeapProfiles) { + if (profile._loaded || !profile._is_loading) return; - } + profile.sideBarElement.subtitle = WebInspector.UIString("Parsing\u2026"); + function doParse() + { + var loadedSnapshot = JSON.parse(profile._json); + var callbacks = profile._callbacks; + delete profile._callbacks; + delete profile._json; + delete profile._is_loading; + profile._loaded = true; + profile.sideBarElement.subtitle = ""; + + if (WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) { + WebInspector.panels.profiles._enableDetailedHeapProfiles(false); + return; + } - if (!Preferences.detailedHeapProfiles) WebInspector.HeapSnapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot); - else - WebInspector.DetailedHeapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot); - for (var i = 0; i < callbacks.length; ++i) - callbacks[i](profile); + for (var i = 0; i < callbacks.length; ++i) + callbacks[i](profile); + } + setTimeout(doParse, 0); + } else { + if (!profile.proxy) + return; + var proxy = profile.proxy; + function parsed() + { + profile.sideBarElement.subtitle = Number.bytesToString(proxy.totalSize); + } + if (proxy.finishLoading(parsed)) + profile.sideBarElement.subtitle = WebInspector.UIString("Parsing\u2026"); } }, diff --git a/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js b/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js index 4df313c..e6ce0b2 100644 --- a/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js +++ b/Source/WebCore/inspector/front-end/PropertiesSidebarPane.js @@ -57,7 +57,7 @@ WebInspector.PropertiesSidebarPane.prototype = { if (error || !objectPayload) return; var object = WebInspector.RemoteObject.fromPayload(objectPayload); - object.getOwnProperties(false, fillSection.bind(this)); + object.getOwnProperties(fillSection.bind(this)); } function fillSection(prototypes) diff --git a/Source/WebCore/inspector/front-end/RemoteObject.js b/Source/WebCore/inspector/front-end/RemoteObject.js index 294be50..b6038ca 100644 --- a/Source/WebCore/inspector/front-end/RemoteObject.js +++ b/Source/WebCore/inspector/front-end/RemoteObject.js @@ -107,12 +107,17 @@ WebInspector.RemoteObject.prototype = { return this._type === "error"; }, - getOwnProperties: function(abbreviate, callback) + getOwnProperties: function(callback) { - this.getProperties(false, abbreviate, callback); + this._getProperties(false, callback); }, - getProperties: function(ignoreHasOwnProperty, abbreviate, callback) + getAllProperties: function(callback) + { + this._getProperties(true, callback); + }, + + _getProperties: function(ignoreHasOwnProperty, callback) { if (!this._objectId) { callback([]); @@ -126,7 +131,7 @@ WebInspector.RemoteObject.prototype = { properties[i].value = WebInspector.RemoteObject.fromPayload(properties[i].value); callback(properties); } - RuntimeAgent.getProperties(this._objectId, !!ignoreHasOwnProperty, abbreviate, remoteObjectBinder); + RuntimeAgent.getProperties(this._objectId, !!ignoreHasOwnProperty, remoteObjectBinder); }, setPropertyValue: function(name, value, callback) @@ -237,12 +242,12 @@ WebInspector.LocalJSONObject.prototype = { return typeof this._value === "object" && this._value !== null && Object.keys(this._value).length; }, - getOwnProperties: function(abbreviate, callback) + getOwnProperties: function(callback) { - return this.getProperties(false, abbreviate, callback); + callback(this._children()); }, - getProperties: function(ignoreHasOwnProperty, abbreviate, callback) + getAllProperties: function(callback) { callback(this._children()); }, diff --git a/Source/WebCore/inspector/front-end/Resource.js b/Source/WebCore/inspector/front-end/Resource.js index 8035fd8..d8373cd 100644 --- a/Source/WebCore/inspector/front-end/Resource.js +++ b/Source/WebCore/inspector/front-end/Resource.js @@ -33,7 +33,7 @@ WebInspector.Resource = function(identifier, url) this._endTime = -1; this._category = WebInspector.resourceCategories.other; this._pendingContentCallbacks = []; - this._responseHeadersSize = 0; + this.history = []; } // Keep these in sync with WebCore::InspectorResource::Type @@ -101,6 +101,17 @@ WebInspector.Resource.Type = { } } +WebInspector.Resource._domainModelBindings = []; + +WebInspector.Resource.registerDomainModelBinding = function(type, binding) +{ + WebInspector.Resource._domainModelBindings[type] = binding; +} + +WebInspector.Resource.Events = { + RevisionAdded: 0 +} + WebInspector.Resource.prototype = { get url() { @@ -240,7 +251,7 @@ WebInspector.Resource.prototype = { if (this.cached) return 0; if (this.statusCode === 304) // Not modified - return this._responseHeadersSize; + return this.responseHeadersSize; if (this._transferSize !== undefined) return this._transferSize; // If we did not receive actual transfer size from network @@ -254,7 +265,7 @@ WebInspector.Resource.prototype = { // work for chunks with non-trivial encodings. We need a way to // get actual transfer size from the network stack. var bodySize = Number(this.responseHeaders["Content-Length"] || this.resourceSize); - return this._responseHeadersSize + bodySize; + return this.responseHeadersSize + bodySize; }, increaseTransferSize: function(x) @@ -292,6 +303,16 @@ WebInspector.Resource.prototype = { this._failed = x; }, + get canceled() + { + return this._canceled; + }, + + set canceled(x) + { + this._canceled = x; + }, + get category() { return this._category; @@ -393,10 +414,35 @@ WebInspector.Resource.prototype = { this._requestHeaders = x; delete this._sortedRequestHeaders; delete this._requestCookies; + delete this._responseHeadersSize; this.dispatchEventToListeners("requestHeaders changed"); }, + get requestHeadersText() + { + return this._requestHeadersText; + }, + + set requestHeadersText(x) + { + this._requestHeadersText = x; + delete this._responseHeadersSize; + + this.dispatchEventToListeners("requestHeaders changed"); + }, + + get requestHeadersSize() + { + if (typeof(this._requestHeadersSize) === "undefined") { + if (this._requestHeadersText) + this._requestHeadersSize = this._requestHeadersText.length; + else + this._requestHeadersSize = this._headersSize(this._requestHeaders) + } + return this._requestHeadersSize; + }, + get sortedRequestHeaders() { if (this._sortedRequestHeaders !== undefined) @@ -441,13 +487,37 @@ WebInspector.Resource.prototype = { set responseHeaders(x) { this._responseHeaders = x; - // FIXME: we should take actual headers size from network stack, when possible. - this._responseHeadersSize = this._headersSize(x); + delete this._responseHeadersSize; delete this._sortedResponseHeaders; delete this._responseCookies; this.dispatchEventToListeners("responseHeaders changed"); }, + + get responseHeadersText() + { + return this._responseHeadersText; + }, + + set responseHeadersText(x) + { + this._responseHeadersText = x; + delete this._responseHeadersSize; + + this.dispatchEventToListeners("responseHeaders changed"); + }, + + get responseHeadersSize() + { + if (typeof(this._responseHeadersSize) === "undefined") { + if (this._responseHeadersText) + this._responseHeadersSize = this._responseHeadersText.length; + else + this._responseHeadersSize = this._headersSize(this._responseHeaders) + } + return this._responseHeadersSize; + }, + get sortedResponseHeaders() { @@ -526,9 +596,11 @@ WebInspector.Resource.prototype = { _headersSize: function(headers) { + // We should take actual headers size from network stack, when possible, but fall back to + // this lousy computation when no headers text is available. var size = 0; for (var header in headers) - size += header.length + headers[header].length + 3; // _typical_ overhead per herader is ": ".length + "\n".length. + size += header.length + headers[header].length + 4; // _typical_ overhead per header is ": ".length + "\r\n".length. return size; }, @@ -566,7 +638,10 @@ WebInspector.Resource.prototype = { // If status is an error, content is likely to be of an inconsistent type, // as it's going to be an error message. We do not want to emit a warning // for this, though, as this will already be reported as resource loading failure. - if (this.statusCode >= 400) + // Also, if a URL like http://localhost/wiki/load.php?debug=true&lang=en produces text/css and gets reloaded, + // it is 304 Not Modified and its guessed mime-type is text/php, which is wrong. + // Don't check for mime-types in 304-resources. + if (this.statusCode >= 400 || this.statusCode === 304) return true; if (typeof this.type === "undefined" @@ -627,59 +702,34 @@ WebInspector.Resource.prototype = { this._content = content; }, - isLocallyModified: function() + isEditable: function() { - return !!this._baseRevision; + if (this._actualResource) + return false; + var binding = WebInspector.Resource._domainModelBindings[this.type]; + return binding && binding.canSetContent(this); }, - setContent: function(newContent, onRevert) + setContent: function(newContent, majorChange, callback) { - var revisionResource = new WebInspector.Resource(null, this.url); - revisionResource.type = this.type; - revisionResource.loader = this.loader; - revisionResource.timestamp = this.timestamp; - revisionResource._content = this._content; - revisionResource._actualResource = this; - revisionResource._fireOnRevert = onRevert; - - if (this.finished) - revisionResource.finished = true; - else { - function finished() - { - this.removeEventListener("finished", finished); - revisionResource.finished = true; - } - this.addEventListener("finished", finished.bind(this)); + if (!this.isEditable(this)) { + if (callback) + callback("Resource is not editable"); + return; } - - if (!this._baseRevision) - this._baseRevision = revisionResource; - else - revisionResource._baseRevision = this._baseRevision; - - var data = { revision: revisionResource }; - this._content = newContent; - this.timestamp = new Date(); - this.dispatchEventToListeners("content-changed", data); + var binding = WebInspector.Resource._domainModelBindings[this.type]; + binding.setContent(this, newContent, majorChange, callback); }, - revertToThis: function() + addRevision: function(newContent) { - if (!this._actualResource || !this._fireOnRevert) - return; + var revision = new WebInspector.ResourceRevision(this, this._content, this._contentTimestamp); + this.history.push(revision); - function callback(content) - { - if (content) - this._fireOnRevert(content); - } - this.requestContent(callback.bind(this)); - }, + this._content = newContent; + this._contentTimestamp = new Date(); - get baseRevision() - { - return this._baseRevision; + this.dispatchEventToListeners(WebInspector.Resource.Events.RevisionAdded, revision); }, requestContent: function(callback) @@ -713,6 +763,11 @@ WebInspector.Resource.prototype = { image.src = this.url; }, + isDataURL: function() + { + return this.url.match(/^data:/i); + }, + _contentURL: function() { const maxDataUrlSize = 1024 * 1024; @@ -733,6 +788,7 @@ WebInspector.Resource.prototype = { function onResourceContent(data) { this._content = data; + this._originalContent = data; var callbacks = this._pendingContentCallbacks.slice(); for (var i = 0; i < callbacks.length; ++i) callbacks[i](this._content, this._contentEncoded); @@ -744,3 +800,76 @@ WebInspector.Resource.prototype = { } WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.ResourceRevision = function(resource, content, timestamp) +{ + this._resource = resource; + this._content = content; + this._timestamp = timestamp; +} + +WebInspector.ResourceRevision.prototype = { + get resource() + { + return this._resource; + }, + + get timestamp() + { + return this._timestamp; + }, + + get content() + { + return this._content; + }, + + revertToThis: function() + { + function revert(content) + { + this._resource.setContent(content, true); + } + this.requestContent(revert.bind(this)); + }, + + requestContent: function(callback) + { + if (typeof this._content === "string") { + callback(this._content); + return; + } + + // If we are here, this is initial revision. First, look up content fetched over the wire. + if (typeof this.resource._originalContent === "string") { + this._content = this._resource._originalContent; + callback(this._content); + return; + } + + // If unsuccessful, request the content. + function mycallback(content) + { + this._content = content; + callback(content); + } + WebInspector.networkManager.requestContent(this._resource, false, mycallback.bind(this)); + } +} + +WebInspector.ResourceDomainModelBinding = function() +{ +} + +WebInspector.ResourceDomainModelBinding.prototype = { + canSetContent: function() + { + // Implemented by the domains. + return true; + }, + + setContent: function(resource, content, majorChange, callback) + { + // Implemented by the domains. + } +} diff --git a/Source/WebCore/inspector/front-end/ResourceHeadersView.js b/Source/WebCore/inspector/front-end/ResourceHeadersView.js index e79078a..f13a392 100644 --- a/Source/WebCore/inspector/front-end/ResourceHeadersView.js +++ b/Source/WebCore/inspector/front-end/ResourceHeadersView.js @@ -59,9 +59,11 @@ WebInspector.ResourceHeadersView = function(resource) this._requestHeadersTreeElement.selectable = false; this._headersTreeOutline.appendChild(this._requestHeadersTreeElement); - this._decodeHover = WebInspector.UIString("Double-Click to toggle between URL encoded and decoded formats"); this._decodeRequestParameters = true; + this._showRequestHeadersText = false; + this._showResponseHeadersText = false; + this._queryStringTreeElement = new TreeElement("", null, true); this._queryStringTreeElement.expanded = true; this._queryStringTreeElement.selectable = false; @@ -146,7 +148,19 @@ WebInspector.ResourceHeadersView.prototype = { { parmsTreeElement.removeChildren(); - parmsTreeElement.titleHTML = title + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", parms.length) + "</span>"; + parmsTreeElement.listItemElement.removeChildren(); + parmsTreeElement.listItemElement.appendChild(document.createTextNode(title)); + + var headerCount = document.createElement("span"); + headerCount.addStyleClass("header-count"); + headerCount.textContent = WebInspector.UIString(" (%d)", parms.length); + parmsTreeElement.listItemElement.appendChild(headerCount); + + var toggleTitle = this._decodeRequestParameters ? WebInspector.UIString("view URL encoded") : WebInspector.UIString("view decoded"); + var toggleButton = this._createToggleButton(toggleTitle); + toggleButton.addEventListener("click", this._toggleURLdecoding.bind(this)); + parmsTreeElement.listItemElement.appendChild(toggleButton); + for (var i = 0; i < parms.length; ++i) { var name = parms[i].name; @@ -175,8 +189,6 @@ WebInspector.ResourceHeadersView.prototype = { var parmTreeElement = new TreeElement(null, null, false); parmTreeElement.titleHTML = title; parmTreeElement.selectable = false; - parmTreeElement.tooltip = this._decodeHover; - parmTreeElement.ondblclick = this._toggleURLdecoding.bind(this); parmsTreeElement.appendChild(parmTreeElement); } }, @@ -202,7 +214,17 @@ WebInspector.ResourceHeadersView.prototype = { var additionalRow = null; if (typeof this._resource.webSocketRequestKey3 !== "undefined") additionalRow = {header: "(Key3)", value: this._resource.webSocketRequestKey3}; - this._refreshHeaders(WebInspector.UIString("Request Headers"), this._resource.sortedRequestHeaders, additionalRow, this._requestHeadersTreeElement); + if (this._showRequestHeadersText) + this._refreshHeadersText(WebInspector.UIString("Request Headers"), this._resource.requestHeadersText, this._requestHeadersTreeElement); + else + this._refreshHeaders(WebInspector.UIString("Request Headers"), this._resource.sortedRequestHeaders, additionalRow, this._requestHeadersTreeElement); + + if (this._resource.requestHeadersText) { + var toggleButton = this._createHeadersToggleButton(this._showRequestHeadersText); + toggleButton.addEventListener("click", this._toggleRequestHeadersText.bind(this)); + this._requestHeadersTreeElement.listItemElement.appendChild(toggleButton); + } + this._refreshFormData(); }, @@ -211,7 +233,16 @@ WebInspector.ResourceHeadersView.prototype = { var additionalRow = null; if (typeof this._resource.webSocketChallengeResponse !== "undefined") additionalRow = {header: "(Challenge Response)", value: this._resource.webSocketChallengeResponse}; - this._refreshHeaders(WebInspector.UIString("Response Headers"), this._resource.sortedResponseHeaders, additionalRow, this._responseHeadersTreeElement); + if (this._showResponseHeadersText) + this._refreshHeadersText(WebInspector.UIString("Response Headers"), this._resource.responseHeadersText, this._responseHeadersTreeElement); + else + this._refreshHeaders(WebInspector.UIString("Response Headers"), this._resource.sortedResponseHeaders, additionalRow, this._responseHeadersTreeElement); + + if (this._resource.responseHeadersText) { + var toggleButton = this._createHeadersToggleButton(this._showResponseHeadersText); + toggleButton.addEventListener("click", this._toggleResponseHeadersText.bind(this)); + this._responseHeadersTreeElement.listItemElement.appendChild(toggleButton); + } }, _refreshHTTPInformation: function() @@ -242,15 +273,26 @@ WebInspector.ResourceHeadersView.prototype = { } }, + _refreshHeadersTitle: function(title, headersTreeElement, isHeadersTextShown, headersLength) + { + headersTreeElement.listItemElement.removeChildren(); + headersTreeElement.listItemElement.appendChild(document.createTextNode(title)); + + if (!isHeadersTextShown) { + var headerCount = document.createElement("span"); + headerCount.addStyleClass("header-count"); + headerCount.textContent = WebInspector.UIString(" (%d)", headersLength); + headersTreeElement.listItemElement.appendChild(headerCount); + } + }, + _refreshHeaders: function(title, headers, additionalRow, headersTreeElement) { headersTreeElement.removeChildren(); - + var length = headers.length; - headersTreeElement.titleHTML = title.escapeHTML() + "<span class=\"header-count\">" + WebInspector.UIString(" (%d)", length) + "</span>"; + this._refreshHeadersTitle(title, headersTreeElement, false, length); headersTreeElement.hidden = !length; - - var length = headers.length; for (var i = 0; i < length; ++i) { var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>"; title += "<div class=\"header-value source-code\">" + headers[i].value.escapeHTML() + "</div>" @@ -270,6 +312,49 @@ WebInspector.ResourceHeadersView.prototype = { headerTreeElement.selectable = false; headersTreeElement.appendChild(headerTreeElement); } + }, + + _refreshHeadersText: function(title, headersText, headersTreeElement) + { + headersTreeElement.removeChildren(); + + this._refreshHeadersTitle(title, headersTreeElement, true); + var headerTreeElement = new TreeElement(null, null, false); + headerTreeElement.selectable = false; + headersTreeElement.appendChild(headerTreeElement); + headerTreeElement.listItemElement.addStyleClass("headers-text"); + + var headersTextElement = document.createElement("span"); + headersTextElement.addStyleClass("header-value"); + headersTextElement.addStyleClass("source-code"); + headersTextElement.textContent = String(headersText).trim(); + headerTreeElement.listItemElement.appendChild(headersTextElement); + }, + + _toggleRequestHeadersText: function(event) + { + this._showRequestHeadersText = !this._showRequestHeadersText; + this._refreshRequestHeaders(); + }, + + _toggleResponseHeadersText: function(event) + { + this._showResponseHeadersText = !this._showResponseHeadersText; + this._refreshResponseHeaders(); + }, + + _createToggleButton: function(title) + { + var button = document.createElement("span"); + button.addStyleClass("header-toggle"); + button.textContent = title; + return button; + }, + + _createHeadersToggleButton: function(isHeadersTextShown) + { + var toggleTitle = isHeadersTextShown ? WebInspector.UIString("view parsed") : WebInspector.UIString("view source"); + return this._createToggleButton(toggleTitle); } } diff --git a/Source/WebCore/inspector/front-end/ResourceTreeModel.js b/Source/WebCore/inspector/front-end/ResourceTreeModel.js index fa2c44e..890daeb 100644 --- a/Source/WebCore/inspector/front-end/ResourceTreeModel.js +++ b/Source/WebCore/inspector/front-end/ResourceTreeModel.js @@ -31,8 +31,9 @@ WebInspector.ResourceTreeModel = function(networkManager) { - WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this); + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this); WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this); + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this); WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.FrameDetached, this._onFrameDetachedFromParent, this); WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.FrameCommittedLoad, this._onCommitLoad, this); @@ -43,7 +44,8 @@ WebInspector.ResourceTreeModel.EventTypes = { FrameAdded: "FrameAdded", FrameNavigated: "FrameNavigated", FrameDetached: "FrameDetached", - ResourceAdded: "ResourceAdded" + ResourceAdded: "ResourceAdded", + CachedResourcesLoaded: "CachedResourcesLoaded" } WebInspector.ResourceTreeModel.prototype = { @@ -64,6 +66,8 @@ WebInspector.ResourceTreeModel.prototype = { WebInspector.mainResource = this._addFramesRecursively(mainFramePayload); this._cachedResourcesProcessed = true; + + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded); }, _addOrUpdateFrame: function(frame) @@ -131,6 +135,13 @@ WebInspector.ResourceTreeModel.prototype = { this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, frameId); }, + _onResourceStarted: function(event) + { + if (!this._cachedResourcesProcessed) + return; + this._bindResourceURL(event.data); + }, + _onResourceUpdated: function(event) { if (!this._cachedResourcesProcessed) @@ -238,8 +249,6 @@ WebInspector.ResourceTreeModel.prototype = { _callForFrameResources: function(frameId, callback) { var resources = this._resourcesByFrameId[frameId]; - if (!resources) - return; for (var url in resources) { if (callback(resources[url])) @@ -293,6 +302,7 @@ WebInspector.ResourceTreeModel.prototype = { var resource = new WebInspector.Resource(null, url); resource.frameId = frame.id; resource.loaderId = frame.loaderId; + resource.documentURL = frame.url; return resource; } } diff --git a/Source/WebCore/inspector/front-end/ResourceView.js b/Source/WebCore/inspector/front-end/ResourceView.js index ffd9062..acf5a28 100644 --- a/Source/WebCore/inspector/front-end/ResourceView.js +++ b/Source/WebCore/inspector/front-end/ResourceView.js @@ -45,20 +45,12 @@ WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype; WebInspector.ResourceView.createResourceView = function(resource) { - function sourceFrameForDelegateAndURL(delegate, url) - { - var view = new WebInspector.SourceFrame(delegate, url); - view.resource = resource; - return view; - } - switch (resource.category) { case WebInspector.resourceCategories.documents: case WebInspector.resourceCategories.scripts: case WebInspector.resourceCategories.xhr: - return sourceFrameForDelegateAndURL(new WebInspector.SourceFrameDelegateForResourcesPanel(resource), resource.url); case WebInspector.resourceCategories.stylesheets: - return sourceFrameForDelegateAndURL(new WebInspector.CSSSourceFrameDelegateForResourcesPanel(resource), resource.url); + return new WebInspector.ResourceSourceFrame(resource); case WebInspector.resourceCategories.images: return new WebInspector.ImageView(resource); case WebInspector.resourceCategories.fonts: @@ -70,13 +62,13 @@ WebInspector.ResourceView.createResourceView = function(resource) WebInspector.ResourceView.resourceViewTypeMatchesResource = function(resource) { - var resourceView = resource._resourcesView; + var resourceView = resource._resourceView; switch (resource.category) { case WebInspector.resourceCategories.documents: - case WebInspector.resourceCategories.stylesheets: case WebInspector.resourceCategories.scripts: case WebInspector.resourceCategories.xhr: - return resourceView.__proto__ === WebInspector.SourceFrame.prototype; + case WebInspector.resourceCategories.stylesheets: + return resourceView.__proto__ === WebInspector.ResourceSourceFrame.prototype; case WebInspector.resourceCategories.images: return resourceView.__proto__ === WebInspector.ImageView.prototype; case WebInspector.resourceCategories.fonts: @@ -90,23 +82,23 @@ WebInspector.ResourceView.resourceViewForResource = function(resource) { if (!resource) return null; - if (!resource._resourcesView) - resource._resourcesView = WebInspector.ResourceView.createResourceView(resource); - return resource._resourcesView; + if (!resource._resourceView) + resource._resourceView = WebInspector.ResourceView.createResourceView(resource); + return resource._resourceView; } WebInspector.ResourceView.recreateResourceView = function(resource) { var newView = WebInspector.ResourceView.createResourceView(resource); - var oldView = resource._resourcesView; + var oldView = resource._resourceView; var oldViewParentNode = oldView.visible ? oldView.element.parentNode : null; var scrollTop = oldView.scrollTop; - resource._resourcesView.detach(); - delete resource._resourcesView; + resource._resourceView.detach(); + delete resource._resourceView; - resource._resourcesView = newView; + resource._resourceView = newView; if (oldViewParentNode) newView.show(oldViewParentNode); @@ -120,88 +112,99 @@ WebInspector.ResourceView.existingResourceViewForResource = function(resource) { if (!resource) return null; - return resource._resourcesView; + return resource._resourceView; } -WebInspector.SourceFrameDelegateForResourcesPanel = function(resource) +WebInspector.ResourceSourceFrame = function(resource) { - WebInspector.SourceFrameDelegate.call(this); + WebInspector.SourceFrame.call(this, new WebInspector.SourceFrameDelegate(), resource.url); this._resource = resource; } //This is a map from resource.type to mime types //found in WebInspector.SourceTokenizer.Registry. -WebInspector.SourceFrameDelegateForResourcesPanel.DefaultMIMETypeForResourceType = { +WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType = { 0: "text/html", 1: "text/css", 4: "text/javascript" } -WebInspector.SourceFrameDelegateForResourcesPanel.prototype = { +WebInspector.ResourceSourceFrame.prototype = { + get resource() + { + return this._resource; + }, + + isContentEditable: function() + { + return this._resource.isEditable(); + }, + + editContent: function(newText, callback) + { + this._clearIncrementalUpdateTimer(); + var majorChange = true; + this._resource.setContent(newText, majorChange, callback); + }, + + endEditing: function(oldRange, newRange) + { + function commitIncrementalEdit() + { + var majorChange = false; + this._resource.setContent(this._textModel.text, majorChange, function() {}); + } + const updateTimeout = 200; + this._incrementalUpdateTimer = setTimeout(commitIncrementalEdit.bind(this), updateTimeout); + }, + + _clearIncrementalUpdateTimer: function() + { + if (this._incrementalUpdateTimer) + clearTimeout(this._incrementalUpdateTimer); + delete this._incrementalUpdateTimer; + }, + requestContent: function(callback) { function contentLoaded(text) { - var mimeType = WebInspector.SourceFrameDelegateForResourcesPanel.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType; - var sourceMapping = new WebInspector.IdenticalSourceMapping(); - callback(mimeType, new WebInspector.SourceFrameContent(text, sourceMapping, [])); + var mimeType = WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType[this._resource.type] || this._resource.mimeType; + callback(mimeType, text); } this._resource.requestContent(contentLoaded.bind(this)); } } -WebInspector.SourceFrameDelegateForResourcesPanel.prototype.__proto__ = WebInspector.SourceFrameDelegate.prototype; - +WebInspector.ResourceSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype; -WebInspector.CSSSourceFrameDelegateForResourcesPanel = function(resource) +WebInspector.RevisionSourceFrame = function(revision) { - WebInspector.SourceFrameDelegateForResourcesPanel.call(this, resource); + WebInspector.SourceFrame.call(this, new WebInspector.SourceFrameDelegate(), revision.resource.url); + this._revision = revision; } -WebInspector.CSSSourceFrameDelegateForResourcesPanel.prototype = { - canEditScriptSource: function() +WebInspector.RevisionSourceFrame.prototype = { + get resource() { - return true; + return this._revision.resource; }, - editScriptSource: function(newText) + isContentEditable: function() { - function handleStyleSheet(newText, styleSheet) - { - this._styleSheet = styleSheet; - this._saveStyleSheet(newText); - } - - function handleInfos(newText, error, infos) - { - if (error) - return; - for (var i = 0; i < infos.length; ++i) { - var info = infos[i]; - if (info.sourceURL === this._resource.url) { - WebInspector.CSSStyleSheet.createForId(info.styleSheetId, handleStyleSheet.bind(this, newText)); - break; - } - } - } - - if (this._styleSheet) - this._saveStyleSheet(newText); - else - CSSAgent.getAllStyleSheets(handleInfos.bind(this, newText)); + return false; }, - _saveStyleSheet: function(newText) + requestContent: function(callback) { - function callback(success) + function contentLoaded(text) { - if (!success) - console.error("Failed to save modified stylesheet %s", this._resource.url); + var mimeType = WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType[this._revision.resource.type] || this._revision.resource.mimeType; + callback(mimeType, text); } - - this._styleSheet.setText(newText, callback.bind(this)); + this._revision.requestContent(contentLoaded.bind(this)); } } -WebInspector.CSSSourceFrameDelegateForResourcesPanel.prototype.__proto__ = WebInspector.SourceFrameDelegateForResourcesPanel.prototype; +WebInspector.RevisionSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype; diff --git a/Source/WebCore/inspector/front-end/ResourcesPanel.js b/Source/WebCore/inspector/front-end/ResourcesPanel.js index c65e6b7..d8e2b10 100644 --- a/Source/WebCore/inspector/front-end/ResourcesPanel.js +++ b/Source/WebCore/inspector/front-end/ResourcesPanel.js @@ -111,10 +111,6 @@ WebInspector.ResourcesPanel.prototype = { _initDefaultSelection: function() { - if (this._initializedDefaultSelection) - return; - - this._initializedDefaultSelection = true; var itemURL = WebInspector.settings.resourcesLastSelectedItem; if (itemURL) { for (var treeElement = this.sidebarTree.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.sidebarTree, true)) { @@ -177,6 +173,7 @@ WebInspector.ResourcesPanel.prototype = { WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._cachedResourcesLoaded, this); function populateFrame(frameId) { @@ -191,7 +188,6 @@ WebInspector.ResourcesPanel.prototype = { this._resourceAdded({data:resources[i]}); } populateFrame.call(this, 0); - this._initDefaultSelection(); }, _frameAdded: function(event) @@ -205,7 +201,11 @@ WebInspector.ResourcesPanel.prototype = { var frameTreeElement = this._treeElementForFrameId[frameId]; if (frameTreeElement) { + // Maintain sorted order. + var parent = frameTreeElement.parent; + parent.removeChild(frameTreeElement); frameTreeElement.setTitles(title, subtitle); + parent.appendChild(frameTreeElement); return; } @@ -217,20 +217,6 @@ WebInspector.ResourcesPanel.prototype = { var frameTreeElement = new WebInspector.FrameTreeElement(this, frameId, title, subtitle); this._treeElementForFrameId[frameId] = frameTreeElement; - - // Insert in the alphabetical order, first frames, then resources. - var children = parentTreeElement.children; - for (var i = 0; i < children.length; ++i) { - var child = children[i]; - if (!(child instanceof WebInspector.FrameTreeElement)) { - parentTreeElement.insertChild(frameTreeElement, i); - return; - } - if (child.displayName.localeCompare(frameTreeElement.displayName) > 0) { - parentTreeElement.insertChild(frameTreeElement, i); - return; - } - } parentTreeElement.appendChild(frameTreeElement); }, @@ -260,22 +246,7 @@ WebInspector.ResourcesPanel.prototype = { return; } - var resourceTreeElement = new WebInspector.FrameResourceTreeElement(this, resource); - - // Insert in the alphabetical order, first frames, then resources. Document resource goes first. - var children = frameTreeElement.children; - for (var i = 0; i < children.length; ++i) { - var child = children[i]; - if (!(child instanceof WebInspector.FrameResourceTreeElement)) - continue; - - if (resource.type === WebInspector.Resource.Type.Document || - (child._resource.type !== WebInspector.Resource.Type.Document && child._resource.displayName.localeCompare(resource.displayName) > 0)) { - frameTreeElement.insertChild(resourceTreeElement, i); - return; - } - } - frameTreeElement.appendChild(resourceTreeElement); + frameTreeElement.appendResource(resource); }, _frameNavigated: function(event) @@ -294,6 +265,11 @@ WebInspector.ResourcesPanel.prototype = { frameTreeElement.removeChildren(); }, + _cachedResourcesLoaded: function() + { + this._initDefaultSelection(); + }, + _refreshResource: function(event) { var resource = event.data; @@ -365,23 +341,23 @@ WebInspector.ResourcesPanel.prototype = { } }, - canShowSourceLine: function(url, line) + canShowAnchorLocation: function(anchor) { - return !!WebInspector.resourceForURL(url); + return !!WebInspector.resourceForURL(anchor.href); }, - showSourceLine: function(url, line) + showAnchorLocation: function(anchor) { - var resource = WebInspector.resourceForURL(url); + var resource = WebInspector.resourceForURL(anchor.href); if (resource.type === WebInspector.Resource.Type.XHR) { // Show XHRs in the network panel only. - if (WebInspector.panels.network && WebInspector.panels.network.canShowSourceLine(url, line)) { + if (WebInspector.panels.network && WebInspector.panels.network.canShowAnchorLocation(anchor)) { WebInspector.currentPanel = WebInspector.panels.network; - WebInspector.panels.network.showSourceLine(url, line); + WebInspector.panels.network.showAnchorLocation(anchor); } return; } - this.showResource(WebInspector.resourceForURL(url), line); + this.showResource(resource, anchor.getAttribute("line_number") - 1); }, showResource: function(resource, line) @@ -392,10 +368,8 @@ WebInspector.ResourcesPanel.prototype = { resourceTreeElement.select(); } - if (line) { + if (line !== undefined) { var view = WebInspector.ResourceView.resourceViewForResource(resource); - if (view.revealLine) - view.revealLine(line); if (view.highlightLine) view.highlightLine(line); } @@ -405,19 +379,40 @@ WebInspector.ResourcesPanel.prototype = { _showResourceView: function(resource) { var view = WebInspector.ResourceView.resourceViewForResource(resource); + this._fetchAndApplyDiffMarkup(view, resource); + this._innerShowView(view); + }, - // Consider rendering diff markup here. - if (resource.baseRevision && view instanceof WebInspector.SourceFrame) { - function callback(baseContent) - { - if (baseContent) - this._applyDiffMarkup(view, baseContent, resource.content); - } - resource.baseRevision.requestContent(callback.bind(this)); - } + _showRevisionView: function(revision) + { + if (!revision._view) + revision._view = new WebInspector.RevisionSourceFrame(revision); + var view = revision._view; + this._fetchAndApplyDiffMarkup(view, revision.resource, revision); this._innerShowView(view); }, + _fetchAndApplyDiffMarkup: function(view, resource, revision) + { + var baseRevision = resource.history[0]; + if (!baseRevision) + return; + if (!(view instanceof WebInspector.SourceFrame)) + return; + + baseRevision.requestContent(step1.bind(this)); + + function step1(baseContent) + { + (revision ? revision : resource).requestContent(step2.bind(this, baseContent)); + } + + function step2(baseContent, revisionContent) + { + this._applyDiffMarkup(view, baseContent, revisionContent); + } + }, + _applyDiffMarkup: function(view, baseContent, newContent) { var oldLines = baseContent.split(/\r?\n/); var newLines = newContent.split(/\r?\n/); @@ -695,7 +690,7 @@ WebInspector.ResourcesPanel.prototype = { var views = []; const visibleView = this.visibleView; - if (visibleView.performSearch) + if (visibleView && visibleView.performSearch) views.push(visibleView); function callback(resourceTreeElement) @@ -810,12 +805,13 @@ WebInspector.ResourcesPanel.prototype = { WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype; -WebInspector.BaseStorageTreeElement = function(storagePanel, representedObject, title, iconClasses, hasChildren) +WebInspector.BaseStorageTreeElement = function(storagePanel, representedObject, title, iconClasses, hasChildren, noIcon) { TreeElement.call(this, "", representedObject, hasChildren); this._storagePanel = storagePanel; this._titleText = title; this._iconClasses = iconClasses; + this._noIcon = noIcon; } WebInspector.BaseStorageTreeElement.prototype = { @@ -831,9 +827,11 @@ WebInspector.BaseStorageTreeElement.prototype = { selectionElement.className = "selection"; this.listItemElement.appendChild(selectionElement); - this.imageElement = document.createElement("img"); - this.imageElement.className = "icon"; - this.listItemElement.appendChild(this.imageElement); + if (!this._noIcon) { + this.imageElement = document.createElement("img"); + this.imageElement.className = "icon"; + this.listItemElement.appendChild(this.imageElement); + } this.titleElement = document.createElement("div"); this.titleElement.className = "base-storage-tree-element-title"; @@ -879,9 +877,9 @@ WebInspector.BaseStorageTreeElement.prototype = { WebInspector.BaseStorageTreeElement.prototype.__proto__ = TreeElement.prototype; -WebInspector.StorageCategoryTreeElement = function(storagePanel, categoryName, settingsKey, iconClasses) +WebInspector.StorageCategoryTreeElement = function(storagePanel, categoryName, settingsKey, iconClasses, noIcon) { - WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, categoryName, iconClasses, true); + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, categoryName, iconClasses, true, noIcon); this._expandedSettingKey = "resources" + settingsKey + "Expanded"; WebInspector.settings.installApplicationSetting(this._expandedSettingKey, settingsKey === "Frames"); this._categoryName = categoryName; @@ -923,6 +921,7 @@ WebInspector.FrameTreeElement = function(storagePanel, frameId, title, subtitle) WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, "", ["frame-storage-tree-item"]); this._frameId = frameId; this.setTitles(title, subtitle); + this._categoryElements = {}; } WebInspector.FrameTreeElement.prototype = { @@ -957,15 +956,16 @@ WebInspector.FrameTreeElement.prototype = { setTitles: function(title, subtitle) { - this._displayName = ""; + this._displayName = title || ""; + if (subtitle) + this._displayName += " (" + subtitle + ")"; + if (this.parent) { this.titleElement.textContent = title || ""; - this._displayName = title || ""; if (subtitle) { var subtitleElement = document.createElement("span"); subtitleElement.className = "base-storage-tree-element-subtitle"; subtitleElement.textContent = "(" + subtitle + ")"; - this._displayName += " (" + subtitle + ")"; this.titleElement.appendChild(subtitleElement); } } else { @@ -983,8 +983,67 @@ WebInspector.FrameTreeElement.prototype = { this.listItemElement.removeStyleClass("hovered"); DOMAgent.hideFrameHighlight(); } + }, + + appendResource: function(resource) + { + var categoryName = resource.category.name; + var categoryElement = resource.category === WebInspector.resourceCategories.documents ? this : this._categoryElements[categoryName]; + if (!categoryElement) { + categoryElement = new WebInspector.StorageCategoryTreeElement(this._storagePanel, resource.category.title, categoryName, null, true); + this._categoryElements[resource.category.name] = categoryElement; + this._insertInPresentationOrder(this, categoryElement); + } + var resourceTreeElement = new WebInspector.FrameResourceTreeElement(this._storagePanel, resource); + this._insertInPresentationOrder(categoryElement, resourceTreeElement); + resourceTreeElement._populateRevisions(); + }, + + appendChild: function(treeElement) + { + this._insertInPresentationOrder(this, treeElement); + }, + + _insertInPresentationOrder: function(parentTreeElement, childTreeElement) + { + // Insert in the alphabetical order, first frames, then resources. Document resource goes last. + function typeWeight(treeElement) + { + if (treeElement instanceof WebInspector.StorageCategoryTreeElement) + return 2; + if (treeElement instanceof WebInspector.FrameTreeElement) + return 1; + return 3; + } + + function compare(treeElement1, treeElement2) + { + var typeWeight1 = typeWeight(treeElement1); + var typeWeight2 = typeWeight(treeElement2); + + var result; + if (typeWeight1 > typeWeight2) + result = 1; + else if (typeWeight1 < typeWeight2) + result = -1; + else { + var title1 = treeElement1.displayName || treeElement1.titleText; + var title2 = treeElement2.displayName || treeElement2.titleText; + result = title1.localeCompare(title2); + } + return result; + } + + var children = parentTreeElement.children; + var i; + for (i = 0; i < children.length; ++i) { + if (compare(childTreeElement, children[i]) < 0) + break; + } + parentTreeElement.insertChild(childTreeElement, i); } } + WebInspector.FrameTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; WebInspector.FrameResourceTreeElement = function(storagePanel, resource) @@ -992,7 +1051,7 @@ WebInspector.FrameResourceTreeElement = function(storagePanel, resource) WebInspector.BaseStorageTreeElement.call(this, storagePanel, resource, resource.displayName, ["resource-sidebar-tree-item", "resources-category-" + resource.category.name]); this._resource = resource; this._resource.addEventListener("errors-warnings-updated", this._errorsWarningsUpdated, this); - this._resource.addEventListener("content-changed", this._contentChanged, this); + this._resource.addEventListener(WebInspector.Resource.Events.RevisionAdded, this._revisionAdded, this); this.tooltip = resource.url; } @@ -1104,9 +1163,20 @@ WebInspector.FrameResourceTreeElement.prototype = { this._bubbleElement.addStyleClass("error"); }, - _contentChanged: function(event) + _populateRevisions: function() + { + for (var i = 0; i < this._resource.history.length; ++i) + this._appendRevision(this._resource.history[i]); + }, + + _revisionAdded: function(event) + { + this._appendRevision(event.data); + }, + + _appendRevision: function(revision) { - this.insertChild(new WebInspector.ResourceRevisionTreeElement(this._storagePanel, event.data.revision), 0); + this.insertChild(new WebInspector.ResourceRevisionTreeElement(this._storagePanel, revision), 0); var oldView = WebInspector.ResourceView.existingResourceViewForResource(this._resource); if (oldView) { var newView = WebInspector.ResourceView.recreateResourceView(this._resource); @@ -1243,13 +1313,18 @@ WebInspector.ApplicationCacheTreeElement.prototype.__proto__ = WebInspector.Base WebInspector.ResourceRevisionTreeElement = function(storagePanel, revision) { var title = revision.timestamp ? revision.timestamp.toLocaleTimeString() : WebInspector.UIString("(original)"); - WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, title, ["resource-sidebar-tree-item", "resources-category-" + revision.category.name]); + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, title, ["resource-sidebar-tree-item", "resources-category-" + revision.resource.category.name]); if (revision.timestamp) this.tooltip = revision.timestamp.toLocaleString(); - this._resource = revision; + this._revision = revision; } WebInspector.ResourceRevisionTreeElement.prototype = { + get itemURL() + { + return this._revision.resource.url; + }, + onattach: function() { WebInspector.BaseStorageTreeElement.prototype.onattach.call(this); @@ -1261,20 +1336,22 @@ WebInspector.ResourceRevisionTreeElement.prototype = { onselect: function() { WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); - this._storagePanel._showResourceView(this._resource); + this._storagePanel._showRevisionView(this._revision); }, _ondragstart: function(event) { - event.dataTransfer.setData("text/plain", this._resource.content); - event.dataTransfer.effectAllowed = "copy"; - return true; + if (this._revision.content) { + event.dataTransfer.setData("text/plain", this._revision.content); + event.dataTransfer.effectAllowed = "copy"; + return true; + } }, _handleContextMenuEvent: function(event) { var contextMenu = new WebInspector.ContextMenu(); - contextMenu.appendItem(WebInspector.UIString("Revert to this revision"), this._resource.revertToThis.bind(this._resource)); + contextMenu.appendItem(WebInspector.UIString("Revert to this revision"), this._revision.revertToThis.bind(this._revision)); contextMenu.show(event); } } diff --git a/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js b/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js index bdbb0cf..b7f0dad 100644 --- a/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js +++ b/Source/WebCore/inspector/front-end/ScopeChainSidebarPane.js @@ -59,40 +59,45 @@ WebInspector.ScopeChainSidebarPane.prototype = { var foundLocalScope = false; var scopeChain = callFrame.scopeChain; for (var i = 0; i < scopeChain.length; ++i) { - var scopeObjectProxy = scopeChain[i]; + var scope = scopeChain[i]; var title = null; - var subtitle = scopeObjectProxy.description; + var subtitle = scope.object.description; var emptyPlaceholder = null; var extraProperties = null; - if (scopeObjectProxy.isLocal) { - foundLocalScope = true; - title = WebInspector.UIString("Local"); - emptyPlaceholder = WebInspector.UIString("No Variables"); - subtitle = null; - if (scopeObjectProxy.thisObject) - extraProperties = [ new WebInspector.RemoteObjectProperty("this", WebInspector.RemoteObject.fromPayload(scopeObjectProxy.thisObject)) ]; - } else if (scopeObjectProxy.isClosure) { - title = WebInspector.UIString("Closure"); - emptyPlaceholder = WebInspector.UIString("No Variables"); - subtitle = null; - } else if (i === (scopeChain.length - 1)) - title = WebInspector.UIString("Global"); - else if (scopeObjectProxy.isElement) - title = WebInspector.UIString("Event Target"); - else if (scopeObjectProxy.isDocument) - title = WebInspector.UIString("Event Document"); - else if (scopeObjectProxy.isWithBlock) - title = WebInspector.UIString("With Block"); + switch (scope.type) { + case "local": + foundLocalScope = true; + title = WebInspector.UIString("Local"); + emptyPlaceholder = WebInspector.UIString("No Variables"); + subtitle = null; + if (scope.this) + extraProperties = [ new WebInspector.RemoteObjectProperty("this", WebInspector.RemoteObject.fromPayload(scope.this)) ]; + break; + case "closure": + title = WebInspector.UIString("Closure"); + emptyPlaceholder = WebInspector.UIString("No Variables"); + subtitle = null; + break; + case "catch": + title = WebInspector.UIString("Catch"); + break; + case "with": + title = WebInspector.UIString("With Block"); + break; + case "global": + title = WebInspector.UIString("Global"); + break; + } if (!title || title === subtitle) subtitle = null; - var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromPayload(scopeObjectProxy), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement); + var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromPayload(scope.object), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement); section.editInSelectedCallFrameWhenPaused = true; section.pane = this; - if (!foundLocalScope || scopeObjectProxy.isLocal || title in this._expandedSections) + if (!foundLocalScope || scope.type === "local" || title in this._expandedSections) section.expanded = true; this._sections.push(section); diff --git a/Source/WebCore/inspector/front-end/Script.js b/Source/WebCore/inspector/front-end/Script.js index 805e191..9e75d83 100644 --- a/Source/WebCore/inspector/front-end/Script.js +++ b/Source/WebCore/inspector/front-end/Script.js @@ -23,91 +23,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.Script = function(sourceID, sourceURL, source, lineOffset, columnOffset, length, errorLine, errorMessage, worldType) +WebInspector.Script = function(sourceID, sourceURL, lineOffset, columnOffset, length, errorLine, errorMessage, isContentScript) { this.sourceID = sourceID; this.sourceURL = sourceURL; - this._source = source; this.lineOffset = lineOffset; this.columnOffset = columnOffset; this.length = length; this.errorLine = errorLine; this.errorMessage = errorMessage; - this.worldType = worldType; - - // if no URL, look for "//@ sourceURL=" decorator - // note that this sourceURL comment decorator is behavior that FireBug added - // in it's 1.1 release as noted in the release notes: - // http://fbug.googlecode.com/svn/branches/firebug1.1/docs/ReleaseNotes_1.1.txt - if (!sourceURL) { - // use of [ \t] rather than \s is to prevent \n from matching - var pattern = /^\s*\/\/[ \t]*@[ \t]*sourceURL[ \t]*=[ \t]*(\S+).*$/m; - var match = pattern.exec(source); - - if (match) - this.sourceURL = match[1]; - } -} - -WebInspector.Script.WorldType = { - MAIN_WORLD: 0, - EXTENSIONS_WORLD: 1 -} - -WebInspector.Script.WorldType = { - MAIN_WORLD: 0, - EXTENSIONS_WORLD: 1 + this.isContentScript = isContentScript; } WebInspector.Script.prototype = { - get startingLine() - { - return this.lineOffset + 1; - }, - - get linesCount() - { - if (!this.source) - return 0; - if (!this._lineEndings) - this._lineEndings = this._source.findAll("\n"); - return this._lineEndings.length + 1; - }, - - sourceLine: function(lineNumber, callback) - { - function extractSourceLine() - { - lineNumber -= this.lineOffset; - callback(this._source.substring(this._lineEndings[lineNumber - 1], this._lineEndings[lineNumber])); - } - - if (this._lineEndings) { - extractSourceLine.call(this); - return; - } - - function didRequestSource() - { - this._lineEndings = this._source.findAll("\n"); - extractSourceLine.call(this); - } - this.requestSource(didRequestSource.bind(this)); - }, - - get source() - { - if (!this._source && this.resource) - this._source = this.resource.content; - return this._source; - }, - - set source(source) - { - this._source = source; - delete this._lineEndings; - }, - requestSource: function(callback) { if (this._source) { @@ -117,11 +45,20 @@ WebInspector.Script.prototype = { function didGetScriptSource(error, source) { - if (error) - return; this._source = source; callback(this._source); } DebuggerAgent.getScriptSource(this.sourceID, didGetScriptSource.bind(this)); + }, + + editSource: function(newSource, callback) + { + function didEditScriptSource(error, callFrames) + { + if (!error) + this._source = newSource; + callback(error, callFrames); + } + DebuggerAgent.editScriptSource(this.sourceID, newSource, didEditScriptSource.bind(this)); } } diff --git a/Source/WebCore/inspector/front-end/ScriptFormatter.js b/Source/WebCore/inspector/front-end/ScriptFormatter.js index 2e166f4..8085c55 100644 --- a/Source/WebCore/inspector/front-end/ScriptFormatter.js +++ b/Source/WebCore/inspector/front-end/ScriptFormatter.js @@ -36,10 +36,15 @@ WebInspector.ScriptFormatter = function() this._tasks = []; } -WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, lineNumber, columnNumber) +WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, location) { - var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0; - return position + columnNumber; + var position = location.lineNumber ? lineEndings[location.lineNumber - 1] + 1 : 0; + return position + location.columnNumber; +} + +WebInspector.ScriptFormatter.lineToPosition = function(lineEndings, lineNumber) +{ + return this.locationToPosition(lineEndings, { lineNumber: lineNumber, columnNumber: 0 }); } WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position) @@ -58,7 +63,7 @@ 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); + start.position = WebInspector.ScriptFormatter.locationToPosition(lineEndings, start); var endPosition = start.position + scripts[i].length; var end = WebInspector.ScriptFormatter.positionToLocation(lineEndings, endPosition); end.position = endPosition; diff --git a/Source/WebCore/inspector/front-end/ScriptFormatterWorker.js b/Source/WebCore/inspector/front-end/ScriptFormatterWorker.js index 1a4c28e..ab68524 100644 --- a/Source/WebCore/inspector/front-end/ScriptFormatterWorker.js +++ b/Source/WebCore/inspector/front-end/ScriptFormatterWorker.js @@ -28,9 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var parse = loadModule("parse-js.js"); -var process = loadModule("process.js"); - onmessage = function(event) { var source = event.data; var formattedSource = beautify(source); @@ -53,34 +50,31 @@ function beautify(source) function buildMapping(source, formattedSource) { var mapping = { original: [], formatted: [] }; - var lastCodePosition = 0; - var regexp = /[\$\.\w]+|{|}/g; + var lastPosition = 0; + var regexp = /(^|[^\\])\b((?=\D)[\$\.\w]+)\b/g; while (true) { var match = regexp.exec(formattedSource); if (!match) break; - var position = source.indexOf(match[0], lastCodePosition); + var position = source.indexOf(match[2], lastPosition); if (position === -1) - continue; + throw "No match found in original source for " + match[2]; mapping.original.push(position); - mapping.formatted.push(match.index); - lastCodePosition = position + match[0].length; + mapping.formatted.push(match.index + match[1].length); + lastPosition = position + match[2].length; } return mapping; } -function loadModule(src) -{ - var request = new XMLHttpRequest(); - request.open("GET", src, false); - request.send(); - - var exports = {}; - eval(request.responseText); - return exports; -} - function require() { return parse; } + +var exports = {}; +importScripts("UglifyJS/parse-js.js"); +var parse = exports; + +var exports = {}; +importScripts("UglifyJS/process.js"); +var process = exports; diff --git a/Source/WebCore/inspector/front-end/ScriptsPanel.js b/Source/WebCore/inspector/front-end/ScriptsPanel.js index 7547c36..8a6c58e 100644 --- a/Source/WebCore/inspector/front-end/ScriptsPanel.js +++ b/Source/WebCore/inspector/front-end/ScriptsPanel.js @@ -65,15 +65,6 @@ WebInspector.ScriptsPanel = function() // FIXME: append the functions select element to the top status bar when it is implemented. // this.topStatusBar.appendChild(this.functionsSelectElement); - this.formatButton = document.createElement("button"); - this.formatButton.className = "status-bar-item"; - this.formatButton.id = "format-script"; - this.formatButton.title = WebInspector.UIString("Format script."); - this.formatButton.appendChild(document.createElement("img")); - this.formatButton.addEventListener("click", this._toggleFormatSourceFiles.bind(this), false); - if (Preferences.debugMode) - this.topStatusBar.appendChild(this.formatButton); - this.sidebarButtonsElement = document.createElement("div"); this.sidebarButtonsElement.id = "scripts-sidebar-buttons"; this.topStatusBar.appendChild(this.sidebarButtonsElement); @@ -142,9 +133,9 @@ WebInspector.ScriptsPanel = function() this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane(); this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(this._presentationModel); this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane(); - this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(this._presentationModel); + this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(this._presentationModel, this._showSourceLine.bind(this)); if (Preferences.nativeInstrumentationEnabled) { - this.sidebarPanes.domBreakpoints = WebInspector.createDOMBreakpointsSidebarPane(); + this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane; this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane(); this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane(); } @@ -204,11 +195,17 @@ WebInspector.ScriptsPanel = function() // Keep these in sync with WebCore::ScriptDebugServer WebInspector.ScriptsPanel.PauseOnExceptionsState = { - DontPauseOnExceptions : 0, - PauseOnAllExceptions : 1, - PauseOnUncaughtExceptions: 2 + DontPauseOnExceptions : "none", + PauseOnAllExceptions : "all", + PauseOnUncaughtExceptions: "uncaught" }; +WebInspector.ScriptsPanel.BrowserBreakpointTypes = { + DOM: "DOM", + EventListener: "EventListener", + XHR: "XHR" +} + WebInspector.ScriptsPanel.prototype = { get toolbarItemLabel() { @@ -234,6 +231,8 @@ WebInspector.ScriptsPanel.prototype = { { WebInspector.Panel.prototype.show.call(this); this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px"; + if (Preferences.nativeInstrumentationEnabled) + this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element); if (this.visibleView) this.visibleView.show(this.viewsContainerElement); @@ -280,7 +279,7 @@ WebInspector.ScriptsPanel.prototype = { var select = this._filesSelectElement; var option = document.createElement("option"); option.text = sourceFile.url ? WebInspector.displayNameForURL(sourceFile.url) : WebInspector.UIString("(program)"); - if (sourceFile.isExtensionScript) + if (sourceFile.isContentScript) option.addStyleClass("extension-script"); function optionCompare(a, b) { @@ -375,29 +374,33 @@ WebInspector.ScriptsPanel.prototype = { this.sidebarPanes.callstack.update(callFrames, details); this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame; - var status; if (details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint) { - if (details.eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.EventListener) { + if (details.eventData.breakpointType === WebInspector.ScriptsPanel.BrowserBreakpointTypes.DOM) { + this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.eventData); + function didCreateBreakpointHitStatusMessage(element) + { + this.sidebarPanes.callstack.setStatus(element); + } + this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.eventData, didCreateBreakpointHitStatusMessage.bind(this)); + } else if (details.eventData.breakpointType === WebInspector.ScriptsPanel.BrowserBreakpointTypes.EventListener) { var eventName = details.eventData.eventName; this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.eventData.eventName); var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName); - status = WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI); - } else if (details.eventData.breakpointType === WebInspector.BreakpointManager.BreakpointTypes.XHR) { + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI)); + } else if (details.eventData.breakpointType === WebInspector.ScriptsPanel.BrowserBreakpointTypes.XHR) { this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.eventData.breakpointURL); - status = WebInspector.UIString("Paused on a XMLHttpRequest."); + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest.")); } } else { - function didGetSourceLocation(sourceFileId, lineNumber, columnNumber) + function didGetSourceLocation(sourceFileId, lineNumber) { if (!sourceFileId || !this._presentationModel.findBreakpoint(sourceFileId, lineNumber)) return; this.sidebarPanes.jsBreakpoints.highlightBreakpoint(sourceFileId, lineNumber); - status = WebInspector.UIString("Paused on a JavaScript breakpoint."); + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint.")); } - callFrames[0].sourceLocation(didGetSourceLocation.bind(this)); + callFrames[0].sourceLine(didGetSourceLocation.bind(this)); } - if (status) - this.sidebarPanes.callstack.setStatus(status); window.focus(); InspectorFrontendHost.bringToFront(); @@ -414,7 +417,7 @@ WebInspector.ScriptsPanel.prototype = { _debuggerWasEnabled: function() { - this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionState); + this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionStateString); if (this._debuggerEnabled) return; @@ -478,17 +481,26 @@ WebInspector.ScriptsPanel.prototype = { x.show(this.viewsContainerElement); }, - canShowSourceLine: function(url, line) + canShowAnchorLocation: function(anchor) { - return this._debuggerEnabled && (url in this._sourceFileIdToFilesSelectOption); + return this._debuggerEnabled && this._presentationModel.sourceFileForScriptURL(anchor.href); }, - showSourceLine: function(url, line) + showAnchorLocation: function(anchor) { - if (!(url in this._sourceFileIdToFilesSelectOption)) - return; - var sourceFrame = this._showSourceFrameAndAddToHistory(url); - sourceFrame.highlightLine(line); + function didRequestSourceMapping(mapping) + { + var lineNumber = mapping.scriptLocationToSourceLine({lineNumber:anchor.getAttribute("line_number") - 1, columnNumber:0}); + this._showSourceLine(sourceFile.id, lineNumber); + } + var sourceFile = this._presentationModel.sourceFileForScriptURL(anchor.href); + sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this)); + }, + + _showSourceLine: function(sourceFileId, lineNumber) + { + var sourceFrame = this._showSourceFrameAndAddToHistory(sourceFileId); + sourceFrame.highlightLine(lineNumber); }, handleShortcut: function(event) @@ -612,7 +624,7 @@ WebInspector.ScriptsPanel.prototype = { this.sidebarPanes.watchExpressions.refreshExpressions(); this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame; - function didGetSourceLocation(sourceFileId, lineNumber, columnNumber) + function didGetSourceLocation(sourceFileId, lineNumber) { if (!sourceFileId) return; @@ -625,7 +637,7 @@ WebInspector.ScriptsPanel.prototype = { sourceFrame.setExecutionLine(lineNumber); this._executionSourceFrame = sourceFrame; } - callFrame.sourceLocation(didGetSourceLocation.bind(this)); + callFrame.sourceLine(didGetSourceLocation.bind(this)); }, _filesSelectChanged: function() @@ -672,6 +684,7 @@ WebInspector.ScriptsPanel.prototype = { _setPauseOnExceptions: function(pauseOnExceptionsState) { + pauseOnExceptionsState = pauseOnExceptionsState || WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions; function callback(error) { if (error) @@ -684,9 +697,9 @@ WebInspector.ScriptsPanel.prototype = { this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions."); this._pauseOnExceptionButton.state = pauseOnExceptionsState; - WebInspector.settings.pauseOnExceptionState = pauseOnExceptionsState; + WebInspector.settings.pauseOnExceptionStateString = pauseOnExceptionsState; } - DebuggerAgent.setPauseOnExceptionsState(pauseOnExceptionsState, callback.bind(this)); + DebuggerAgent.setPauseOnExceptions(pauseOnExceptionsState, callback.bind(this)); }, _updateDebuggerButtons: function() @@ -741,6 +754,7 @@ WebInspector.ScriptsPanel.prototype = { this.sidebarPanes.scopechain.update(null); this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight(); if (Preferences.nativeInstrumentationEnabled) { + this.sidebarPanes.domBreakpoints.clearBreakpointHighlight(); this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight(); this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight(); } @@ -771,12 +785,6 @@ WebInspector.ScriptsPanel.prototype = { this._updateBackAndForwardButtons(); }, - _toggleFormatSourceFiles: function() - { - this.reset(); - this._presentationModel.toggleFormatSourceFiles(); - }, - _enableDebugging: function() { if (this._debuggerEnabled) @@ -801,7 +809,12 @@ WebInspector.ScriptsPanel.prototype = { _togglePauseOnExceptions: function() { - this._setPauseOnExceptions((this._pauseOnExceptionButton.state + 1) % this._pauseOnExceptionButton.states); + var nextStateMap = {}; + var stateEnum = WebInspector.ScriptsPanel.PauseOnExceptionsState; + nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions; + nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions; + nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions; + this._setPauseOnExceptions(nextStateMap[this._pauseOnExceptionButton.state]); }, _togglePause: function() @@ -1008,11 +1021,7 @@ WebInspector.SourceFrameDelegateForScriptsPanel = function(model, sourceFileId) WebInspector.SourceFrameDelegateForScriptsPanel.prototype = { requestContent: function(callback) { - function didRequestSourceFileContent(mimeType, text) - { - callback(mimeType, { text: text }); - } - this._model.requestSourceFileContent(this._sourceFileId, didRequestSourceFileContent.bind(this)); + this._model.requestSourceFileContent(this._sourceFileId, callback); }, debuggingSupported: function() @@ -1076,6 +1085,17 @@ WebInspector.SourceFrameDelegateForScriptsPanel.prototype = { releaseEvaluationResult: function() { RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup); + }, + + toggleFormatSourceFiles: function() + { + WebInspector.panels.scripts.reset(); + this._model.toggleFormatSourceFiles(); + }, + + formatSourceFilesToggled: function() + { + return this._model.formatSourceFilesToggled(); } } diff --git a/Source/WebCore/inspector/front-end/SearchController.js b/Source/WebCore/inspector/front-end/SearchController.js index 735c424..d0f9cb4 100755 --- a/Source/WebCore/inspector/front-end/SearchController.js +++ b/Source/WebCore/inspector/front-end/SearchController.js @@ -84,7 +84,7 @@ WebInspector.SearchController.prototype = { var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey; if (isFindKey) { - this._focusSearchField(); + this.focusSearchField(); event.handled = true; } break; @@ -92,7 +92,7 @@ WebInspector.SearchController.prototype = { case "F3": if (!isMac) { - this._focusSearchField(); + this.focusSearchField(); event.handled = true; } break; @@ -157,7 +157,7 @@ WebInspector.SearchController.prototype = { WebInspector.toolbar.resize(); }, - _focusSearchField: function() + focusSearchField: function() { this.element.focus(); this.element.select(); diff --git a/Source/WebCore/inspector/front-end/Settings.js b/Source/WebCore/inspector/front-end/Settings.js index 9995ca2..856153a 100644 --- a/Source/WebCore/inspector/front-end/Settings.js +++ b/Source/WebCore/inspector/front-end/Settings.js @@ -72,13 +72,8 @@ WebInspector.Settings = function() this.installApplicationSetting("watchExpressions", []); this.installApplicationSetting("breakpoints", []); this.installApplicationSetting("eventListenerBreakpoints", []); + this.installApplicationSetting("domBreakpoints", []); this.installApplicationSetting("xhrBreakpoints", []); - - this.installProjectSetting("nativeBreakpoints", []); -} - -WebInspector.Settings.Events = { - ProjectChanged: "project-changed" } WebInspector.Settings.prototype = { @@ -91,47 +86,6 @@ WebInspector.Settings.prototype = { this.__defineSetter__(key, this._set.bind(this, key)); }, - installProjectSetting: function(key, defaultValue) - { - this.__defineGetter__(key, this._getProjectSetting.bind(this, key, defaultValue)); - this.__defineSetter__(key, this._setProjectSetting.bind(this, key)); - }, - - inspectedURLChanged: function(url) - { - var fragmentIndex = url.indexOf("#"); - if (fragmentIndex !== -1) - url = url.substring(0, fragmentIndex); - this._projectId = url; - this.dispatchEventToListeners(WebInspector.Settings.Events.ProjectChanged); - }, - - get projectId() - { - return this._projectId; - }, - - findSettingForAllProjects: function(key) - { - var result = {}; - if (window.localStorage == null) - return result; - - var regexp = "^" + key + ":(.*)"; - for (var i = 0; i < window.localStorage.length; ++i) { - var fullKey = window.localStorage.key(i); - var match = fullKey.match(regexp); - if (!match) - continue; - try { - result[match[1]] = JSON.parse(window.localStorage[fullKey]); - } catch(e) { - window.localStorage.removeItem(fullKey); - } - } - return result; - }, - _get: function(key, defaultValue) { if (window.localStorage != null && key in window.localStorage) { @@ -148,21 +102,6 @@ WebInspector.Settings.prototype = { { if (window.localStorage != null) window.localStorage[key] = JSON.stringify(value); - }, - - _getProjectSetting: function(key, defaultValue) - { - return this._get(this._formatProjectKey(key), defaultValue); - }, - - _setProjectSetting: function(key, value) - { - return this._set(this._formatProjectKey(key), value); - }, - - _formatProjectKey: function(key) - { - return key + ":" + this._projectId; } } diff --git a/Source/WebCore/inspector/front-end/SourceFile.js b/Source/WebCore/inspector/front-end/SourceFile.js index 4f56c00..c58a0c7 100644 --- a/Source/WebCore/inspector/front-end/SourceFile.js +++ b/Source/WebCore/inspector/front-end/SourceFile.js @@ -38,7 +38,7 @@ WebInspector.SourceFile = function(id, script, contentChangedDelegate) this.id = id; this.url = script.sourceURL; - this.isExtensionScript = script.worldType === WebInspector.Script.WorldType.EXTENSIONS_WORLD; + this.isContentScript = script.isContentScript; this.messages = []; this.breakpoints = {}; @@ -68,6 +68,12 @@ WebInspector.SourceFile.prototype = { return this._content; }, + set content(content) + { + // FIXME: move live edit implementation to SourceFile and remove this setter. + this._content = content; + }, + requestSourceMapping: function(callback) { if (!this._mapping) @@ -126,6 +132,11 @@ WebInspector.SourceFile.prototype = { { function didRequestContent(text) { + if (!text) { + this._loadAndConcatenateScriptsContent(); + return; + } + if (resource.type === WebInspector.Resource.Type.Script) this._didRequestContent("text/javascript", text); else { @@ -150,7 +161,11 @@ WebInspector.SourceFile.prototype = { function didRequestSource(source) { sources.push(source); - if (sources.length === scripts.length) + if (sources.length < scripts.length) + return; + if (scripts.length === 1 && !scripts[0].lineOffset && !scripts[0].columnOffset) + this._didRequestContent("text/javascript", source); + else this._concatenateScriptsContent(scripts, sources); } for (var i = 0; i < scripts.length; ++i) @@ -248,18 +263,24 @@ WebInspector.FormattedSourceFile.prototype = { WebInspector.FormattedSourceFile.prototype.__proto__ = WebInspector.SourceFile.prototype; -WebInspector.SourceMapping = function(sortedScripts) +WebInspector.SourceMapping = function(scripts) { - this._sortedScripts = sortedScripts; + this._sortedScripts = scripts.slice(); + this._sortedScripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; }); } WebInspector.SourceMapping.prototype = { - scriptLocationToSourceLocation: function(lineNumber, columnNumber) + scriptLocationToSourceLine: function(location) { - return { lineNumber: lineNumber, columnNumber: columnNumber }; + return location.lineNumber; }, - sourceLocationToScriptLocation: function(lineNumber, columnNumber) + sourceLineToScriptLocation: function(lineNumber) + { + return this._sourceLocationToScriptLocation(lineNumber, 0); + }, + + _sourceLocationToScriptLocation: function(lineNumber, columnNumber) { var closestScript = this._sortedScripts[0]; for (var i = 1; i < this._sortedScripts.length; ++i) { @@ -268,43 +289,34 @@ WebInspector.SourceMapping.prototype = { break; closestScript = script; } - return { scriptId: closestScript.sourceID, lineNumber: lineNumber, columnNumber: columnNumber }; + return { sourceID: closestScript.sourceID, lineNumber: lineNumber, columnNumber: columnNumber }; } } -WebInspector.FormattedSourceMapping = function(sortedScripts, originalText, formattedText, mapping) +WebInspector.FormattedSourceMapping = function(scripts, originalText, formattedText, mapping) { - WebInspector.SourceMapping.call(this, sortedScripts); + WebInspector.SourceMapping.call(this, scripts); this._originalLineEndings = originalText.lineEndings(); this._formattedLineEndings = formattedText.lineEndings(); this._mapping = mapping; } WebInspector.FormattedSourceMapping.prototype = { - scriptLocationToSourceLocation: function(lineNumber, columnNumber) + scriptLocationToSourceLine: function(location) { - var originalPosition = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber); - var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition); - return WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition); + var originalPosition = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, location); + var index = this._mapping.original.upperBound(originalPosition - 1); + var formattedPosition = this._mapping.formatted[index]; + return WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition).lineNumber; }, - sourceLocationToScriptLocation: function(lineNumber, columnNumber) + sourceLineToScriptLocation: function(lineNumber) { - var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber); - var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition); + var formattedPosition = WebInspector.ScriptFormatter.lineToPosition(this._formattedLineEndings, lineNumber); + var index = this._mapping.formatted.upperBound(formattedPosition - 1); + var originalPosition = this._mapping.original[index]; var originalLocation = WebInspector.ScriptFormatter.positionToLocation(this._originalLineEndings, originalPosition); - return WebInspector.SourceMapping.prototype.sourceLocationToScriptLocation.call(this, originalLocation.lineNumber, originalLocation.columnNumber); - }, - - _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; + return WebInspector.SourceMapping.prototype._sourceLocationToScriptLocation.call(this, originalLocation.lineNumber, originalLocation.columnNumber); } } diff --git a/Source/WebCore/inspector/front-end/SourceFrame.js b/Source/WebCore/inspector/front-end/SourceFrame.js index 7482f34..fda3e0c 100644 --- a/Source/WebCore/inspector/front-end/SourceFrame.js +++ b/Source/WebCore/inspector/front-end/SourceFrame.js @@ -30,9 +30,7 @@ WebInspector.SourceFrame = function(delegate, url) { - WebInspector.View.call(this); - - this.element.addStyleClass("script-view"); + WebInspector.TextViewerDelegate.call(this); this._delegate = delegate; this._url = url; @@ -40,6 +38,10 @@ WebInspector.SourceFrame = function(delegate, url) this._textModel = new WebInspector.TextEditorModel(); this._textModel.replaceTabsWithSpaces = true; + this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url, this); + this._textViewer.element.addStyleClass("script-view"); + this._visible = false; + this._currentSearchResultIndex = -1; this._searchResults = []; @@ -47,8 +49,7 @@ WebInspector.SourceFrame = function(delegate, url) this._rowMessages = {}; this._messageBubbles = {}; - this._registerShortcuts(); - this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + this._breakpoints = {}; } WebInspector.SourceFrame.Events = { @@ -56,39 +57,54 @@ WebInspector.SourceFrame.Events = { } WebInspector.SourceFrame.prototype = { + get visible() + { + return this._textViewer.visible; + }, + + set visible(x) + { + this._textViewer.visible = x; + }, show: function(parentElement) { - WebInspector.View.prototype.show.call(this, parentElement); + this._ensureContentLoaded(); - if (!this._contentRequested) { - this._contentRequested = true; - this._delegate.requestContent(this._createTextViewer.bind(this)); - } + this._textViewer.show(parentElement); + this._textViewer.resize(); - if (this._textViewer) { + if (this.loaded) { if (this._scrollTop) this._textViewer.scrollTop = this._scrollTop; if (this._scrollLeft) this._textViewer.scrollLeft = this._scrollLeft; - this._textViewer.resize(); } }, hide: function() { - if (this._textViewer) { + if (this.loaded) { this._scrollTop = this._textViewer.scrollTop; this._scrollLeft = this._textViewer.scrollLeft; this._textViewer.freeCachedElements(); } - WebInspector.View.prototype.hide.call(this); - + this._textViewer.hide(); this._hidePopup(); this._clearLineHighlight(); }, + detach: function() + { + this._textViewer.detach(); + }, + + get element() + { + return this._textViewer.element; + }, + get loaded() { return !!this._content; @@ -99,28 +115,33 @@ WebInspector.SourceFrame.prototype = { return true; }, + _ensureContentLoaded: function() + { + if (!this._contentRequested) { + this._contentRequested = true; + this.requestContent(this._initializeTextViewer.bind(this)); + } + }, + + requestContent: function(callback) + { + this._delegate.requestContent(callback); + }, + markDiff: function(diffData) { - if (this._diffLines && this._textViewer) + if (this._diffLines && this.loaded) this._removeDiffDecorations(); this._diffLines = diffData; - if (this._textViewer) + if (this.loaded) this._updateDiffDecorations(); }, - revealLine: function(lineNumber) - { - if (this._textViewer) - this._textViewer.revealLine(lineNumber - 1, 0); - else - this._lineNumberToReveal = lineNumber; - }, - addMessage: function(msg) { this._messages.push(msg); - if (this._textViewer) + if (this.loaded) this.addMessageToSource(msg.line - 1, msg); }, @@ -134,8 +155,8 @@ WebInspector.SourceFrame.prototype = { this._messages = []; this._rowMessages = {}; this._messageBubbles = {}; - if (this._textViewer) - this._textViewer.resize(); + + this._textViewer.resize(); }, get textModel() @@ -145,36 +166,87 @@ WebInspector.SourceFrame.prototype = { get scrollTop() { - return this._textViewer ? this._textViewer.scrollTop : this._scrollTop; + return this.loaded ? this._textViewer.scrollTop : this._scrollTop; }, set scrollTop(scrollTop) { this._scrollTop = scrollTop; - if (this._textViewer) + if (this.loaded) this._textViewer.scrollTop = scrollTop; }, highlightLine: function(line) { - if (this._textViewer) - this._textViewer.highlightLine(line - 1); + if (this.loaded) + this._textViewer.highlightLine(line); else this._lineToHighlight = line; }, _clearLineHighlight: function() { - if (this._textViewer) + if (this.loaded) this._textViewer.clearLineHighlight(); else delete this._lineToHighlight; }, - _startEditing: function() + _saveViewerState: function() { - if (this._originalTextModelContent === undefined) { - this._originalTextModelContent = this._textModel.text; + this._viewerState = { + textModelContent: this._textModel.text, + executionLineNumber: this._executionLineNumber, + messages: this._messages, + diffLines: this._diffLines, + breakpoints: this._breakpoints + }; + }, + + _restoreViewerState: function() + { + if (!this._viewerState) + return; + this._textModel.setText(null, this._viewerState.textModelContent); + + this._messages = this._viewerState.messages; + this._diffLines = this._viewerState.diffLines; + this._setTextViewerDecorations(); + + if (typeof this._viewerState.executionLineNumber === "number") { + this.clearExecutionLine(); + this.setExecutionLine(this._viewerState.executionLineNumber); + } + + var oldBreakpoints = this._breakpoints; + this._breakpoints = {}; + for (var lineNumber in oldBreakpoints) + this.removeBreakpoint(Number(lineNumber)); + + var newBreakpoints = this._viewerState.breakpoints; + for (var lineNumber in newBreakpoints) { + lineNumber = Number(lineNumber); + var breakpoint = newBreakpoints[lineNumber]; + this.addBreakpoint(lineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled); + } + + delete this._viewerState; + }, + + isContentEditable: function() + { + return this._delegate.canEditScriptSource(); + }, + + readOnlyStateChanged: function(readOnly) + { + WebInspector.markBeingEdited(this._textViewer.element, !readOnly); + }, + + startEditing: function() + { + if (!this._viewerState) { + this._saveViewerState(); this._delegate.setScriptSourceIsBeingEdited(true); } @@ -182,19 +254,61 @@ WebInspector.SourceFrame.prototype = { this.clearMessages(); }, - _endEditing: function(oldRange, newRange) + endEditing: function(oldRange, newRange) { - // FIXME: Implement this. + if (!oldRange || !newRange) + return; + + // Adjust execution line number. + if (typeof this._executionLineNumber === "number") { + var newExecutionLineNumber = this._lineNumberAfterEditing(this._executionLineNumber, oldRange, newRange); + this.clearExecutionLine(); + this.setExecutionLine(newExecutionLineNumber, true); + } + + // Adjust breakpoints. + var oldBreakpoints = this._breakpoints; + this._breakpoints = {}; + for (var lineNumber in oldBreakpoints) { + lineNumber = Number(lineNumber); + var breakpoint = oldBreakpoints[lineNumber]; + var newLineNumber = this._lineNumberAfterEditing(lineNumber, oldRange, newRange); + if (lineNumber === newLineNumber) + this._breakpoints[lineNumber] = breakpoint; + else { + this.removeBreakpoint(lineNumber); + this.addBreakpoint(newLineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled); + } + } }, - _createTextViewer: function(mimeType, content) + _lineNumberAfterEditing: function(lineNumber, oldRange, newRange) { - this._content = content; - this._textModel.setText(null, content.text); + var shiftOffset = lineNumber <= oldRange.startLine ? 0 : newRange.linesCount - oldRange.linesCount; + + // Special case of editing the line itself. We should decide whether the line number should move below or not. + if (lineNumber === oldRange.startLine) { + var whiteSpacesRegex = /^[\s\xA0]*$/; + for (var i = 0; lineNumber + i <= newRange.endLine; ++i) { + if (!whiteSpacesRegex.test(this._textModel.line(lineNumber + i))) { + shiftOffset = i; + break; + } + } + } - 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 newLineNumber = Math.max(0, lineNumber + shiftOffset); + if (oldRange.startLine < lineNumber && lineNumber < oldRange.endLine) + newLineNumber = oldRange.startLine; + return newLineNumber; + }, + + _initializeTextViewer: function(mimeType, content) + { + this._textViewer.mimeType = mimeType; + + this._content = content; + this._textModel.setText(null, content); var element = this._textViewer.element; if (this._delegate.debuggingSupported()) { @@ -204,24 +318,13 @@ WebInspector.SourceFrame.prototype = { element.addEventListener("scroll", this._scroll.bind(this), true); } - if (this._delegate.canEditScriptSource()) - element.addEventListener("dblclick", this._doubleClick.bind(this), true); - - this.element.appendChild(element); - this._textViewer.beginUpdates(); - this._textViewer.mimeType = mimeType; this._setTextViewerDecorations(); - if ("_executionLineNumber" in this) + if (typeof this._executionLineNumber === "number") this.setExecutionLine(this._executionLineNumber); - if (this._lineNumberToReveal) { - this.revealLine(this._lineNumberToReveal); - delete this._lineNumberToReveal; - } - if (this._lineToHighlight) { this.highlightLine(this._lineToHighlight); delete this._lineToHighlight; @@ -235,6 +338,9 @@ WebInspector.SourceFrame.prototype = { this.dispatchEventToListeners(WebInspector.SourceFrame.Events.Loaded); this._textViewer.endUpdates(); + + if (this._parentElement) + this.show(this._parentElement) }, _setTextViewerDecorations: function() @@ -277,17 +383,18 @@ WebInspector.SourceFrame.prototype = { callback(this, this._searchResults.length); } - if (this._textViewer) + if (this.loaded) doFindSearchMatches.call(this, query); else this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query); + this._ensureContentLoaded(); }, searchCanceled: function() { delete this._delayedFindSearchMatches; - if (!this._textViewer) + if (!this.loaded) return; this._currentSearchResultIndex = -1; @@ -327,7 +434,7 @@ WebInspector.SourceFrame.prototype = { _jumpToSearchResult: function(index) { - if (!this._textViewer || !this._searchResults.length) + if (!this.loaded || !this._searchResults.length) return; this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length; this._textViewer.markAndRevealRange(this._searchResults[this._currentSearchResultIndex]); @@ -365,18 +472,19 @@ WebInspector.SourceFrame.prototype = { msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount); }, - setExecutionLine: function(lineNumber) + setExecutionLine: function(lineNumber, skipRevealLine) { this._executionLineNumber = lineNumber; - if (this._textViewer) { + if (this.loaded) { this._textViewer.addDecoration(lineNumber, "webkit-execution-line"); - this._textViewer.revealLine(lineNumber); + if (!skipRevealLine) + this._textViewer.revealLine(lineNumber); } }, clearExecutionLine: function() { - if (this._textViewer) + if (this.loaded) this._textViewer.removeDecoration(this._executionLineNumber, "webkit-execution-line"); delete this._executionLineNumber; }, @@ -418,7 +526,9 @@ WebInspector.SourceFrame.prototype = { addMessageToSource: function(lineNumber, msg) { if (lineNumber >= this._textModel.linesCount) - return; + lineNumber = this._textModel.linesCount - 1; + if (lineNumber < 0) + lineNumber = 0; var messageBubbleElement = this._messageBubbles[lineNumber]; if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) { @@ -471,6 +581,11 @@ WebInspector.SourceFrame.prototype = { addBreakpoint: function(lineNumber, resolved, conditional, enabled) { + this._breakpoints[lineNumber] = { + resolved: resolved, + conditional: conditional, + enabled: enabled + }; this._textViewer.beginUpdates(); this._textViewer.addDecoration(lineNumber, "webkit-breakpoint"); if (!enabled) @@ -482,6 +597,7 @@ WebInspector.SourceFrame.prototype = { removeBreakpoint: function(lineNumber) { + delete this._breakpoints[lineNumber]; this._textViewer.beginUpdates(); this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint"); this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled"); @@ -491,13 +607,17 @@ WebInspector.SourceFrame.prototype = { _contextMenu: function(event) { - var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); - if (!target) - return; - var lineNumber = target.lineNumber; - var contextMenu = new WebInspector.ContextMenu(); + var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); + if (target) + this._populateLineGutterContextMenu(target.lineNumber, contextMenu); + else + this._populateTextAreaContextMenu(contextMenu); + contextMenu.show(event); + }, + _populateLineGutterContextMenu: function(lineNumber, contextMenu) + { contextMenu.appendItem(WebInspector.UIString("Continue to Here"), this._delegate.continueToLine.bind(this._delegate, lineNumber)); var breakpoint = this._delegate.findBreakpoint(lineNumber); @@ -539,7 +659,11 @@ WebInspector.SourceFrame.prototype = { else contextMenu.appendItem(WebInspector.UIString("Enable Breakpoint"), setBreakpointEnabled.bind(this, true)); } - contextMenu.show(event); + }, + + _populateTextAreaContextMenu: function(contextMenu) + { + contextMenu.appendCheckboxItem(WebInspector.UIString("De-obfuscate Source"), this._delegate.toggleFormatSourceFiles.bind(this._delegate), this._delegate.formatSourceFilesToggled()); }, _scroll: function(event) @@ -764,107 +888,64 @@ WebInspector.SourceFrame.prototype = { resize: function() { - if (this._textViewer) - this._textViewer.resize(); + this._textViewer.resize(); }, - formatSource: function() + commitEditing: function(callback) { - if (!this._content) + if (!this._viewerState) { + // No editing was actually done. + this._delegate.setScriptSourceIsBeingEdited(false); + callback(); return; + } - function didFormat(formattedContent) + function didEditContent(error) { - this._content = formattedContent; - this._textModel.setText(null, formattedContent.text); - this._setTextViewerDecorations(); - } - var formatter = new WebInspector.ScriptFormatter(); - formatter.formatContent(this._content, didFormat.bind(this)) - }, + if (error) { + if (error.data && error.data[0]) { + WebInspector.log(error.data[0], WebInspector.ConsoleMessage.MessageLevel.Error); + WebInspector.showConsole(); + } + callback(error); + return; + } - _registerShortcuts: function() - { - this._shortcuts = {}; - var handleSaveCallback = this._handleSave.bind(this); - this._shortcuts[WebInspector.KeyboardShortcut.makeKey("s", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)] = handleSaveCallback; - this._shortcuts[WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.Keys.Enter.code, WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta)] = handleSaveCallback; - this._shortcuts[WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.Keys.Esc.code)] = this._handleRevertEditing.bind(this); - }, + var newBreakpoints = {}; + for (var lineNumber in this._breakpoints) { + newBreakpoints[lineNumber] = this._breakpoints[lineNumber]; + this.removeBreakpoint(Number(lineNumber)); + } - _handleKeyDown: function(e) - { - var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e); - var handler = this._shortcuts[shortcutKey]; - if (handler && handler.call(this)) { - e.preventDefault(); - e.stopPropagation(); - } - }, + for (var lineNumber in this._viewerState.breakpoints) + this._delegate.removeBreakpoint(Number(lineNumber)); - _handleSave: function() - { - if (this._textViewer.readOnly || !this._delegate.canEditScriptSource()) - return false; + for (var lineNumber in newBreakpoints) { + var breakpoint = newBreakpoints[lineNumber]; + this._delegate.setBreakpoint(Number(lineNumber), breakpoint.condition, breakpoint.enabled); + } - if (this._originalTextModelContent === undefined) { - // No editing was actually done. - this._textViewer.readOnly = true; + delete this._viewerState; this._delegate.setScriptSourceIsBeingEdited(false); - return true; - } - - var originalTextModelContent = this._originalTextModelContent; - var newSource = this._textModel.text; - - delete this._originalTextModelContent; - this._textViewer.readOnly = true; - this._delegate.setScriptSourceIsBeingEdited(false); - function didEditScriptSource(success, newBodyOrErrorMessage) - { - if (!success && this._originalTextModelContent === undefined && this._textModel.text === newSource) { - this._originalTextModelContent = originalTextModelContent; - this._textViewer.readOnly = false; - this._delegate.setScriptSourceIsBeingEdited(true); - WebInspector.log(newBodyOrErrorMessage, WebInspector.ConsoleMessage.MessageLevel.Error); - WebInspector.showConsole(); - } + callback(); } - this._delegate.editScriptSource(newSource, didEditScriptSource.bind(this)); - return true; + this.editContent(this._textModel.text, didEditContent.bind(this)); }, - _handleRevertEditing: function() + editContent: function(newContent, callback) { - if (this._textViewer.readOnly) - return false; - - if (this._originalTextModelContent !== undefined) - this._textModel.setText(null, this._originalTextModelContent); - delete this._originalTextModelContent; - this._textViewer.readOnly = true; - this._delegate.setScriptSourceIsBeingEdited(false); - return true; + this._delegate.editScriptSource(newContent, callback); }, - _doubleClick: function(event) + cancelEditing: function() { - if (!this._delegate.canEditScriptSource()) - return; - - var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content"); - if (!lineRow) - return; // Do not trigger editing from line numbers. - - if (this._textViewer.readOnly) { - this._textViewer.readOnly = false; - window.getSelection().collapseToStart(); - } + this._restoreViewerState(); + this._delegate.setScriptSourceIsBeingEdited(false); } } -WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype; +WebInspector.SourceFrame.prototype.__proto__ = WebInspector.TextViewerDelegate.prototype; WebInspector.SourceFrameDelegate = function() @@ -935,5 +1016,15 @@ WebInspector.SourceFrameDelegate.prototype = { releaseEvaluationResult: function() { // Should be implemented by subclasses. + }, + + toggleFormatSourceFiles: function() + { + // Should be implemented by subclasses. + }, + + formatSourceFilesToggled: function() + { + // Should be implemented by subclasses. } } diff --git a/Source/WebCore/inspector/front-end/SourceFrameContent.js b/Source/WebCore/inspector/front-end/SourceFrameContent.js deleted file mode 100644 index 3f3a8e9..0000000 --- a/Source/WebCore/inspector/front-end/SourceFrameContent.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.SourceFrameContent = function(text, mapping, scriptRanges) -{ - this._text = text; - this._mapping = mapping; - this._scriptRanges = scriptRanges; -} - -WebInspector.SourceFrameContent.prototype = { - get text() - { - return this._text; - }, - - get scriptRanges() - { - return this._scriptRanges; - }, - - sourceFrameLineNumberToActualLocation: function(lineNumber) - { - var location = this._mapping.sourceLocationToActualLocation(lineNumber, 0); - location.sourceID = this._sourceIDForSourceFrameLineNumber(lineNumber); - return location; - }, - - actualLocationToSourceFrameLineNumber: function(lineNumber, columnNumber) - { - return this._mapping.actualLocationToSourceLocation(lineNumber, columnNumber).lineNumber; - }, - - _sourceIDForSourceFrameLineNumber: function(lineNumber) - { - for (var i = 0; i < this._scriptRanges.length; ++i) { - var scriptRange = this._scriptRanges[i]; - 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.SourceMapping = function() -{ -} - -WebInspector.SourceMapping.prototype = { - actualLocationToSourceLocation: function(lineNumber, columnNumber) - { - // Should be implemented by subclasses. - }, - - sourceLocationToActualLocation: function(lineNumber, columnNumber) - { - // Should be implemented by subclasses. - } -} - - -WebInspector.IdenticalSourceMapping = function() -{ - WebInspector.SourceMapping.call(this); -} - -WebInspector.IdenticalSourceMapping.prototype = { - actualLocationToSourceLocation: function(lineNumber, columnNumber) - { - return { lineNumber: lineNumber, columnNumber: columnNumber}; - }, - - sourceLocationToActualLocation: function(lineNumber, columnNumber) - { - return { lineNumber: lineNumber, columnNumber: columnNumber}; - } -} - -WebInspector.IdenticalSourceMapping.prototype.__proto__ = WebInspector.SourceMapping.prototype; diff --git a/Source/WebCore/inspector/front-end/StylesSidebarPane.js b/Source/WebCore/inspector/front-end/StylesSidebarPane.js index 29d0317..a662008 100644 --- a/Source/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/Source/WebCore/inspector/front-end/StylesSidebarPane.js @@ -503,7 +503,7 @@ WebInspector.StylesSidebarPane.prototype = { addBlankSection: function() { - var blankSection = new WebInspector.BlankStylePropertiesSection(this, appropriateSelectorForNode(this.node, true)); + var blankSection = new WebInspector.BlankStylePropertiesSection(this, this.node ? this.node.appropriateSelectorFor(true) : ""); blankSection.pane = this; var elementStyleSection = this.sections[0][1]; @@ -635,8 +635,6 @@ WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, function linkifyUncopyable(url, line) { var link = WebInspector.linkifyResourceAsNode(url, "resources", line + 1); - link.setAttribute("data-uncopyable", link.textContent); - link.textContent = ""; return link; } @@ -1643,47 +1641,29 @@ WebInspector.StylePropertyTreeElement.prototype = { var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this.valueElement); var wordString = wordRange.toString(); - var replacementString = wordString; + var replacementString; + var prefix, suffix, number; - var matches = /(.*?)(-?\d+(?:\.\d+)?)(.*)/.exec(wordString); + var matches; + matches = /(.*#)([\da-fA-F]+)(.*)/.exec(wordString); if (matches && matches.length) { - var prefix = matches[1]; - var number = parseFloat(matches[2]); - var suffix = matches[3]; - - // If the number is near zero or the number is one and the direction will take it near zero. - var numberNearZero = (number < 1 && number > -1); - if (number === 1 && event.keyIdentifier === "Down") - numberNearZero = true; - else if (number === -1 && event.keyIdentifier === "Up") - numberNearZero = true; - - if (numberNearZero && event.altKey && arrowKeyPressed) { - if (event.keyIdentifier === "Down") - number = Math.ceil(number - 1); - else - number = Math.floor(number + 1); - } else { - // Jump by 10 when shift is down or jump by 0.1 when near zero or Alt/Option is down. - // Also jump by 10 for page up and down, or by 100 if shift is held with a page key. - var changeAmount = 1; - if (event.shiftKey && pageKeyPressed) - changeAmount = 100; - else if (event.shiftKey || pageKeyPressed) - changeAmount = 10; - else if (event.altKey || numberNearZero) - changeAmount = 0.1; - - if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown") - changeAmount *= -1; - - // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns. - // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1. - number = Number((number + changeAmount).toFixed(6)); - } + prefix = matches[1]; + suffix = matches[3]; + number = this._alteredHexNumber(matches[2], event); replacementString = prefix + number + suffix; + } else { + matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString); + if (matches && matches.length) { + prefix = matches[1]; + suffix = matches[3]; + number = this._alteredFloatNumber(parseFloat(matches[2]), event); + replacementString = prefix + number + suffix; + } + } + + if (replacementString) { var replacementTextNode = document.createTextNode(replacementString); wordRange.deleteContents(); @@ -1710,6 +1690,75 @@ WebInspector.StylePropertyTreeElement.prototype = { } }, + _alteredFloatNumber: function(number, event) + { + var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); + // If the number is near zero or the number is one and the direction will take it near zero. + var numberNearZero = (number < 1 && number > -1); + if (number === 1 && event.keyIdentifier === "Down") + numberNearZero = true; + else if (number === -1 && event.keyIdentifier === "Up") + numberNearZero = true; + + var result; + if (numberNearZero && event.altKey && arrowKeyPressed) { + if (event.keyIdentifier === "Down") + result = Math.ceil(number - 1); + else + result = Math.floor(number + 1); + } else { + // Jump by 10 when shift is down or jump by 0.1 when near zero or Alt/Option is down. + // Also jump by 10 for page up and down, or by 100 if shift is held with a page key. + var changeAmount = 1; + if (event.shiftKey && !arrowKeyPressed) + changeAmount = 100; + else if (event.shiftKey || !arrowKeyPressed) + changeAmount = 10; + else if (event.altKey || numberNearZero) + changeAmount = 0.1; + + if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown") + changeAmount *= -1; + + // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns. + // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1. + result = Number((number + changeAmount).toFixed(6)); + } + + return result; + }, + + _alteredHexNumber: function(hexString, event) + { + var number = parseInt(hexString, 16); + if (isNaN(number) || !isFinite(number)) + return hexString; + + var maxValue = Math.pow(16, hexString.length) - 1; + var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); + + var delta; + if (arrowKeyPressed) + delta = (event.keyIdentifier === "Up") ? 1 : -1; + else + delta = (event.keyIdentifier === "PageUp") ? 16 : -16; + + if (event.shiftKey) + delta *= 16; + + var result = number + delta; + if (result < 0) + result = 0; // Color hex values are never negative, so clamp to 0. + else if (result > maxValue) + return hexString; + + // Ensure the result length is the same as the original hex value. + var resultString = result.toString(16).toUpperCase(); + for (var i = 0, lengthDelta = hexString.length - resultString.length; i < lengthDelta; ++i) + resultString = "0" + resultString; + return resultString; + }, + editingEnded: function(context) { this.hasChildren = context.hasChildren; diff --git a/Source/WebCore/inspector/front-end/TestController.js b/Source/WebCore/inspector/front-end/TestController.js index e6783f9..301994c 100644 --- a/Source/WebCore/inspector/front-end/TestController.js +++ b/Source/WebCore/inspector/front-end/TestController.js @@ -36,7 +36,7 @@ WebInspector.TestController.prototype = { notifyDone: function(callId, result) { var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result); - InspectorAgent.didEvaluateForTestInFrontend(callId, message); + RuntimeAgent.evaluate("didEvaluateForTestInFrontend(" + callId + ", " + message + ")", "test"); } } diff --git a/Source/WebCore/inspector/front-end/TextEditorModel.js b/Source/WebCore/inspector/front-end/TextEditorModel.js index b14a3b7..47c53d7 100644 --- a/Source/WebCore/inspector/front-end/TextEditorModel.js +++ b/Source/WebCore/inspector/front-end/TextEditorModel.js @@ -59,6 +59,7 @@ WebInspector.TextEditorModel = function() this._attributes = []; this._undoStack = []; this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/; + this._lineBreak = "\n"; } WebInspector.TextEditorModel.prototype = { @@ -74,7 +75,7 @@ WebInspector.TextEditorModel.prototype = { get text() { - return this._lines.join("\n"); + return this._lines.join(this._lineBreak); }, line: function(lineNumber) @@ -91,9 +92,12 @@ WebInspector.TextEditorModel.prototype = { setText: function(range, text) { - if (!range) + text = text || ""; + if (!range) { range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length); - var command = this._pushUndoableCommand(range, text); + this._lineBreak = /\r\n/.test(text) ? "\r\n" : "\n"; + } + var command = this._pushUndoableCommand(range); var newRange = this._innerSetText(range, text); command.range = newRange.clone(); @@ -113,11 +117,10 @@ WebInspector.TextEditorModel.prototype = { if (text === "") return new WebInspector.TextRange(range.startLine, range.startColumn, range.startLine, range.startColumn); - var newLines = text.split("\n"); + var newLines = text.split(/\r?\n/); this._replaceTabsIfNeeded(newLines); var prefix = this._lines[range.startLine].substring(0, range.startColumn); - var prefixArguments = this._arguments var suffix = this._lines[range.startLine].substring(range.startColumn); var postCaret = prefix.length; @@ -211,13 +214,13 @@ WebInspector.TextEditorModel.prototype = { var clip = []; if (range.startLine === range.endLine) { clip.push(this._lines[range.startLine].substring(range.startColumn, range.endColumn)); - return clip.join("\n"); + return clip.join(this._lineBreak); } clip.push(this._lines[range.startLine].substring(range.startColumn)); for (var i = range.startLine + 1; i < range.endLine; ++i) clip.push(this._lines[i]); clip.push(this._lines[range.endLine].substring(0, range.endColumn)); - return clip.join("\n"); + return clip.join(this._lineBreak); }, setAttribute: function(line, name, value) @@ -243,7 +246,7 @@ WebInspector.TextEditorModel.prototype = { delete attrs[name]; }, - _pushUndoableCommand: function(range, text) + _pushUndoableCommand: function(range) { var command = { text: this.copyRange(range), @@ -262,29 +265,29 @@ WebInspector.TextEditorModel.prototype = { return command; }, - undo: function() + undo: function(callback) { this._markRedoableState(); this._inUndo = true; - var range = this._doUndo(this._undoStack); + var range = this._doUndo(this._undoStack, callback); delete this._inUndo; return range; }, - redo: function() + redo: function(callback) { this.markUndoableState(); this._inRedo = true; - var range = this._doUndo(this._redoStack); + var range = this._doUndo(this._redoStack, callback); delete this._inRedo; return range; }, - _doUndo: function(stack) + _doUndo: function(stack, callback) { var range = null; for (var i = stack.length - 1; i >= 0; --i) { @@ -292,6 +295,8 @@ WebInspector.TextEditorModel.prototype = { stack.length = i; range = this.setText(command.range, command.text); + if (callback) + callback(command.range, range); if (i > 0 && stack[i - 1].explicit) return range; } diff --git a/Source/WebCore/inspector/front-end/TextViewer.js b/Source/WebCore/inspector/front-end/TextViewer.js index 43b34f6..1b40b3e 100644 --- a/Source/WebCore/inspector/front-end/TextViewer.js +++ b/Source/WebCore/inspector/front-end/TextViewer.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. All rights reserved. * Copyright (C) 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,12 +29,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.TextViewer = function(textModel, platform, url) +WebInspector.TextViewer = function(textModel, platform, url, delegate) { + WebInspector.View.call(this); + this._textModel = textModel; this._textModel.changeListener = this._textChanged.bind(this); + this._textModel.resetUndoStack(); + this._delegate = delegate; - this.element = document.createElement("div"); this.element.className = "text-editor monospace"; var enterTextChangeMode = this._enterInternalTextChangeMode.bind(this); @@ -49,7 +52,12 @@ WebInspector.TextViewer = function(textModel, platform, url) // Forward mouse wheel events from the unscrollable gutter to the main panel. this._gutterPanel.element.addEventListener("mousewheel", function(e) { this._mainPanel.element.dispatchEvent(e); - }.bind(this), false) + }.bind(this), false); + + this.element.addEventListener("dblclick", this._doubleClick.bind(this), true); + this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + + this._registerShortcuts(); } WebInspector.TextViewer.prototype = { @@ -60,7 +68,10 @@ WebInspector.TextViewer.prototype = { set readOnly(readOnly) { + if (this._mainPanel.readOnly === readOnly) + return; this._mainPanel.readOnly = readOnly; + this._delegate.readOnlyStateChanged(readOnly); }, get readOnly() @@ -68,16 +79,6 @@ WebInspector.TextViewer.prototype = { return this._mainPanel.readOnly; }, - set startEditingListener(startEditingListener) - { - this._startEditingListener = startEditingListener; - }, - - set endEditingListener(endEditingListener) - { - this._endEditingListener = endEditingListener; - }, - get textModel() { return this._textModel; @@ -164,31 +165,23 @@ WebInspector.TextViewer.prototype = { // WebInspector.TextModel listener _textChanged: function(oldRange, newRange, oldText, newText) { - if (!this._internalTextChangeMode) { - this._mainPanel.textChanged(oldRange, newRange); - this._gutterPanel.textChanged(oldRange, newRange); - this._updatePanelOffsets(); - } + if (!this._internalTextChangeMode) + this._textModel.resetUndoStack(); + this._mainPanel.textChanged(oldRange, newRange); + this._gutterPanel.textChanged(oldRange, newRange); + this._updatePanelOffsets(); }, _enterInternalTextChangeMode: function() { this._internalTextChangeMode = true; - - if (this._startEditingListener) - this._startEditingListener(); + this._delegate.startEditing(); }, _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); + this._delegate.endEditing(oldRange, newRange); }, _updatePanelOffsets: function() @@ -218,7 +211,7 @@ WebInspector.TextViewer.prototype = { return; var mainChunk = this._mainPanel.chunkForLine(lineNumber); - if (mainChunk.linesCount === 1) { + if (mainChunk.linesCount === 1 && mainChunk.decorated) { var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber); var height = mainChunk.height; if (height) @@ -230,9 +223,125 @@ WebInspector.TextViewer.prototype = { if (gutterChunk.linesCount === 1) gutterChunk.element.style.removeProperty("height"); } + }, + + _doubleClick: function(event) + { + if (!this.readOnly || this._commitEditingInProgress) + return; + + var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content"); + if (!lineRow) + return; // Do not trigger editing from line numbers. + + if (!this._delegate.isContentEditable()) + return; + + this.readOnly = false; + window.getSelection().collapseToStart(); + }, + + _registerShortcuts: function() + { + var keys = WebInspector.KeyboardShortcut.Keys; + var modifiers = WebInspector.KeyboardShortcut.Modifiers; + + this._shortcuts = {}; + var commitEditing = this._commitEditing.bind(this); + var cancelEditing = this._cancelEditing.bind(this); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey("s", modifiers.CtrlOrMeta)] = commitEditing; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Enter.code, modifiers.CtrlOrMeta)] = commitEditing; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Esc.code)] = cancelEditing; + + var handleUndo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, false); + var handleRedo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, true); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.CtrlOrMeta)] = handleUndo; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.Shift | modifiers.CtrlOrMeta)] = handleRedo; + + var handleTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, false); + var handleShiftTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, true); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code)] = handleTabKey; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code, modifiers.Shift)] = handleShiftTabKey; + }, + + _handleKeyDown: function(e) + { + var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e); + var handler = this._shortcuts[shortcutKey]; + if (handler && handler.call(this)) { + e.preventDefault(); + e.stopPropagation(); + } + }, + + _commitEditing: function() + { + if (this.readOnly) + return false; + + this.readOnly = true; + function didCommitEditing(error) + { + this._commitEditingInProgress = false; + if (error) + this.readOnly = false; + } + this._commitEditingInProgress = true; + this._delegate.commitEditing(didCommitEditing.bind(this)); + return true; + }, + + _cancelEditing: function() + { + if (this.readOnly) + return false; + + this.readOnly = true; + this._delegate.cancelEditing(); + return true; } } +WebInspector.TextViewer.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.TextViewerDelegate = function() +{ +} + +WebInspector.TextViewerDelegate.prototype = { + isContentEditable: function() + { + // Should be implemented by subclasses. + }, + + readOnlyStateChanged: function(readOnly) + { + // Should be implemented by subclasses. + }, + + startEditing: function() + { + // Should be implemented by subclasses. + }, + + endEditing: function(oldRange, newRange) + { + // Should be implemented by subclasses. + }, + + commitEditing: function() + { + // Should be implemented by subclasses. + }, + + cancelEditing: function() + { + // Should be implemented by subclasses. + } +} + +WebInspector.TextViewerDelegate.prototype.__proto__ = WebInspector.Object.prototype; + WebInspector.TextEditorChunkedPanel = function(textModel) { this._textModel = textModel; @@ -259,19 +368,20 @@ WebInspector.TextEditorChunkedPanel.prototype = { addDecoration: function(lineNumber, decoration) { + if (lineNumber >= this._textModel.linesCount) + return; + var chunk = this.makeLineAChunk(lineNumber); chunk.addDecoration(decoration); }, removeDecoration: function(lineNumber, decoration) { - var chunk = this.makeLineAChunk(lineNumber); - chunk.removeDecoration(decoration); - }, + if (lineNumber >= this._textModel.linesCount) + return; - textChanged: function(oldRange, newRange) - { - this._buildChunks(); + var chunk = this.chunkForLine(lineNumber); + chunk.removeDecoration(decoration); }, _buildChunks: function() @@ -294,16 +404,19 @@ WebInspector.TextEditorChunkedPanel.prototype = { makeLineAChunk: function(lineNumber) { - if (!this._textChunks) - this._buildChunks(); - var chunkNumber = this._chunkNumberForLine(lineNumber); var oldChunk = this._textChunks[chunkNumber]; if (oldChunk.linesCount === 1) return oldChunk; + return this._splitChunkOnALine(lineNumber, chunkNumber); + }, + + _splitChunkOnALine: function(lineNumber, chunkNumber) + { this.beginDomUpdates(); + var oldChunk = this._textChunks[chunkNumber]; var wasExpanded = oldChunk.expanded; oldChunk.expanded = false; @@ -447,9 +560,6 @@ WebInspector.TextEditorChunkedPanel.prototype = { if (this._paintCoalescingLevel || this._dirtyLines) return; - if (!this._textChunks) - this._buildChunks(); - var visibleFrom = this.element.scrollTop; var visibleTo = this.element.scrollTop + this.element.clientHeight; @@ -526,10 +636,7 @@ WebInspector.TextEditorGutterPanel.prototype = { textChanged: function(oldRange, newRange) { - if (!this._textChunks) { - this._buildChunks(); - return; - } + this.beginDomUpdates(); var linesDiff = newRange.linesCount - oldRange.linesCount; if (linesDiff) { @@ -565,6 +672,8 @@ WebInspector.TextEditorGutterPanel.prototype = { chunk = this._textChunks[++chunkNumber]; } } + + this.endDomUpdates(); }, syncClientHeight: function(clientHeight) @@ -744,6 +853,9 @@ WebInspector.TextEditorMainPanel.prototype = { set readOnly(readOnly) { + if (this._readOnly === readOnly) + return; + this.beginDomUpdates(); this._readOnly = readOnly; if (this._readOnly) @@ -762,14 +874,25 @@ WebInspector.TextEditorMainPanel.prototype = { { if (this._rangeToMark) { var markedLine = this._rangeToMark.startLine; - this._rangeToMark = null; - this._paintLines(markedLine, markedLine + 1); + delete this._rangeToMark; + // Remove the marked region immediately. + if (!this._dirtyLines) { + this.beginDomUpdates(); + var chunk = this.chunkForLine(markedLine); + var wasExpanded = chunk.expanded; + chunk.expanded = false; + chunk.updateCollapsedLineRow(); + chunk.expanded = wasExpanded; + this.endDomUpdates(); + } else + this._paintLines(markedLine, markedLine + 1); } if (range) { this._rangeToMark = range; this.revealLine(range.startLine); - this._paintLines(range.startLine, range.startLine + 1); + var chunk = this.makeLineAChunk(range.startLine); + this._paintLine(chunk.element); if (this._markedRangeElement) this._markedRangeElement.scrollIntoViewIfNeeded(); } @@ -799,6 +922,65 @@ WebInspector.TextEditorMainPanel.prototype = { this._cachedRows = []; }, + handleUndoRedo: function(redo) + { + if (this._readOnly || this._dirtyLines) + return false; + + this.beginUpdates(); + this._enterTextChangeMode(); + + var callback = function(oldRange, newRange) { + this._exitTextChangeMode(oldRange, newRange); + this._enterTextChangeMode(); + }.bind(this); + + var range = redo ? this._textModel.redo(callback) : this._textModel.undo(callback); + if (range) + this._setCaretLocation(range.endLine, range.endColumn, true); + + this._exitTextChangeMode(null, null); + this.endUpdates(); + + return true; + }, + + handleTabKeyPress: function(shiftKey) + { + if (this._readOnly || this._dirtyLines) + return false; + + var selection = this._getSelection(); + if (!selection) + return false; + + if (shiftKey) + return true; + + this.beginUpdates(); + this._enterTextChangeMode(); + + var range = selection; + if (range.startLine > range.endLine || (range.startLine === range.endLine && range.startColumn > range.endColumn)) + range = new WebInspector.TextRange(range.endLine, range.endColumn, range.startLine, range.startColumn); + + var newRange = this._setText(range, "\t"); + + this._exitTextChangeMode(range, newRange); + this.endUpdates(); + + this._setCaretLocation(newRange.endLine, newRange.endColumn, true); + return true; + }, + + _splitChunkOnALine: function(lineNumber, chunkNumber) + { + var selection = this._getSelection(); + var chunk = WebInspector.TextEditorChunkedPanel.prototype._splitChunkOnALine.call(this, lineNumber, chunkNumber); + this._restoreSelection(selection); + return chunk; + }, + _buildChunks: function() { for (var i = 0; i < this._textModel.linesCount; ++i) @@ -825,6 +1007,7 @@ WebInspector.TextEditorMainPanel.prototype = { this._restorePaintLinesOperationsCredit(); WebInspector.TextEditorChunkedPanel.prototype._expandChunks.call(this, fromIndex, toIndex); + this._adjustPaintLinesOperationsRefreshValue(); this._restoreSelection(selection); }, @@ -844,7 +1027,7 @@ WebInspector.TextEditorMainPanel.prototype = { if (!this._scheduledPaintLines) { this._scheduledPaintLines = [ { startLine: startLine, endLine: endLine } ]; - this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 10); + this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 0); } else { for (var i = 0; i < this._scheduledPaintLines.length; ++i) { var chunk = this._scheduledPaintLines[i]; @@ -879,14 +1062,31 @@ WebInspector.TextEditorMainPanel.prototype = { var scheduledPaintLines = this._scheduledPaintLines; delete this._scheduledPaintLines; - + this._restorePaintLinesOperationsCredit(); this._paintLineChunks(scheduledPaintLines, !skipRestoreSelection); + this._adjustPaintLinesOperationsRefreshValue(); }, _restorePaintLinesOperationsCredit: function() { - this._paintLinesOperationsCredit = 250; + if (!this._paintLinesOperationsRefreshValue) + this._paintLinesOperationsRefreshValue = 250; + this._paintLinesOperationsCredit = this._paintLinesOperationsRefreshValue; + this._paintLinesOperationsLastRefresh = Date.now(); + }, + + _adjustPaintLinesOperationsRefreshValue: function() + { + var operationsDone = this._paintLinesOperationsRefreshValue - this._paintLinesOperationsCredit; + if (operationsDone <= 0) + return; + var timePast = Date.now() - this._paintLinesOperationsLastRefresh; + if (timePast <= 0) + return; + // Make the synchronous CPU chunk for painting the lines 50 msec. + var value = Math.floor(operationsDone / timePast * 50); + this._paintLinesOperationsRefreshValue = Number.constrain(value, 150, 1500); }, _paintLines: function(fromLine, toLine, restoreSelection) @@ -943,20 +1143,22 @@ WebInspector.TextEditorMainPanel.prototype = { _paintLine: function(lineRow) { var lineNumber = lineRow.lineNumber; - if (this._dirtyLines || this._scheduledPaintLines || this._paintLinesOperationsCredit < 0) { + if (this._dirtyLines) { this._schedulePaintLines(lineNumber, lineNumber + 1); return; } 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); + if (this._scheduledPaintLines || this._paintLinesOperationsCredit < 0) { + this._schedulePaintLines(lineNumber, lineNumber + 1); return; } + var highlight = this._textModel.getAttribute(lineNumber, "highlight"); + if (!highlight) + return; + lineRow.removeChildren(); var line = this._textModel.line(lineNumber); if (!line) @@ -990,11 +1192,11 @@ WebInspector.TextEditorMainPanel.prototype = { this._appendTextNode(lineRow, line.substring(plainTextStart, line.length)); --this._paintLinesOperationsCredit; } - 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 { + if (this._rangeToMark && this._rangeToMark.startLine === lineNumber) + this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn); this.endDomUpdates(); } }, @@ -1035,13 +1237,28 @@ WebInspector.TextEditorMainPanel.prototype = { return new WebInspector.TextRange(end.line, end.column, start.line, start.column); }, - _restoreSelection: function(range) + _restoreSelection: function(range, scrollIntoView) { if (!range) return; var start = this._positionToSelection(range.startLine, range.startColumn); var end = range.isEmpty() ? start : this._positionToSelection(range.endLine, range.endColumn); window.getSelection().setBaseAndExtent(start.container, start.offset, end.container, end.offset); + + if (scrollIntoView) { + for (var node = end.container; node; node = node.parentElement) { + if (node.scrollIntoViewIfNeeded) { + node.scrollIntoViewIfNeeded(); + break; + } + } + } + }, + + _setCaretLocation: function(line, column, scrollIntoView) + { + var range = new WebInspector.TextRange(line, column, line, column); + this._restoreSelection(range, scrollIntoView); }, _selectionToPosition: function(container, offset) @@ -1051,14 +1268,14 @@ WebInspector.TextEditorMainPanel.prototype = { 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"); + var lineRow = this._enclosingLineRowOrSelf(container); var lineNumber = lineRow.lineNumber; if (container === lineRow && offset === 0) return { line: lineNumber, column: 0 }; // This may be chunk and chunks may contain \n. var column = 0; - var node = lineRow.traverseNextTextNode(lineRow); + var node = lineRow.nodeType === Node.TEXT_NODE ? lineRow : lineRow.traverseNextTextNode(lineRow); while (node && node !== container) { var text = node.textContent; for (var i = 0; i < text.length; ++i) { @@ -1087,7 +1304,8 @@ WebInspector.TextEditorMainPanel.prototype = { _positionToSelection: function(line, column) { var chunk = this.chunkForLine(line); - var lineRow = chunk.getExpandedLineRow(line); + // One-lined collapsed chunks may still stay highlighted. + var lineRow = chunk.linesCount === 1 ? chunk.element : chunk.getExpandedLineRow(line); if (lineRow) var rangeBoundary = lineRow.rangeBoundaryForOffset(column); else { @@ -1103,6 +1321,18 @@ WebInspector.TextEditorMainPanel.prototype = { return rangeBoundary; }, + _enclosingLineRowOrSelf: function(element) + { + var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content"); + if (lineRow) + return lineRow; + for (var lineRow = element; lineRow; lineRow = lineRow.parentElement) { + if (lineRow.parentElement === this._container) + return lineRow; + } + return null; + }, + _appendSpan: function(element, content, className) { if (className === "html-resource-link" || className === "html-external-link") { @@ -1167,7 +1397,7 @@ WebInspector.TextEditorMainPanel.prototype = { if (target === this._container) return; - var lineRow = target.enclosingNodeOrSelfWithClass("webkit-line-content"); + var lineRow = this._enclosingLineRowOrSelf(target); if (!lineRow) return; @@ -1195,7 +1425,7 @@ WebInspector.TextEditorMainPanel.prototype = { var endLine = startLine + 1; for (var row = lineRow.nextSibling; row; row = row.nextSibling) { - if (typeof row.lineNumber === "number") { + if (typeof row.lineNumber === "number" && row.lineNumber > startLine) { endLine = row.lineNumber; break; } @@ -1205,7 +1435,7 @@ WebInspector.TextEditorMainPanel.prototype = { // Now this will no longer be valid. delete lineRow.lineNumber; } - + if (this._dirtyLines) { this._dirtyLines.start = Math.min(this._dirtyLines.start, startLine); this._dirtyLines.end = Math.max(this._dirtyLines.end, endLine); @@ -1258,7 +1488,7 @@ WebInspector.TextEditorMainPanel.prototype = { this._collectLinesFromDiv(lines, lineRow); } - // Try to decrease the range being replaced if possible. + // 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]) @@ -1277,26 +1507,65 @@ WebInspector.TextEditorMainPanel.prototype = { lines = lines.slice(startOffset, endOffset); + // Try to decrease the range being replaced by column offsets, if possible. + var startColumn = 0; + var endColumn = this._textModel.lineLength(endLine - 1); + if (lines.length > 0) { + var line1 = this._textModel.line(startLine); + var line2 = lines[0]; + while (line1[startColumn] && line1[startColumn] === line2[startColumn]) + ++startColumn; + lines[0] = line2.substring(startColumn); + + var line1 = this._textModel.line(endLine - 1); + var line2 = lines[lines.length - 1]; + for (var i = 0; i < endColumn && i < line2.length; ++i) { + if (startLine === endLine - 1 && endColumn - i <= startColumn) + break; + if (line1[endColumn - i - 1] !== line2[line2.length - i - 1]) + break; + } + if (i) { + endColumn -= i; + lines[lines.length - 1] = line2.substring(0, line2.length - i); + } + } + var selection = this._getSelection(); - if (lines.length === 0 && endLine < this._textModel.linesCount) { + 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")); - } + else if (lines.length === 0 && startLine > 0) + var oldRange = new WebInspector.TextRange(startLine - 1, this._textModel.lineLength(startLine - 1), endLine - 1, this._textModel.lineLength(endLine - 1)); + else + var oldRange = new WebInspector.TextRange(startLine, startColumn, endLine - 1, endColumn); + + var newRange = this._setText(oldRange, lines.join("\n")); + + this._paintScheduledLines(true); + this._restoreSelection(selection); + + this._exitTextChangeMode(oldRange, newRange); + }, + textChanged: function(oldRange, newRange) + { this.beginDomUpdates(); this._removeDecorationsInRange(oldRange); this._updateChunksForRanges(oldRange, newRange); this._updateHighlightsForRange(newRange); - this._paintScheduledLines(true); this.endDomUpdates(); + }, - this._restoreSelection(selection); + _setText: function(range, text) + { + if (this._lastEditedRange && (!text || text.indexOf("\n") !== -1 || this._lastEditedRange.endLine !== range.startLine || this._lastEditedRange.endColumn !== range.startColumn)) + this._textModel.markUndoableState(); - this._exitTextChangeMode(oldRange, newRange); + var newRange = this._textModel.setText(range, text); + this._lastEditedRange = newRange; + + return newRange; }, _removeDecorationsInRange: function(range) @@ -1342,6 +1611,8 @@ WebInspector.TextEditorMainPanel.prototype = { // Most frequent case: a chunk remained the same. for (var chunkNumber = firstChunkNumber; chunkNumber <= lastChunkNumber; ++chunkNumber) { var chunk = this._textChunks[chunkNumber]; + if (chunk.startLine + chunk.linesCount > this._textModel.linesCount) + break; 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) @@ -1428,7 +1699,7 @@ WebInspector.TextEditorMainPanel.prototype = { _collectLinesFromDiv: function(lines, element) { var textContents = []; - var node = element.traverseNextNode(element); + var node = element.nodeType === Node.TEXT_NODE ? element : element.traverseNextNode(element); while (node) { if (element.decorationsElement === node) { node = node.nextSibling; diff --git a/Source/WebCore/inspector/front-end/WebKit.qrc b/Source/WebCore/inspector/front-end/WebKit.qrc index 0777a19..1b5cb39 100644 --- a/Source/WebCore/inspector/front-end/WebKit.qrc +++ b/Source/WebCore/inspector/front-end/WebKit.qrc @@ -9,8 +9,6 @@ <file>AuditRules.js</file> <file>AuditsPanel.js</file> <file>BottomUpProfileDataGridTree.js</file> - <file>Breakpoint.js</file> - <file>BreakpointManager.js</file> <file>BreakpointsSidebarPane.js</file> <file>CallStackSidebarPane.js</file> <file>Checkbox.js</file> @@ -34,6 +32,7 @@ <file>DebuggerPresentationModel.js</file> <file>SourceFile.js</file> <file>DOMAgent.js</file> + <file>DOMBreakpointsSidebarPane.js</file> <file>DOMStorage.js</file> <file>DOMStorageItemsView.js</file> <file>DOMSyntaxHighlighter.js</file> @@ -51,6 +50,7 @@ <file>GoToLineDialog.js</file> <file>HAREntry.js</file> <file>HeapSnapshot.js</file> + <file>HeapSnapshotProxy.js</file> <file>HeapSnapshotView.js</file> <file>HelpScreen.js</file> <file>ImageView.js</file> @@ -98,7 +98,6 @@ <file>SidebarTreeElement.js</file> <file>SourceCSSTokenizer.js</file> <file>SourceFrame.js</file> - <file>SourceFrameContent.js</file> <file>SourceHTMLTokenizer.js</file> <file>SourceJavaScriptTokenizer.js</file> <file>SourceTokenizer.js</file> diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css index 0311f22..d6fef89 100644 --- a/Source/WebCore/inspector/front-end/inspector.css +++ b/Source/WebCore/inspector/front-end/inspector.css @@ -89,8 +89,8 @@ body.inactive #toolbar { border-bottom: 1px solid rgb(64%, 64%, 64%); } -body.detached.platform-mac-leopard #toolbar, -body.detached.platform-mac-snowleopard #toolbar { +body.detached.platform-mac-leopard:not(.remote) #toolbar, +body.detached.platform-mac-snowleopard:not(.remote) #toolbar { background: transparent !important; } @@ -349,7 +349,7 @@ body.attached #search { background-position: 0 0; background-color: transparent; border: 0 none transparent; - margin-top: 9px; + margin-top: 4px; } #close-button-left:hover, #close-button-right:hover { @@ -493,14 +493,6 @@ button.status-bar-item.toggled-on .glyph { background-color: rgb(66, 129, 235); } -button.status-bar-item.toggled-1 .glyph { - background-color: rgb(66, 129, 235); -} - -button.status-bar-item.toggled-2 .glyph { - background-color: purple; -} - button.status-bar-item:disabled { opacity: 0.5; background-position: 0 0 !important; @@ -872,7 +864,7 @@ body.platform-linux .monospace, body.platform-linux .source-code { .console-formatted-string, .console-formatted-regexp { color: rgb(196, 26, 22); - white-space: pre-wrap; + white-space: pre; } .console-formatted-null, .console-formatted-undefined { @@ -2520,6 +2512,14 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { -webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png); } +.scripts-pause-on-exceptions-status-bar-item.toggled-all .glyph { + background-color: rgb(66, 129, 235); +} + +.scripts-pause-on-exceptions-status-bar-item.toggled-uncaught .glyph { + background-color: purple; +} + #scripts-status-bar { position: absolute; top: -1px; @@ -4309,10 +4309,6 @@ a.worker-item { color: inherit; } -.styles-section a::before { - content: attr(data-uncopyable); -} - .styles-section .properties { display: none; margin: 0; diff --git a/Source/WebCore/inspector/front-end/inspector.html b/Source/WebCore/inspector/front-end/inspector.html index 9ba1dca..18c2564 100644 --- a/Source/WebCore/inspector/front-end/inspector.html +++ b/Source/WebCore/inspector/front-end/inspector.html @@ -46,7 +46,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="ExtensionRegistryStub.js"></script> <script type="text/javascript" src="Object.js"></script> <script type="text/javascript" src="Settings.js"></script> - <script type="text/javascript" src="CSSStyleModel.js"></script> <script type="text/javascript" src="Checkbox.js"></script> <script type="text/javascript" src="ContextMenu.js"></script> <script type="text/javascript" src="KeyboardShortcut.js"></script> @@ -61,6 +60,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="Panel.js"></script> <script type="text/javascript" src="TimelineGrid.js"></script> <script type="text/javascript" src="Resource.js"></script> + <script type="text/javascript" src="CSSStyleModel.js"></script> <script type="text/javascript" src="NetworkManager.js"></script> <script type="text/javascript" src="ResourceTreeModel.js"></script> <script type="text/javascript" src="ResourceCategory.js"></script> @@ -73,8 +73,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="CookieItemsView.js"></script> <script type="text/javascript" src="ApplicationCacheItemsView.js"></script> <script type="text/javascript" src="Script.js"></script> - <script type="text/javascript" src="Breakpoint.js"></script> - <script type="text/javascript" src="BreakpointManager.js"></script> <script type="text/javascript" src="SidebarPane.js"></script> <script type="text/javascript" src="ElementsTreeOutline.js"></script> <script type="text/javascript" src="SidebarTreeElement.js"></script> @@ -83,6 +81,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="RemoteObject.js"></script> <script type="text/javascript" src="ObjectPropertiesSection.js"></script> <script type="text/javascript" src="BreakpointsSidebarPane.js"></script> + <script type="text/javascript" src="DOMBreakpointsSidebarPane.js"></script> <script type="text/javascript" src="CallStackSidebarPane.js"></script> <script type="text/javascript" src="ScopeChainSidebarPane.js"></script> <script type="text/javascript" src="WatchExpressionsSidebarPane.js"></script> @@ -101,8 +100,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="ElementsPanel.js"></script> <script type="text/javascript" src="NetworkPanel.js"></script> <script type="text/javascript" src="InjectedFakeWorker.js"></script> + <script type="text/javascript" src="TextViewer.js"></script> <script type="text/javascript" src="SourceFrame.js"></script> - <script type="text/javascript" src="SourceFrameContent.js"></script> <script type="text/javascript" src="ResourceView.js"></script> <script type="text/javascript" src="ScriptsPanel.js"></script> <script type="text/javascript" src="ResourcesPanel.js"></script> @@ -128,7 +127,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="DOMSyntaxHighlighter.js"></script> <script type="text/javascript" src="TextEditorModel.js"></script> <script type="text/javascript" src="TextEditorHighlighter.js"></script> - <script type="text/javascript" src="TextViewer.js"></script> <script type="text/javascript" src="SourceTokenizer.js"></script> <script type="text/javascript" src="SourceCSSTokenizer.js"></script> <script type="text/javascript" src="SourceHTMLTokenizer.js"></script> @@ -142,6 +140,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="TopDownProfileDataGridTree.js"></script> <script type="text/javascript" src="ProfileView.js"></script> <script type="text/javascript" src="HeapSnapshot.js"></script> + <script type="text/javascript" src="HeapSnapshotProxy.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> diff --git a/Source/WebCore/inspector/front-end/inspector.js b/Source/WebCore/inspector/front-end/inspector.js index 59171db..b125e7e 100644 --- a/Source/WebCore/inspector/front-end/inspector.js +++ b/Source/WebCore/inspector/front-end/inspector.js @@ -171,17 +171,6 @@ var WebInspector = { } }, - createDOMBreakpointsSidebarPane: function() - { - var pane = new WebInspector.NativeBreakpointsSidebarPane(WebInspector.UIString("DOM Breakpoints")); - function breakpointAdded(event) - { - pane.addBreakpointItem(new WebInspector.BreakpointItem(event.data)); - } - WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.DOMBreakpointAdded, breakpointAdded); - return pane; - }, - _createPanels: function() { var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(','); @@ -427,6 +416,8 @@ WebInspector.doLoadedDone = function() document.body.addStyleClass("platform-" + flavor); var port = WebInspector.port; document.body.addStyleClass("port-" + port); + if (WebInspector.socket) + document.body.addStyleClass("remote"); WebInspector.settings = new WebInspector.Settings(); @@ -460,8 +451,8 @@ WebInspector.doLoadedDone = function() this.cssModel = new WebInspector.CSSStyleModel(); this.debuggerModel = new WebInspector.DebuggerModel(); - this.breakpointManager = new WebInspector.BreakpointManager(); this.searchController = new WebInspector.SearchController(); + this.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane(); this.panels = {}; this._createPanels(); @@ -508,6 +499,8 @@ WebInspector.doLoadedDone = function() ConsoleAgent.setMonitoringXHREnabled(true); ConsoleAgent.enable(this.console.setConsoleMessageExpiredCount.bind(this.console)); + DatabaseAgent.enable(); + WebInspector.showPanel(WebInspector.settings.lastActivePanel); function propertyNamesCallback(error, names) @@ -624,16 +617,8 @@ WebInspector.documentClick = function(event) function followLink() { - // FIXME: support webkit-html-external-link links here. - if (WebInspector.canShowSourceLine(anchor.href, anchor.getAttribute("line_number"), anchor.getAttribute("preferred_panel"))) { - if (anchor.hasStyleClass("webkit-html-external-link")) { - anchor.removeStyleClass("webkit-html-external-link"); - anchor.addStyleClass("webkit-html-resource-link"); - } - - WebInspector.showSourceLine(anchor.href, anchor.getAttribute("line_number"), anchor.getAttribute("preferred_panel")); + if (WebInspector._showAnchorLocation(anchor)) return; - } const profileMatch = WebInspector.ProfileType.URLRegExp.exec(anchor.href); if (profileMatch) { @@ -995,18 +980,13 @@ WebInspector.startUserInitiatedDebugging = function() WebInspector.domContentEventFired = function(time) { this.panels.audits.mainResourceDOMContentTime = time; - if (this.panels.network) - this.panels.network.mainResourceDOMContentTime = time; - this.extensionServer.notifyPageDOMContentLoaded((time - WebInspector.mainResource.startTime) * 1000); this.mainResourceDOMContentTime = time; } WebInspector.loadEventFired = function(time) { this.panels.audits.mainResourceLoadTime = time; - this.panels.network.mainResourceLoadTime = time; this.panels.resources.loadEventFired(); - this.extensionServer.notifyPageLoaded((time - WebInspector.mainResource.startTime) * 1000); this.mainResourceLoadTime = time; } @@ -1045,8 +1025,8 @@ WebInspector.bringToFront = function() WebInspector.inspectedURLChanged = function(url) { InspectorFrontendHost.inspectedURLChanged(url); - this.settings.inspectedURLChanged(url); - this.extensionServer.notifyInspectedURLChanged(); + this.domBreakpointsSidebarPane.setInspectedURL(url); + this.extensionServer.notifyInspectedURLChanged(url); } WebInspector.didCreateWorker = function() @@ -1225,30 +1205,31 @@ WebInspector.displayNameForURL = function(url) return url.trimURL(WebInspector.mainResource.domain); } -WebInspector._choosePanelToShowSourceLine = function(url, line, preferredPanel) -{ - preferredPanel = preferredPanel || "resources"; - - var panel = this.panels[preferredPanel]; - if (panel && panel.canShowSourceLine(url, line)) - return panel; - panel = this.panels.resources; - return panel.canShowSourceLine(url, line) ? panel : null; -} - -WebInspector.canShowSourceLine = function(url, line, preferredPanel) +WebInspector._showAnchorLocation = function(anchor) { - return !!this._choosePanelToShowSourceLine(url, line, preferredPanel); + var preferedPanel = this.panels[anchor.getAttribute("preferred_panel") || "resources"]; + if (WebInspector._showAnchorLocationInPanel(anchor, preferedPanel)) + return true; + if (preferedPanel !== this.panels.resources && WebInspector._showAnchorLocationInPanel(anchor, this.panels.resources)) + return true; + return false; } -WebInspector.showSourceLine = function(url, line, preferredPanel) +WebInspector._showAnchorLocationInPanel = function(anchor, panel) { - this.currentPanel = this._choosePanelToShowSourceLine(url, line, preferredPanel); - if (!this.currentPanel) + if (!panel.canShowAnchorLocation(anchor)) return false; + + // FIXME: support webkit-html-external-link links here. + if (anchor.hasStyleClass("webkit-html-external-link")) { + anchor.removeStyleClass("webkit-html-external-link"); + anchor.addStyleClass("webkit-html-resource-link"); + } + + this.currentPanel = panel; if (this.drawer) this.drawer.immediatelyFinishAnimation(); - this.currentPanel.showSourceLine(url, line); + this.currentPanel.showAnchorLocation(anchor); return true; } @@ -1315,6 +1296,7 @@ WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, too else if (typeof tooltipText !== "string" || tooltipText.length) a.title = tooltipText; a.textContent = linkText; + a.style.maxWidth = "100%"; return a; } @@ -1451,9 +1433,25 @@ WebInspector.isBeingEdited = function(element) return element.__editing; } +WebInspector.markBeingEdited = function(element, value) +{ + if (value) { + if (element.__editing) + return false; + element.__editing = true; + WebInspector.__editingCount = (WebInspector.__editingCount || 0) + 1; + } else { + if (!element.__editing) + return false; + delete element.__editing; + --WebInspector.__editingCount; + } + return true; +} + WebInspector.isEditingAnyField = function() { - return this.__editing; + return !!WebInspector.__editingCount; } // Available config fields (all optional): @@ -1465,10 +1463,8 @@ WebInspector.isEditingAnyField = function() // multiline: Boolean - whether the edited element is multiline WebInspector.startEditing = function(element, config) { - if (element.__editing) + if (!WebInspector.markBeingEdited(element, true)) return; - element.__editing = true; - WebInspector.__editing = true; config = config || {}; var committedCallback = config.commitHandler; @@ -1496,8 +1492,7 @@ WebInspector.startEditing = function(element, config) } function cleanUpAfterEditing() { - delete this.__editing; - delete WebInspector.__editing; + WebInspector.markBeingEdited(element, false); this.removeStyleClass("editing"); this.tabIndex = oldTabIndex; diff --git a/Source/WebCore/inspector/front-end/networkPanel.css b/Source/WebCore/inspector/front-end/networkPanel.css index 2711347..8ff5e9e 100644 --- a/Source/WebCore/inspector/front-end/networkPanel.css +++ b/Source/WebCore/inspector/front-end/networkPanel.css @@ -714,6 +714,22 @@ display: none; } +.resource-headers-view .outline-disclosure li .header-toggle { + display: none; +} + +.resource-headers-view .outline-disclosure li.expanded .header-toggle { + display: inline; + margin-left: 30px; + font-weight: normal; + color: rgb(45%, 45%, 45%); +} + +.resource-headers-view .outline-disclosure li .header-toggle:hover { + color: rgb(20%, 20%, 45%); + cursor: pointer; +} + .resource-headers-view .outline-disclosure .header-name { color: rgb(33%, 33%, 33%); display: inline-block; @@ -731,6 +747,11 @@ margin-top: 1px; } +.resource-headers-view .outline-disclosure li.headers-text { + text-indent: 0; + margin-left: -2px; +} + .resource-headers-view .outline-disclosure .raw-form-data { white-space: pre-wrap; } diff --git a/Source/WebCore/inspector/front-end/utilities.js b/Source/WebCore/inspector/front-end/utilities.js index fbfdfbb..839fce5 100644 --- a/Source/WebCore/inspector/front-end/utilities.js +++ b/Source/WebCore/inspector/front-end/utilities.js @@ -451,6 +451,14 @@ String.prototype.trimURL = function(baseURLDomain) return result; } +String.prototype.removeURLFragment = function() +{ + var fragmentIndex = this.indexOf("#"); + if (fragmentIndex == -1) + fragmentIndex = this.length; + return this.substring(0, fragmentIndex); +} + function isNodeWhitespace() { if (!this || this.nodeType !== Node.TEXT_NODE) @@ -592,31 +600,6 @@ function traversePreviousNode(stayWithin) return this.parentNode; } -function appropriateSelectorForNode(node, justSelector) -{ - if (!node) - return ""; - - var lowerCaseName = node.localName || node.nodeName.toLowerCase(); - - var id = node.getAttribute("id"); - if (id) { - var selector = "#" + id; - return (justSelector ? selector : lowerCaseName + selector); - } - - var className = node.getAttribute("class"); - if (className) { - var selector = "." + className.replace(/\s+/, "."); - return (justSelector ? selector : lowerCaseName + selector); - } - - if (lowerCaseName === "input" && node.getAttribute("type")) - return lowerCaseName + "[type=\"" + node.getAttribute("type") + "\"]"; - - return lowerCaseName; -} - function getDocumentForNode(node) { return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument; |