diff options
Diffstat (limited to 'WebCore/inspector/front-end')
58 files changed, 4536 insertions, 1885 deletions
diff --git a/WebCore/inspector/front-end/AbstractTimelinePanel.js b/WebCore/inspector/front-end/AbstractTimelinePanel.js index 75e4062..c5180f6 100644 --- a/WebCore/inspector/front-end/AbstractTimelinePanel.js +++ b/WebCore/inspector/front-end/AbstractTimelinePanel.js @@ -57,10 +57,13 @@ WebInspector.AbstractTimelinePanel.prototype = { // Should be implemented by the concrete subclasses. }, - createInterface: function() + get items() { - this._createFilterPanel(); + return this._items; + }, + createInterface: function() + { this.containerElement = document.createElement("div"); this.containerElement.id = "resources-container"; this.containerElement.addEventListener("scroll", this._updateDividersLabelBarPosition.bind(this), false); @@ -70,10 +73,20 @@ WebInspector.AbstractTimelinePanel.prototype = { this.sidebarElement.id = "resources-sidebar"; this.populateSidebar(); - this._createGraph(); + this._containerContentElement = document.createElement("div"); + this._containerContentElement.id = "resources-container-content"; + this.containerElement.appendChild(this._containerContentElement); + + this.summaryBar = new WebInspector.SummaryBar(this.categories); + this.summaryBar.element.id = "resources-summary"; + this._containerContentElement.appendChild(this.summaryBar.element); + + this._timelineGrid = new WebInspector.TimelineGrid(); + this._containerContentElement.appendChild(this._timelineGrid.element); + this.itemsGraphsElement = this._timelineGrid.itemsGraphsElement; }, - _createFilterPanel: function() + createFilterPanel: function() { this.filterBarElement = document.createElement("div"); this.filterBarElement.id = "resources-filter"; @@ -108,14 +121,14 @@ WebInspector.AbstractTimelinePanel.prototype = { createFilterElement.call(this, category); }, - _showCategory: function(category) + showCategory: function(category) { var filterClass = "filter-" + category.toLowerCase(); this.itemsGraphsElement.addStyleClass(filterClass); this.itemsTreeElement.childrenListElement.addStyleClass(filterClass); }, - _hideCategory: function(category) + hideCategory: function(category) { var filterClass = "filter-" + category.toLowerCase(); this.itemsGraphsElement.removeStyleClass(filterClass); @@ -132,7 +145,7 @@ WebInspector.AbstractTimelinePanel.prototype = { continue; child.removeStyleClass("selected"); - this._hideCategory(child.category); + this.hideCategory(child.category); } } @@ -148,7 +161,7 @@ WebInspector.AbstractTimelinePanel.prototype = { // Something other than All is being selected, so we want to unselect All. if (this.filterAllElement.hasStyleClass("selected")) { this.filterAllElement.removeStyleClass("selected"); - this._hideCategory("all"); + this.hideCategory("all"); } } @@ -158,7 +171,7 @@ WebInspector.AbstractTimelinePanel.prototype = { unselectAll.call(this); target.addStyleClass("selected"); - this._showCategory(target.category); + this.showCategory(target.category); return; } @@ -166,18 +179,18 @@ WebInspector.AbstractTimelinePanel.prototype = { // If selectMultiple is turned on, and we were selected, we just // want to unselect ourselves. target.removeStyleClass("selected"); - this._hideCategory(target.category); + this.hideCategory(target.category); } else { // If selectMultiple is turned on, and we weren't selected, we just // want to select ourselves. target.addStyleClass("selected"); - this._showCategory(target.category); + this.showCategory(target.category); } }, _updateFilter: function(e) { - var isMac = InspectorController.platform().indexOf("mac-") === 0; + var isMac = WebInspector.isMac(); var selectMultiple = false; if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) selectMultiple = true; @@ -191,83 +204,20 @@ WebInspector.AbstractTimelinePanel.prototype = { this.containerElement.scrollTop = 0; }, - _createGraph: function() - { - this._containerContentElement = document.createElement("div"); - this._containerContentElement.id = "resources-container-content"; - this.containerElement.appendChild(this._containerContentElement); - - this.summaryBar = new WebInspector.SummaryBar(this.categories); - this.summaryBar.element.id = "resources-summary"; - this._containerContentElement.appendChild(this.summaryBar.element); - - this.itemsGraphsElement = document.createElement("div"); - this.itemsGraphsElement.id = "resources-graphs"; - this._containerContentElement.appendChild(this.itemsGraphsElement); - - this.dividersElement = document.createElement("div"); - this.dividersElement.id = "resources-dividers"; - this._containerContentElement.appendChild(this.dividersElement); - - this.eventDividersElement = document.createElement("div"); - this.eventDividersElement.id = "resources-event-dividers"; - this._containerContentElement.appendChild(this.eventDividersElement); - - this.dividersLabelBarElement = document.createElement("div"); - this.dividersLabelBarElement.id = "resources-dividers-label-bar"; - this._containerContentElement.appendChild(this.dividersLabelBarElement); - }, - updateGraphDividersIfNeeded: function(force) { if (!this.visible) { this.needsRefresh = true; return false; } - - if (document.body.offsetWidth <= 0) { - // The stylesheet hasn't loaded yet or the window is closed, - // so we can't calculate what is need. Return early. - return false; - } - - var dividerCount = Math.round(this.dividersElement.offsetWidth / 64); - var slice = this.calculator.boundarySpan / dividerCount; - if (!force && this._currentDividerSlice === slice) - return false; - - this._currentDividerSlice = slice; - - this.dividersElement.removeChildren(); - this.eventDividersElement.removeChildren(); - this.dividersLabelBarElement.removeChildren(); - - for (var i = 1; i <= dividerCount; ++i) { - var divider = document.createElement("div"); - divider.className = "resources-divider"; - if (i === dividerCount) - divider.addStyleClass("last"); - divider.style.left = ((i / dividerCount) * 100) + "%"; - - this.dividersElement.appendChild(divider.cloneNode()); - - var label = document.createElement("div"); - label.className = "resources-divider-label"; - if (!isNaN(slice)) - label.textContent = this.calculator.formatValue(slice * i); - divider.appendChild(label); - - this.dividersLabelBarElement.appendChild(divider); - } + return this._timelineGrid.updateDividers(force, this.calculator); }, _updateDividersLabelBarPosition: function() { var scrollTop = this.containerElement.scrollTop; var dividersTop = (scrollTop < this.summaryBar.element.offsetHeight ? this.summaryBar.element.offsetHeight : scrollTop); - this.dividersElement.style.top = scrollTop + "px"; - this.eventDividersElement.style.top = scrollTop + "px"; - this.dividersLabelBarElement.style.top = dividersTop + "px"; + this._timelineGrid.setScrollAndDividerTop(scrollTop, dividersTop); }, get needsRefresh() @@ -318,26 +268,32 @@ WebInspector.AbstractTimelinePanel.prototype = { this.updateGraphDividersIfNeeded(); }, + invalidateAllItems: function() + { + this._staleItems = this._items.slice(); + }, + refresh: function() { this.needsRefresh = false; var staleItemsLength = this._staleItems.length; + var boundariesChanged = false; for (var i = 0; i < staleItemsLength; ++i) { var item = this._staleItems[i]; - if (!item._itemTreeElement) { + if (!item._itemsTreeElement) { // Create the timeline tree element and graph. - item._itemTreeElement = this.createItemTreeElement(item); - item._itemTreeElement._itemGraph = this.createItemGraph(item); + item._itemsTreeElement = this.createItemTreeElement(item); + item._itemsTreeElement._itemGraph = this.createItemGraph(item); - this.itemsTreeElement.appendChild(item._itemTreeElement); - this.itemsGraphsElement.appendChild(item._itemTreeElement._itemGraph.graphElement); + this.itemsTreeElement.appendChild(item._itemsTreeElement); + this.itemsGraphsElement.appendChild(item._itemsTreeElement._itemGraph.graphElement); } - if (item._itemTreeElement.refresh) - item._itemTreeElement.refresh(); + if (item._itemsTreeElement.refresh) + item._itemsTreeElement.refresh(); if (this.calculator.updateBoundaries(item)) boundariesChanged = true; @@ -345,12 +301,12 @@ WebInspector.AbstractTimelinePanel.prototype = { if (boundariesChanged) { // The boundaries changed, so all item graphs are stale. - this._staleItems = this._items; + this._staleItems = this._items.slice(); staleItemsLength = this._staleItems.length; } for (var i = 0; i < staleItemsLength; ++i) - this._staleItems[i]._itemTreeElement._itemGraph.refresh(this.calculator); + this._staleItems[i]._itemsTreeElement._itemGraph.refresh(this.calculator); this._staleItems = []; @@ -394,7 +350,7 @@ WebInspector.AbstractTimelinePanel.prototype = { this._calculator = x; this._calculator.reset(); - this._staleItems = this._items; + this._staleItems = this._items.slice(); this.refresh(); }, @@ -408,12 +364,12 @@ WebInspector.AbstractTimelinePanel.prototype = { { this._items.remove(item, true); - if (item._itemTreeElement) { - this.itemsTreeElement.removeChild(resource._itemTreeElement); - this.itemsGraphsElement.removeChild(resource._itemTreeElement._itemGraph.graphElement); + if (item._itemsTreeElement) { + this.itemsTreeElement.removeChild(item._itemsTreeElement); + this.itemsGraphsElement.removeChild(item._itemsTreeElement._itemGraph.graphElement); } - delete item._itemTreeElement; + delete item._itemsTreeElement; this.adjustScrollPosition(); }, @@ -458,6 +414,11 @@ WebInspector.AbstractTimelinePanel.prototype = { // Prevent the container from being scrolled off the end. if ((this.containerElement.scrollTop + this.containerElement.offsetHeight) > this.sidebarElement.offsetHeight) this.containerElement.scrollTop = (this.sidebarElement.offsetHeight - this.containerElement.offsetHeight); + }, + + addEventDivider: function(divider) + { + this._timelineGrid.addEventDivider(divider); } } diff --git a/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js b/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js index 41a8a3a..5aaae0c 100644 --- a/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js +++ b/WebCore/inspector/front-end/BottomUpProfileDataGridTree.js @@ -31,11 +31,7 @@ WebInspector.BottomUpProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*BottomUpProfileDataGridTree*/ owningTree) { - // In bottom up mode, our parents are our children since we display an inverted tree. - // However, we don't want to show the very top parent since it is redundant. - var hasChildren = !!(profileNode.parent && profileNode.parent.parent); - - WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren); + WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, this._willHaveChildren(profileNode)); this._remainingNodeInfos = []; } @@ -78,6 +74,14 @@ WebInspector.BottomUpProfileDataGridNode.prototype = { this._merge(child, true); }, + _restore: function() + { + WebInspector.ProfileDataGridNode.prototype._restore(); + + if (!this.children.length) + this.hasChildren = this._willHaveChildren(); + }, + _merge: function(/*ProfileDataGridNode*/ child, /*Boolean*/ shouldAbsorb) { this.selfTime -= child.selfTime; @@ -128,6 +132,14 @@ WebInspector.BottomUpProfileDataGridNode.prototype = { } delete this._remainingNodeInfos; + }, + + _willHaveChildren: function(profileNode) + { + profileNode = profileNode || this.profileNode; + // In bottom up mode, our parents are our children since we display an inverted tree. + // However, we don't want to show the very top parent since it is redundant. + return !!(profileNode.parent && profileNode.parent.parent); } } diff --git a/WebCore/inspector/front-end/Breakpoint.js b/WebCore/inspector/front-end/Breakpoint.js index 292975a..5d46cc9 100644 --- a/WebCore/inspector/front-end/Breakpoint.js +++ b/WebCore/inspector/front-end/Breakpoint.js @@ -89,7 +89,7 @@ WebInspector.Breakpoint.prototype = { this.dispatchEventToListeners("condition-changed"); if (this.enabled) - InspectorController.updateBreakpoint(this.sourceID, this.line, c); + InspectorBackend.updateBreakpoint(this.sourceID, this.line, c); } } diff --git a/WebCore/inspector/front-end/BreakpointsSidebarPane.js b/WebCore/inspector/front-end/BreakpointsSidebarPane.js index e6edece..9d4fe55 100644 --- a/WebCore/inspector/front-end/BreakpointsSidebarPane.js +++ b/WebCore/inspector/front-end/BreakpointsSidebarPane.js @@ -58,21 +58,24 @@ WebInspector.BreakpointsSidebarPane.prototype = { this.bodyElement.appendChild(this.listElement); } - if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + if (!InspectorBackend.debuggerEnabled() || !breakpoint.sourceID) return; if (breakpoint.enabled) - InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); + InspectorBackend.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); }, _appendBreakpointElement: function(breakpoint) { - function checkboxClicked() + function checkboxClicked(event) { breakpoint.enabled = !breakpoint.enabled; + + // without this, we'd switch to the source of the clicked breakpoint + event.stopPropagation(); } - function labelClicked() + function breakpointClicked() { var script = WebInspector.panels.scripts.scriptOrResourceForID(breakpoint.sourceID); if (script) @@ -82,6 +85,7 @@ WebInspector.BreakpointsSidebarPane.prototype = { var breakpointElement = document.createElement("li"); breakpoint._breakpointListElement = breakpointElement; breakpointElement._breakpointObject = breakpoint; + breakpointElement.addEventListener("click", breakpointClicked, false); var checkboxElement = document.createElement("input"); checkboxElement.className = "checkbox-elem"; @@ -90,9 +94,7 @@ WebInspector.BreakpointsSidebarPane.prototype = { checkboxElement.addEventListener("click", checkboxClicked, false); breakpointElement.appendChild(checkboxElement); - var labelElement = document.createElement("a"); - labelElement.textContent = breakpoint.label; - labelElement.addEventListener("click", labelClicked, false); + var labelElement = document.createTextNode(breakpoint.label); breakpointElement.appendChild(labelElement); var sourceTextElement = document.createElement("div"); @@ -133,10 +135,10 @@ WebInspector.BreakpointsSidebarPane.prototype = { this.bodyElement.appendChild(this.emptyElement); } - if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + if (!InspectorBackend.debuggerEnabled() || !breakpoint.sourceID) return; - InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line); + InspectorBackend.removeBreakpoint(breakpoint.sourceID, breakpoint.line); }, _breakpointEnableChanged: function(event) @@ -146,13 +148,13 @@ WebInspector.BreakpointsSidebarPane.prototype = { var checkbox = breakpoint._breakpointListElement.firstChild; checkbox.checked = breakpoint.enabled; - if (!InspectorController.debuggerEnabled() || !breakpoint.sourceID) + if (!InspectorBackend.debuggerEnabled() || !breakpoint.sourceID) return; if (breakpoint.enabled) - InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); + InspectorBackend.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); else - InspectorController.removeBreakpoint(breakpoint.sourceID, breakpoint.line); + InspectorBackend.removeBreakpoint(breakpoint.sourceID, breakpoint.line); }, _breakpointTextChanged: function(event) diff --git a/WebCore/inspector/front-end/Color.js b/WebCore/inspector/front-end/Color.js index 9d9cd76..11d6bad 100644 --- a/WebCore/inspector/front-end/Color.js +++ b/WebCore/inspector/front-end/Color.js @@ -437,7 +437,7 @@ WebInspector.Color.HexTable = { "B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"], "B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"], "B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"], - "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenRod"], + "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenrod"], "BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"], "BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"], "BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"], @@ -451,7 +451,7 @@ WebInspector.Color.HexTable = { "D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"], "D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"], "DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"], - "DAA520": [[218, 165, 32], [43, 74, 49], "goldenRod"], + "DAA520": [[218, 165, 32], [43, 74, 49], "goldenrod"], "DC143C": [[237, 164, 61], [35, 83, 58], "crimson"], "DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"], "DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"], @@ -460,7 +460,7 @@ WebInspector.Color.HexTable = { "E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"], "E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"], "EE82EE": [[238, 130, 238], [300, 76, 72], "violet"], - "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenRod"], + "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenrod"], "F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"], "F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"], "F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"], @@ -475,7 +475,7 @@ WebInspector.Color.HexTable = { "FA8072": [[250, 128, 114], [6, 93, 71], "salmon"], "FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"], "FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"], - "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenRodYellow"], + "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenrodYellow"], "FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"], "FF0000": [[255, 0, 0], [0, 100, 50], "red"], "FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"], diff --git a/WebCore/inspector/front-end/ConsolePanel.js b/WebCore/inspector/front-end/ConsolePanel.js new file mode 100644 index 0000000..6dbc558 --- /dev/null +++ b/WebCore/inspector/front-end/ConsolePanel.js @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2009 Joseph Pecoraro + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.ConsolePanel = function() +{ + WebInspector.Panel.call(this); +} + +WebInspector.ConsolePanel.prototype = { + toolbarItemClass: "console", + + get toolbarItemLabel() + { + return WebInspector.UIString("Console"); + }, + + show: function() + { + WebInspector.Panel.prototype.show.call(this); + + this._previousConsoleState = WebInspector.drawer.state; + WebInspector.drawer.enterPanelMode(); + WebInspector.showConsole(); + + // Move the scope bar to the top of the messages, like the resources filter. + var scopeBar = document.getElementById("console-filter"); + var consoleMessages = document.getElementById("console-messages"); + + scopeBar.parentNode.removeChild(scopeBar); + document.getElementById("console-view").insertBefore(scopeBar, consoleMessages); + + // Update styles, and give console-messages a top margin so it doesn't overwrite the scope bar. + scopeBar.addStyleClass("console-filter-top"); + scopeBar.removeStyleClass("status-bar-item"); + + consoleMessages.addStyleClass("console-filter-top"); + }, + + hide: function() + { + WebInspector.Panel.prototype.hide.call(this); + + if (this._previousConsoleState === WebInspector.Drawer.State.Hidden) + WebInspector.drawer.immediatelyExitPanelMode(); + else + WebInspector.drawer.exitPanelMode(); + delete this._previousConsoleState; + + // Move the scope bar back to the bottom bar, next to Clear Console. + var scopeBar = document.getElementById("console-filter"); + + scopeBar.parentNode.removeChild(scopeBar); + document.getElementById("other-drawer-status-bar-items").appendChild(scopeBar); + + // Update styles, and remove the top margin on console-messages. + scopeBar.removeStyleClass("console-filter-top"); + scopeBar.addStyleClass("status-bar-item"); + + document.getElementById("console-messages").removeStyleClass("console-filter-top"); + } +} + +WebInspector.ConsolePanel.prototype.__proto__ = WebInspector.Panel.prototype; diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js index 9317824..9815f4a 100644 --- a/WebCore/inspector/front-end/ConsoleView.js +++ b/WebCore/inspector/front-end/ConsoleView.js @@ -57,51 +57,60 @@ WebInspector.ConsoleView = function(drawer) this.toggleConsoleButton.title = WebInspector.UIString("Show console."); this.toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false); - var anchoredStatusBar = document.getElementById("anchored-status-bar-items"); - anchoredStatusBar.appendChild(this.toggleConsoleButton); - // Will hold the list of filter elements this.filterBarElement = document.getElementById("console-filter"); - + function createDividerElement() { var dividerElement = document.createElement("div"); - dividerElement.addStyleClass("divider"); - this.filterBarElement.appendChild(dividerElement); } - + + var updateFilterHandler = this._updateFilter.bind(this); function createFilterElement(category) { var categoryElement = document.createElement("li"); categoryElement.category = category; - - categoryElement.addStyleClass(categoryElement.category); - + categoryElement.addStyleClass(categoryElement.category); + categoryElement.addEventListener("click", updateFilterHandler, false); + var label = category.toString(); categoryElement.appendChild(document.createTextNode(label)); - - categoryElement.addEventListener("click", this._updateFilter.bind(this), false); - + this.filterBarElement.appendChild(categoryElement); return categoryElement; } this.allElement = createFilterElement.call(this, "All"); - createDividerElement.call(this); - this.errorElement = createFilterElement.call(this, "Errors"); this.warningElement = createFilterElement.call(this, "Warnings"); this.logElement = createFilterElement.call(this, "Logs"); this.filter(this.allElement, false); + + this._shortcuts = {}; + + var shortcut; + var handler = this.clearMessages.bind(this, true); + + shortcut = WebInspector.KeyboardShortcut.makeKey("k", WebInspector.KeyboardShortcut.Modifiers.Meta); + this._shortcuts[shortcut] = handler; + this._shortcuts[shortcut].isMacOnly = true; + shortcut = WebInspector.KeyboardShortcut.makeKey("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl); + this._shortcuts[shortcut] = handler; + + this._customFormatters = { + "object": this._formatobject, + "array": this._formatarray, + "node": this._formatnode + }; } WebInspector.ConsoleView.prototype = { _updateFilter: function(e) { - var isMac = InspectorController.platform().indexOf("mac-") === 0; + var isMac = WebInspector.isMac(); var selectMultiple = false; if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) selectMultiple = true; @@ -242,7 +251,8 @@ WebInspector.ConsoleView.prototype = { this.promptElement.scrollIntoView(false); }, - updateMessageRepeatCount: function(count) { + updateMessageRepeatCount: function(count) + { var msg = this.previousMessage; var prevRepeatCount = msg.totalRepeatCount; @@ -260,7 +270,8 @@ WebInspector.ConsoleView.prototype = { } }, - _incrementErrorWarningCount: function(msg) { + _incrementErrorWarningCount: function(msg) + { switch (msg.level) { case WebInspector.ConsoleMessage.MessageLevel.Warning: WebInspector.warnings += msg.repeatDelta; @@ -274,7 +285,7 @@ WebInspector.ConsoleView.prototype = { clearMessages: function(clearInspectorController) { if (clearInspectorController) - InspectorController.clearMessages(false); + InspectorBackend.clearMessages(false); if (WebInspector.panels.resources) WebInspector.panels.resources.clearMessages(); @@ -396,6 +407,23 @@ WebInspector.ConsoleView.prototype = { return; } + if (isFnKey(event)) { + if (WebInspector.currentPanel && WebInspector.currentPanel.handleKeyEvent) { + WebInspector.currentPanel.handleKeyEvent(event); + return; + } + } + + var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); + var handler = this._shortcuts[shortcut]; + if (handler) { + if (!this._shortcuts[shortcut].isMacOnly || WebInspector.isMac()) { + handler(); + event.preventDefault(); + return; + } + } + this.prompt.handleKeyEvent(event); }, @@ -453,44 +481,18 @@ WebInspector.ConsoleView.prototype = { _format: function(output, forceObjectFormat) { var isProxy = (output != null && typeof output === "object"); + var type = (forceObjectFormat ? "object" : Object.proxyType(output)); - if (forceObjectFormat) - var type = "object"; - else - var type = Object.proxyType(output); - - if (isProxy && type !== "object" && type !== "function" && type !== "array" && type !== "node") { - // Unwrap primitive value, skip decoration. - output = output.description; - type = "undecorated" - } - - // We don't perform any special formatting on these types, so we just - // pass them through the simple _formatvalue function. - var undecoratedTypes = { - "undefined": 1, - "null": 1, - "boolean": 1, - "number": 1, - "undecorated": 1 - }; - - var formatter; - if (forceObjectFormat) - formatter = "_formatobject"; - else if (type in undecoratedTypes) - formatter = "_formatvalue"; - else { - formatter = "_format" + type; - if (!(formatter in this)) { - formatter = "_formatobject"; - type = "object"; - } + var formatter = this._customFormatters[type]; + if (!formatter || !isProxy) { + formatter = this._formatvalue; + output = output.description || output; + type = "undecorated"; } var span = document.createElement("span"); span.addStyleClass("console-formatted-" + type); - this[formatter](output, span); + formatter.call(this, output, span); return span; }, @@ -499,25 +501,27 @@ WebInspector.ConsoleView.prototype = { elem.appendChild(document.createTextNode(val)); }, - _formatfunction: function(func, elem) - { - elem.appendChild(document.createTextNode(func.description)); - }, - - _formatdate: function(date, elem) + _formatobject: function(obj, elem) { - elem.appendChild(document.createTextNode(date)); + elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, null, true).element); }, - _formatstring: function(str, elem) + _formatnode: function(object, elem) { - elem.appendChild(document.createTextNode("\"" + str + "\"")); - }, + function printNode(nodeId) + { + if (!nodeId) + return; + var treeOutline = new WebInspector.ElementsTreeOutline(); + treeOutline.showInElementsPanelEnabled = true; + treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); + treeOutline.element.addStyleClass("outline-disclosure"); + if (!treeOutline.children[0].hasChildren) + treeOutline.element.addStyleClass("single-node"); + elem.appendChild(treeOutline.element); + } - _formatregexp: function(re, elem) - { - var formatted = String(re.description).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); - elem.appendChild(document.createTextNode(formatted)); + InjectedScriptAccess.pushNodeToFrontend(object, printNode); }, _formatarray: function(arr, elem) @@ -529,6 +533,7 @@ WebInspector.ConsoleView.prototype = { { if (!properties) return; + var elements = []; for (var i = 0; i < properties.length; ++i) { var name = properties[i].name; @@ -547,53 +552,6 @@ WebInspector.ConsoleView.prototype = { elem.appendChild(document.createTextNode(", ")); } elem.appendChild(document.createTextNode("]")); - }, - - _formatnode: function(object, elem) - { - function printNode(nodeId) - { - if (!nodeId) - return; - var treeOutline = new WebInspector.ElementsTreeOutline(); - treeOutline.showInElementsPanelEnabled = true; - treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); - treeOutline.element.addStyleClass("outline-disclosure"); - if (!treeOutline.children[0].hasChildren) - treeOutline.element.addStyleClass("single-node"); - elem.appendChild(treeOutline.element); - } - InjectedScriptAccess.pushNodeToFrontend(object, printNode); - }, - - _formatobject: function(obj, elem) - { - elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, null, true).element); - }, - - _formaterror: function(obj, elem) - { - var messageElement = document.createElement("span"); - messageElement.className = "error-message"; - messageElement.textContent = obj.name + ": " + obj.message; - elem.appendChild(messageElement); - - if (obj.sourceURL) { - var urlElement = document.createElement("a"); - urlElement.className = "webkit-html-resource-link"; - urlElement.href = obj.sourceURL; - urlElement.lineNumber = obj.line; - urlElement.preferredPanel = "scripts"; - - if (obj.line > 0) - urlElement.textContent = WebInspector.displayNameForURL(obj.sourceURL) + ":" + obj.line; - else - urlElement.textContent = WebInspector.displayNameForURL(obj.sourceURL); - - elem.appendChild(document.createTextNode(" (")); - elem.appendChild(urlElement); - elem.appendChild(document.createTextNode(")")); - } } } @@ -648,62 +606,28 @@ WebInspector.ConsoleMessage.prototype = { _format: function(parameters) { + // This node is used like a Builder. Values are contintually appended onto it. var formattedResult = document.createElement("span"); - if (!parameters.length) return formattedResult; // Formatting code below assumes that parameters are all wrappers whereas frontend console - // API allows passing arbitrary values as messages (strings, numberts, etc.). Wrap them here. - for (var i = 0; i < parameters.length; ++i) { + // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here. + for (var i = 0; i < parameters.length; ++i) if (typeof parameters[i] !== "object" && typeof parameters[i] !== "function") parameters[i] = WebInspector.ObjectProxy.wrapPrimitiveValue(parameters[i]); - } - function formatForConsole(obj) - { - return WebInspector.console._format(obj); - } - - function formatAsObjectForConsole(obj) - { - return WebInspector.console._format(obj, true); - } - - if (Object.proxyType(parameters[0]) === "string") { - var formatters = {} - for (var i in String.standardFormatters) - formatters[i] = String.standardFormatters[i]; - - // Firebug uses %o for formatting objects. - formatters.o = formatForConsole; - // Firebug allows both %i and %d for formatting integers. - formatters.i = formatters.d; - // Support %O to force object formating, instead of the type-based %o formatting. - formatters.O = formatAsObjectForConsole; - - function append(a, b) - { - if (!(b instanceof Node)) - a.appendChild(WebInspector.linkifyStringAsFragment(b.toString())); - else - a.appendChild(b); - return a; - } - - var result = String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append); - formattedResult = result.formattedResult; + // Multiple parameters with the first being a format string. Save unused substitutions. + if (parameters.length > 1 && Object.proxyType(parameters[0]) === "string") { + var result = this._formatWithSubstitutionString(parameters, formattedResult) parameters = result.unusedSubstitutions; if (parameters.length) formattedResult.appendChild(document.createTextNode(" ")); } + // Single parameter, or unused substitutions from above. for (var i = 0; i < parameters.length; ++i) { - if (Object.proxyType(parameters[i]) === "string") - formattedResult.appendChild(WebInspector.linkifyStringAsFragment(parameters[i].description)); - else - formattedResult.appendChild(formatForConsole(parameters[i])); - + this._formatIndividualValue(parameters[i], formattedResult); if (i < parameters.length - 1) formattedResult.appendChild(document.createTextNode(" ")); } @@ -711,6 +635,51 @@ WebInspector.ConsoleMessage.prototype = { return formattedResult; }, + _formatWithSubstitutionString: function(parameters, formattedResult) + { + var formatters = {} + for (var i in String.standardFormatters) + formatters[i] = String.standardFormatters[i]; + + function consoleFormatWrapper(force) + { + return function(obj) { + return WebInspector.console._format(obj, force); + }; + } + + // Firebug uses %o for formatting objects. + formatters.o = consoleFormatWrapper(); + // Firebug allows both %i and %d for formatting integers. + formatters.i = formatters.d; + // Support %O to force object formating, instead of the type-based %o formatting. + formatters.O = consoleFormatWrapper(true); + + function append(a, b) + { + if (!(b instanceof Node)) + a.appendChild(WebInspector.linkifyStringAsFragment(b.toString())); + else + a.appendChild(b); + return a; + } + + // String.format does treat formattedResult like a Builder, result is an object. + return String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append); + }, + + _formatIndividualValue: function(param, formattedResult) + { + if (Object.proxyType(param) === "string") { + if (this.originatingCommand && this.level === WebInspector.ConsoleMessage.MessageLevel.Log) { + var quotedString = "\"" + param.description.replace(/"/g, "\\\"") + "\""; + formattedResult.appendChild(WebInspector.linkifyStringAsFragment(quotedString)); + } else + formattedResult.appendChild(WebInspector.linkifyStringAsFragment(param.description)); + } else + formattedResult.appendChild(WebInspector.console._format(param)); + }, + toMessageElement: function() { if (this._element) @@ -958,9 +927,9 @@ WebInspector.ConsoleCommandResult = function(result, exception, originatingComma var line = (exception ? result.line : -1); var url = (exception ? result.sourceURL : null); - WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, line, url, null, 1, message); - this.originatingCommand = originatingCommand; + + WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, line, url, null, 1, message); } WebInspector.ConsoleCommandResult.prototype = { diff --git a/WebCore/inspector/front-end/ContextMenu.js b/WebCore/inspector/front-end/ContextMenu.js new file mode 100644 index 0000000..3cdb152 --- /dev/null +++ b/WebCore/inspector/front-end/ContextMenu.js @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2009 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.ContextMenu = function() { + this._items = []; + this._handlers = {}; +} + +WebInspector.ContextMenu.prototype = { + show: function(event) + { + // Remove trailing separator. + while (this._items.length > 0 && !("id" in this._items[this._items.length - 1])) + this._items.splice(this._items.length - 1, 1); + + if (this._items.length) { + WebInspector._contextMenu = this; + InspectorFrontendHost.showContextMenu(event, this._items); + } + }, + + appendItem: function(label, handler) + { + var id = this._items.length; + this._items.push({id: id, label: label}); + this._handlers[id] = handler; + }, + + appendSeparator: function() + { + // No separator dupes allowed. + if (this._items.length === 0) + return; + if (!("id" in this._items[this._items.length - 1])) + return; + this._items.push({}); + }, + + _itemSelected: function(id) + { + if (this._handlers[id]) + this._handlers[id].call(this); + } +} + +WebInspector.contextMenuItemSelected = function(id) +{ + if (WebInspector._contextMenu) + WebInspector._contextMenu._itemSelected(id); +} + +WebInspector.contextMenuCleared = function() +{ + // FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected + // so we can't delete last menu object from WebInspector. Fix the contract. +} diff --git a/WebCore/inspector/front-end/CookieItemsView.js b/WebCore/inspector/front-end/CookieItemsView.js index 9f9845c..b31b7ea 100644 --- a/WebCore/inspector/front-end/CookieItemsView.js +++ b/WebCore/inspector/front-end/CookieItemsView.js @@ -67,7 +67,8 @@ WebInspector.CookieItemsView.prototype = { this.element.removeChildren(); var self = this; - function callback(cookies, isAdvanced) { + function callback(allCookies, isAdvanced) { + var cookies = self._cookiesForDomain(allCookies); var dataGrid = (isAdvanced ? self.dataGridForCookies(cookies) : self.simpleDataGridForCookies(cookies)); if (dataGrid) { self._dataGrid = dataGrid; @@ -85,7 +86,31 @@ WebInspector.CookieItemsView.prototype = { } } - WebInspector.Cookies.getCookiesAsync(callback, this._cookieDomain); + WebInspector.Cookies.getCookiesAsync(callback); + }, + + _cookiesForDomain: function(allCookies) + { + var cookiesForDomain = []; + var resourceURLsForDocumentURL = []; + + for (var id in WebInspector.resources) { + var resource = WebInspector.resources[id]; + var match = resource.documentURL.match(WebInspector.URLRegExp); + if (match && match[2] === this._cookieDomain) + resourceURLsForDocumentURL.push(resource.url); + } + + for (var i = 0; i < allCookies.length; ++i) { + for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) { + var resourceURL = resourceURLsForDocumentURL[j]; + if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) { + cookiesForDomain.push(allCookies[i]); + break; + } + } + } + return cookiesForDomain; }, dataGridForCookies: function(cookies) @@ -185,7 +210,7 @@ WebInspector.CookieItemsView.prototype = { for (var columnIdentifier in columns) columns[columnIdentifier].width += "%"; - var dataGrid = new WebInspector.DataGrid(columns); + var dataGrid = new WebInspector.DataGrid(columns, null, this._deleteCookieCallback.bind(this)); var length = nodes.length; for (var i = 0; i < length; ++i) dataGrid.appendChild(nodes[i]); @@ -258,11 +283,16 @@ WebInspector.CookieItemsView.prototype = { _deleteButtonClicked: function(event) { - if (!this._dataGrid) + if (!this._dataGrid || !this._dataGrid.selectedNode) return; - var cookie = this._dataGrid.selectedNode.cookie; - InspectorController.deleteCookie(cookie.name, this._cookieDomain); + this._deleteCookieCallback(this._dataGrid.selectedNode); + }, + + _deleteCookieCallback: function(node) + { + var cookie = node.cookie; + InspectorBackend.deleteCookie(cookie.name, this._cookieDomain); this.update(); }, diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js index 25ffafa..4ccf843 100644 --- a/WebCore/inspector/front-end/DOMAgent.js +++ b/WebCore/inspector/front-end/DOMAgent.js @@ -61,9 +61,10 @@ WebInspector.DOMNode = function(doc, payload) { this._matchedCSSRules = []; if (this.nodeType == Node.ELEMENT_NODE) { - if (this.nodeName == "HTML") + // HTML and BODY from internal iframes should not overwrite top-level ones. + if (!this.ownerDocument.documentElement && this.nodeName === "HTML") this.ownerDocument.documentElement = this; - if (this.nodeName == "BODY") + if (!this.ownerDocument.body && this.nodeName === "BODY") this.ownerDocument.body = this; } } @@ -178,6 +179,7 @@ WebInspector.DOMNode.prototype = { this.lastChild = this.children[this._childNodeCount - 1]; for (var i = 0; i < this._childNodeCount; ++i) { var child = this.children[i]; + child.index = i; child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null; child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null; child.parentNode = this; @@ -326,25 +328,25 @@ WebInspector.DOMAgent.prototype = { callback(parent.children); } var callId = WebInspector.Callback.wrap(mycallback); - InspectorController.getChildNodes(callId, parent.id); + InspectorBackend.getChildNodes(callId, parent.id); }, setAttributeAsync: function(node, name, value, callback) { var mycallback = this._didApplyDomChange.bind(this, node, callback); - InspectorController.setAttribute(WebInspector.Callback.wrap(mycallback), node.id, name, value); + InspectorBackend.setAttribute(WebInspector.Callback.wrap(mycallback), node.id, name, value); }, removeAttributeAsync: function(node, name, callback) { var mycallback = this._didApplyDomChange.bind(this, node, callback); - InspectorController.removeAttribute(WebInspector.Callback.wrap(mycallback), node.id, name); + InspectorBackend.removeAttribute(WebInspector.Callback.wrap(mycallback), node.id, name); }, setTextNodeValueAsync: function(node, text, callback) { var mycallback = this._didApplyDomChange.bind(this, node, callback); - InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node.id, text); + InspectorBackend.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node.id, text); }, _didApplyDomChange: function(node, callback, success) @@ -372,13 +374,13 @@ WebInspector.DOMAgent.prototype = { _setDocument: function(payload) { this._idToDOMNode = {}; - if (payload) { + if (payload && "id" in payload) { this.document = new WebInspector.DOMDocument(this, this._window, payload); this._idToDOMNode[payload.id] = this.document; this._bindNodes(this.document.children); } else this.document = null; - WebInspector.panels.elements.reset(); + WebInspector.panels.elements.setDocument(this.document); }, _setDetachedRoot: function(payload) @@ -437,7 +439,7 @@ WebInspector.DOMAgent.prototype = { WebInspector.Cookies = {} -WebInspector.Cookies.getCookiesAsync = function(callback, cookieDomain) +WebInspector.Cookies.getCookiesAsync = function(callback) { function mycallback(cookies, cookiesString) { if (cookiesString) @@ -446,7 +448,7 @@ WebInspector.Cookies.getCookiesAsync = function(callback, cookieDomain) callback(cookies, true); } var callId = WebInspector.Callback.wrap(mycallback); - InspectorController.getCookies(callId, cookieDomain); + InspectorBackend.getCookies(callId); } WebInspector.Cookies.buildCookiesFromString = function(rawCookieString) @@ -468,6 +470,28 @@ WebInspector.Cookies.buildCookiesFromString = function(rawCookieString) return cookies; } +WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL) +{ + var match = resourceURL.match(WebInspector.URLRegExp); + if (!match) + return false; + // See WebInspector.URLRegExp for definitions of the group index constants. + if (!this.cookieDomainMatchesResourceDomain(cookie.domain, match[2])) + return false; + var resourcePort = match[3] ? match[3] : undefined; + var resourcePath = match[4] ? match[4] : '/'; + return (resourcePath.indexOf(cookie.path) === 0 + && (!cookie.port || resourcePort == cookie.port) + && (!cookie.secure || match[1].toLowerCase() === 'https')); +} + +WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain) +{ + if (cookieDomain.charAt(0) !== '.') + return resourceDomain === cookieDomain; + return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i"); +} + WebInspector.EventListeners = {} WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callback) @@ -476,7 +500,7 @@ WebInspector.EventListeners.getEventListenersForNodeAsync = function(node, callb return; var callId = WebInspector.Callback.wrap(callback); - InspectorController.getEventListenersForNode(callId, node.id); + InspectorBackend.getEventListenersForNode(callId, node.id); } WebInspector.CSSStyleDeclaration = function(payload) diff --git a/WebCore/inspector/front-end/DOMStorage.js b/WebCore/inspector/front-end/DOMStorage.js index 03a10bf..c5f658d 100644 --- a/WebCore/inspector/front-end/DOMStorage.js +++ b/WebCore/inspector/front-end/DOMStorage.js @@ -57,19 +57,19 @@ WebInspector.DOMStorage.prototype = { getEntries: function(callback) { var callId = WebInspector.Callback.wrap(callback); - InspectorController.getDOMStorageEntries(callId, this._id); + InspectorBackend.getDOMStorageEntries(callId, this._id); }, setItem: function(key, value, callback) { var callId = WebInspector.Callback.wrap(callback); - InspectorController.setDOMStorageItem(callId, this._id, key, value); + InspectorBackend.setDOMStorageItem(callId, this._id, key, value); }, removeItem: function(key, callback) { var callId = WebInspector.Callback.wrap(callback); - InspectorController.removeDOMStorageItem(callId, this._id, key); + InspectorBackend.removeDOMStorageItem(callId, this._id, key); } } diff --git a/WebCore/inspector/front-end/DOMStorageDataGrid.js b/WebCore/inspector/front-end/DOMStorageDataGrid.js deleted file mode 100644 index 45a9ba1..0000000 --- a/WebCore/inspector/front-end/DOMStorageDataGrid.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2009 Nokia Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. 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.DOMStorageDataGrid = function(columns, domStorage, keys) -{ - WebInspector.DataGrid.call(this, columns); - this.dataTableBody.addEventListener("dblclick", this._ondblclick.bind(this), false); - this._domStorage = domStorage; - this._keys = keys; -} - -WebInspector.DOMStorageDataGrid.prototype = { - _ondblclick: function(event) - { - if (this._editing) - return; - if (this._editingNode) - return; - this._startEditing(event); - }, - - _startEditingColumnOfDataGridNode: function(node, column) - { - this._editing = true; - this._editingNode = node; - this._editingNode.select(); - - var element = this._editingNode._element.children[column]; - WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); - window.getSelection().setBaseAndExtent(element, 0, element, 1); - }, - - _startEditing: function(event) - { - var element = event.target.enclosingNodeOrSelfWithNodeName("td"); - if (!element) - return; - - this._editingNode = this.dataGridNodeFromEvent(event); - if (!this._editingNode) { - if (!this.creationNode) - return; - this._editingNode = this.creationNode; - } - - // Force editing the "Key" column when editing the creation node - if (this._editingNode.isCreationNode) - return this._startEditingColumnOfDataGridNode(this._editingNode, 0); - - this._editing = true; - WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); - window.getSelection().setBaseAndExtent(element, 0, element, 1); - }, - - _editingCommitted: function(element, newText, oldText, context, moveDirection) - { - var columnIdentifier = (element.hasStyleClass("0-column") ? 0 : 1); - var textBeforeEditing = this._editingNode.data[columnIdentifier]; - var currentEditingNode = this._editingNode; - - function moveToNextIfNeeded(wasChange) { - if (!moveDirection) - return; - - if (moveDirection === "forward") { - if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange) - return; - - if (columnIdentifier === 0) - return this._startEditingColumnOfDataGridNode(currentEditingNode, 1); - - var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); - if (nextDataGridNode) - return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0); - if (currentEditingNode.isCreationNode && wasChange) { - addCreationNode(false); - return this._startEditingColumnOfDataGridNode(this.creationNode, 0); - } - return; - } - - if (moveDirection === "backward") { - if (columnIdentifier === 1) - return this._startEditingColumnOfDataGridNode(currentEditingNode, 0); - var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true); - - if (nextDataGridNode) - return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1); - return; - } - } - - if (textBeforeEditing == newText) { - this._editingCancelled(element); - moveToNextIfNeeded.call(this, false); - return; - } - - var domStorage = this._domStorage; - if (columnIdentifier === 0) { - if (this._keys.indexOf(newText) !== -1) { - element.textContent = this._editingNode.data[0]; - this._editingCancelled(element); - moveToNextIfNeeded.call(this, false); - return; - } - domStorage.removeItem(this._editingNode.data[0]); - domStorage.setItem(newText, this._editingNode.data[1]); - this._editingNode.data[0] = newText; - } else { - domStorage.setItem(this._editingNode.data[0], newText); - this._editingNode.data[1] = newText; - } - - if (this._editingNode.isCreationNode) - this.addCreationNode(false); - - this._editingCancelled(element); - moveToNextIfNeeded.call(this, true); - }, - - _editingCancelled: function(element, context) - { - delete this._editing; - this._editingNode = null; - }, - - deleteSelectedRow: function() - { - var node = this.selectedNode; - if (!node || node.isCreationNode) - return; - - if (this._domStorage) - this._domStorage.removeItem(node.data[0]); - } -} - -WebInspector.DOMStorageDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype; diff --git a/WebCore/inspector/front-end/DOMStorageItemsView.js b/WebCore/inspector/front-end/DOMStorageItemsView.js index a7da370..7441f2e 100644 --- a/WebCore/inspector/front-end/DOMStorageItemsView.js +++ b/WebCore/inspector/front-end/DOMStorageItemsView.js @@ -65,22 +65,12 @@ WebInspector.DOMStorageItemsView.prototype = { this.domStorage.getEntries(callback); }, - _showDOMStorageEntries: function(entries) + _showDOMStorageEntries: function(entries) { - if (entries.length > 0) { - this._dataGrid = this._dataGridForDOMStorageEntries(entries); - this.element.appendChild(this._dataGrid.element); - this._dataGrid.updateWidths(); - this.deleteButton.visible = true; - } else { - var emptyMsgElement = document.createElement("div"); - emptyMsgElement.className = "storage-table-empty"; - if (this.domStorage) - emptyMsgElement.textContent = WebInspector.UIString("This storage is empty."); - this.element.appendChild(emptyMsgElement); - this._dataGrid = null; - this.deleteButton.visible = false; - } + this._dataGrid = this._dataGridForDOMStorageEntries(entries); + this.element.appendChild(this._dataGrid.element); + this._dataGrid.updateWidths(); + this.deleteButton.visible = true; }, resize: function() @@ -133,7 +123,7 @@ WebInspector.DOMStorageItemsView.prototype = { columns[0].width += "%"; columns[1].width += "%"; - var dataGrid = new WebInspector.DOMStorageDataGrid(columns, this.domStorage, keys); + var dataGrid = new WebInspector.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this)); var length = nodes.length; for (var i = 0; i < length; ++i) dataGrid.appendChild(nodes[i]); @@ -145,16 +135,41 @@ WebInspector.DOMStorageItemsView.prototype = { _deleteButtonClicked: function(event) { - if (this._dataGrid) { - this._dataGrid.deleteSelectedRow(); - - this.show(); - } + if (!this._dataGrid || !this._dataGrid.selectedNode) + return; + + this._deleteCallback(this._dataGrid.selectedNode); }, _refreshButtonClicked: function(event) { this.update(); + }, + + _editingCallback: function(editingNode, columnIdentifier, oldText, newText) + { + var domStorage = this.domStorage; + if (columnIdentifier === 0) { + if (oldText) + domStorage.removeItem(oldText); + + domStorage.setItem(newText, editingNode.data[1]); + } else { + domStorage.setItem(editingNode.data[0], newText); + } + + this.update(); + }, + + _deleteCallback: function(node) + { + if (!node || node.isCreationNode) + return; + + if (this.domStorage) + this.domStorage.removeItem(node.data[0]); + + this.update(); } } diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js index ce61548..7b58c8e 100644 --- a/WebCore/inspector/front-end/DataGrid.js +++ b/WebCore/inspector/front-end/DataGrid.js @@ -23,7 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.DataGrid = function(columns) +WebInspector.DataGrid = function(columns, editCallback, deleteCallback) { this.element = document.createElement("div"); this.element.className = "data-grid"; @@ -38,7 +38,16 @@ WebInspector.DataGrid = function(columns) this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true); this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true); - + + // FIXME: Add a createCallback which is different from editCallback and has different + // behavior when creating a new node. + if (editCallback) { + this._dataTable.addEventListener("dblclick", this._ondblclick.bind(this), false); + this._editCallback = editCallback; + } + if (deleteCallback) + this._deleteCallback = deleteCallback; + this.aligned = {}; var scrollContainer = document.createElement("div"); @@ -128,6 +137,116 @@ WebInspector.DataGrid = function(columns) } WebInspector.DataGrid.prototype = { + _ondblclick: function(event) + { + if (this._editing || this._editingNode) + return; + + this._startEditing(event.target); + }, + + _startEditingColumnOfDataGridNode: function(node, column) + { + this._editing = true; + this._editingNode = node; + this._editingNode.select(); + + var element = this._editingNode._element.children[column]; + WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + _startEditing: function(target) + { + var element = target.enclosingNodeOrSelfWithNodeName("td"); + if (!element) + return; + + this._editingNode = this.dataGridNodeFromNode(target); + if (!this._editingNode) { + if (!this.creationNode) + return; + this._editingNode = this.creationNode; + } + + // Force editing the 1st column when editing the creation node + if (this._editingNode.isCreationNode) + return this._startEditingColumnOfDataGridNode(this._editingNode, 0); + + this._editing = true; + WebInspector.startEditing(element, this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + _editingCommitted: function(element, newText, oldText, context, moveDirection) + { + // FIXME: We need more column identifiers here throughout this function. + // Not needed yet since only editable DataGrid is DOM Storage, which is Key - Value. + + // FIXME: Better way to do this than regular expressions? + var columnIdentifier = parseInt(element.className.match(/\b(\d+)-column\b/)[1]); + + var textBeforeEditing = this._editingNode.data[columnIdentifier]; + var currentEditingNode = this._editingNode; + + function moveToNextIfNeeded(wasChange) { + if (!moveDirection) + return; + + if (moveDirection === "forward") { + if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange) + return; + + if (columnIdentifier === 0) + return this._startEditingColumnOfDataGridNode(currentEditingNode, 1); + + var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); + if (nextDataGridNode) + return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0); + if (currentEditingNode.isCreationNode && wasChange) { + addCreationNode(false); + return this._startEditingColumnOfDataGridNode(this.creationNode, 0); + } + return; + } + + if (moveDirection === "backward") { + if (columnIdentifier === 1) + return this._startEditingColumnOfDataGridNode(currentEditingNode, 0); + var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true); + + if (nextDataGridNode) + return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1); + return; + } + } + + if (textBeforeEditing == newText) { + this._editingCancelled(element); + moveToNextIfNeeded.call(this, false); + return; + } + + // Update the text in the datagrid that we typed + this._editingNode.data[columnIdentifier] = newText; + + // Make the callback - expects an editing node (table row), the column number that is being edited, + // the text that used to be there, and the new text. + this._editCallback(this._editingNode, columnIdentifier, textBeforeEditing, newText); + + if (this._editingNode.isCreationNode) + this.addCreationNode(false); + + this._editingCancelled(element); + moveToNextIfNeeded.call(this, true); + }, + + _editingCancelled: function(element, context) + { + delete this._editing; + this._editingNode = null; + }, + get sortColumnIdentifier() { if (!this._sortColumnCell) @@ -266,6 +385,7 @@ WebInspector.DataGrid.prototype = { delete child._depth; delete child._revealed; delete child._attached; + child._shouldRefreshChildren = true; var current = child.children[0]; while (current) { @@ -273,6 +393,7 @@ WebInspector.DataGrid.prototype = { delete current._depth; delete current._revealed; delete current._attached; + current._shouldRefreshChildren = true; current = current.traverseNextNode(false, child, true); } @@ -350,7 +471,7 @@ WebInspector.DataGrid.prototype = { handleKeyEvent: function(event) { - if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey) + if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing) return false; var handled = false; @@ -396,6 +517,18 @@ WebInspector.DataGrid.prototype = { this.selectedNode.expand(); } } + } else if (event.keyCode === 8 || event.keyCode === 46) { + if (this._deleteCallback) { + handled = true; + this._deleteCallback(this.selectedNode); + } + } else if (isEnterKey(event)) { + if (this._editCallback) { + handled = true; + // The first child of the selected element is the <td class="0-column">, + // and that's what we want to edit. + this._startEditing(this.selectedNode._element.children[0]); + } } if (nextSelectedNode) { @@ -426,9 +559,9 @@ WebInspector.DataGrid.prototype = { // This is the root, do nothing. }, - dataGridNodeFromEvent: function(event) + dataGridNodeFromNode: function(target) { - var rowElement = event.target.enclosingNodeOrSelfWithNodeName("tr"); + var rowElement = target.enclosingNodeOrSelfWithNodeName("tr"); return rowElement._dataGridNode; }, @@ -473,7 +606,7 @@ WebInspector.DataGrid.prototype = { _mouseDownInDataTable: function(event) { - var gridNode = this.dataGridNodeFromEvent(event); + var gridNode = this.dataGridNodeFromNode(event.target); if (!gridNode || !gridNode.selectable) return; @@ -491,7 +624,7 @@ WebInspector.DataGrid.prototype = { _clickInDataTable: function(event) { - var gridNode = this.dataGridNodeFromEvent(event); + var gridNode = this.dataGridNodeFromNode(event.target); if (!gridNode || !gridNode.hasChildren) return; @@ -1019,6 +1152,30 @@ WebInspector.DataGridNode.prototype = { for (var i = 0; i < this.children.length; ++i) this.children[i]._detach(); + }, + + savePosition: function() + { + if (this._savedPosition) + return; + + if (!this.parent) + throw("savePosition: Node must have a parent."); + this._savedPosition = { + parent: this.parent, + index: this.parent.children.indexOf(this) + }; + }, + + restorePosition: function() + { + if (!this._savedPosition) + return; + + if (this.parent !== this._savedPosition.parent) + this._savedPosition.parent.insertChild(this, this._savedPosition.index); + + delete this._savedPosition; } } diff --git a/WebCore/inspector/front-end/Database.js b/WebCore/inspector/front-end/Database.js index 1a348fc..5edefb1 100644 --- a/WebCore/inspector/front-end/Database.js +++ b/WebCore/inspector/front-end/Database.js @@ -82,7 +82,7 @@ WebInspector.Database.prototype = { callback(names.sort()); } var callId = WebInspector.Callback.wrap(sortingCallback); - InspectorController.getDatabaseTableNames(callId, this._id); + InspectorBackend.getDatabaseTableNames(callId, this._id); }, executeSql: function(query, onSuccess, onError) diff --git a/WebCore/inspector/front-end/Drawer.js b/WebCore/inspector/front-end/Drawer.js index 1b50f91..0426a39 100644 --- a/WebCore/inspector/front-end/Drawer.js +++ b/WebCore/inspector/front-end/Drawer.js @@ -7,13 +7,13 @@ * are met: * * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -31,6 +31,12 @@ WebInspector.Drawer = function() { WebInspector.View.call(this, document.getElementById("drawer")); + this._savedHeight = 200; // Default. + this.state = WebInspector.Drawer.State.Hidden; + this.fullPanel = false; + + this.mainElement = document.getElementById("main"); + this.toolbarElement = document.getElementById("toolbar"); this.mainStatusBar = document.getElementById("main-status-bar"); this.mainStatusBar.addEventListener("mousedown", this._startStatusBarDragging.bind(this), true); this.viewStatusBar = document.getElementById("other-drawer-status-bar-items"); @@ -45,6 +51,8 @@ WebInspector.Drawer.prototype = { set visibleView(x) { if (this._visibleView === x) { + if (this.visible && this.fullPanel) + return; this.visible = !this.visible; return; } @@ -64,6 +72,12 @@ WebInspector.Drawer.prototype = { } }, + get savedHeight() + { + var height = this._savedHeight || this.element.offsetHeight; + return Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this.mainElement.totalOffsetTop - Preferences.minConsoleHeight); + }, + showView: function(view) { if (!this.visible || this.visibleView !== view) @@ -85,15 +99,16 @@ WebInspector.Drawer.prototype = { document.body.addStyleClass("drawer-visible"); var anchoredItems = document.getElementById("anchored-status-bar-items"); - + var height = (this.fullPanel ? window.innerHeight - this.toolbarElement.offsetHeight : this.savedHeight); var animations = [ - {element: document.getElementById("main"), end: {bottom: this.element.offsetHeight}}, + {element: this.element, end: {height: height}}, + {element: document.getElementById("main"), end: {bottom: height}}, {element: document.getElementById("main-status-bar"), start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}}, {element: document.getElementById("other-drawer-status-bar-items"), start: {opacity: 0}, end: {opacity: 1}} ]; - var consoleStatusBar = document.getElementById("drawer-status-bar"); - consoleStatusBar.insertBefore(anchoredItems, consoleStatusBar.firstChild); + var drawerStatusBar = document.getElementById("drawer-status-bar"); + drawerStatusBar.insertBefore(anchoredItems, drawerStatusBar.firstChild); function animationFinished() { @@ -102,9 +117,11 @@ WebInspector.Drawer.prototype = { if (this.visibleView.afterShow) this.visibleView.afterShow(); delete this._animating; + delete this._currentAnimationInterval; + this.state = (this.fullPanel ? WebInspector.Drawer.State.Full : WebInspector.Drawer.State.Variable); } - WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this)); + this._currentAnimationInterval = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this)); }, hide: function() @@ -113,20 +130,23 @@ WebInspector.Drawer.prototype = { return; WebInspector.View.prototype.hide.call(this); - + if (this.visibleView) this.visibleView.hide(); this._animating = true; + if (!this.fullPanel) + this._savedHeight = this.element.offsetHeight; + if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement)) WebInspector.currentFocusElement = WebInspector.previousFocusElement; var anchoredItems = document.getElementById("anchored-status-bar-items"); - // Temporally set properties and classes to mimic the post-animation values so panels + // Temporarily set properties and classes to mimic the post-animation values so panels // like Elements in their updateStatusBarItems call will size things to fit the final location. - document.getElementById("main-status-bar").style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px"); + this.mainStatusBar.style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px"); document.body.removeStyleClass("drawer-visible"); if ("updateStatusBarItems" in WebInspector.currentPanel) WebInspector.currentPanel.updateStatusBarItems(); @@ -145,9 +165,96 @@ WebInspector.Drawer.prototype = { mainStatusBar.style.removeProperty("padding-left"); document.body.removeStyleClass("drawer-visible"); delete this._animating; + delete this._currentAnimationInterval; + this.state = WebInspector.Drawer.State.Hidden; + } + + this._currentAnimationInterval = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this)); + }, + + resize: function() + { + if (this.state === WebInspector.Drawer.State.Hidden) + return; + + var height; + var mainElement = document.getElementById("main"); + if (this.state === WebInspector.Drawer.State.Variable) { + height = parseInt(this.element.style.height); + height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - mainElement.totalOffsetTop - Preferences.minConsoleHeight); + } else + height = window.innerHeight - this.toolbarElement.offsetHeight; + + mainElement.style.bottom = height + "px"; + this.element.style.height = height + "px"; + }, + + enterPanelMode: function() + { + this._cancelAnimationIfNeeded(); + this.fullPanel = true; + + if (this.visible) { + this._savedHeight = this.element.offsetHeight; + var height = window.innerHeight - this.toolbarElement.offsetHeight; + this._animateDrawerHeight(height, WebInspector.Drawer.State.Full); + } + }, + + exitPanelMode: function() + { + this._cancelAnimationIfNeeded(); + this.fullPanel = false; + + if (this.visible) { + // If this animation gets cancelled, we want the state of the drawer to be Variable, + // so that the new animation can't do an immediate transition between Hidden/Full states. + this.state = WebInspector.Drawer.State.Variable; + var height = this.savedHeight; + this._animateDrawerHeight(height, WebInspector.Drawer.State.Variable); + } + }, + + immediatelyExitPanelMode: function() + { + this.visible = false; + this.fullPanel = false; + }, + + _cancelAnimationIfNeeded: function() + { + if (this._animating) { + clearInterval(this._currentAnimationInterval); + delete this._animating; + delete this._currentAnimationInterval; + } + }, + + _animateDrawerHeight: function(height, finalState) + { + this._animating = true; + var animations = [ + {element: this.element, end: {height: height}}, + {element: document.getElementById("main"), end: {bottom: height}} + ]; + + function animationFinished() + { + delete this._animating; + delete this._currentAnimationInterval; + this.state = finalState; } - WebInspector.animateStyle(animations, window.event && window.event.shiftKey ? 2000 : 250, animationFinished.bind(this)); + this._currentAnimationInterval = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this)); + }, + + _animationDuration: function() + { + // Immediate if going between Hidden and Full in full panel mode + if (this.fullPanel && (this.state === WebInspector.Drawer.State.Hidden || this.state === WebInspector.Drawer.State.Full)) + return 0; + + return (window.event && window.event.shiftKey ? 2000 : 250); }, _safelyRemoveChildren: function() @@ -165,10 +272,10 @@ WebInspector.Drawer.prototype = { _startStatusBarDragging: function(event) { - if (!this.visible || event.target !== document.getElementById("main-status-bar")) + if (!this.visible || event.target !== this.mainStatusBar) return; - WebInspector.elementDragStart(document.getElementById("main-status-bar"), this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize"); + WebInspector.elementDragStart(this.mainStatusBar, this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize"); this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop; @@ -178,7 +285,6 @@ WebInspector.Drawer.prototype = { _statusBarDragging: function(event) { var mainElement = document.getElementById("main"); - var height = window.innerHeight - event.pageY + this._statusBarDragOffset; height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - mainElement.totalOffsetTop - Preferences.minConsoleHeight); @@ -193,6 +299,7 @@ WebInspector.Drawer.prototype = { { WebInspector.elementDragEnd(event); + this._savedHeight = this.element.offsetHeight; delete this._statusBarDragOffset; event.stopPropagation(); @@ -200,3 +307,9 @@ WebInspector.Drawer.prototype = { } WebInspector.Drawer.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.Drawer.State = { + Hidden: 0, + Variable: 1, + Full: 2 +}; diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js index aa6319c..9b18251 100644 --- a/WebCore/inspector/front-end/ElementsPanel.js +++ b/WebCore/inspector/front-end/ElementsPanel.js @@ -58,8 +58,8 @@ WebInspector.ElementsPanel = function() this.panel.updateProperties(); this.panel.updateEventListeners(); - if (InspectorController.searchingForNode()) { - InspectorController.toggleNodeSearch(); + if (InspectorBackend.searchingForNode()) { + InspectorBackend.toggleNodeSearch(); this.panel.nodeSearchButton.toggled = false; } if (this._focusedDOMNode) @@ -150,8 +150,8 @@ WebInspector.ElementsPanel.prototype = { WebInspector.hoveredDOMNode = null; - if (InspectorController.searchingForNode()) { - InspectorController.toggleNodeSearch(); + if (InspectorBackend.searchingForNode()) { + InspectorBackend.toggleNodeSearch(); this.nodeSearchButton.toggled = false; } }, @@ -164,13 +164,24 @@ WebInspector.ElementsPanel.prototype = { reset: function() { + if (this.focusedDOMNode) { + this._selectedPathOnReset = []; + var node = this.focusedDOMNode; + while ("index" in node) { + this._selectedPathOnReset.push(node.nodeName); + this._selectedPathOnReset.push(node.index); + node = node.parentNode; + } + this._selectedPathOnReset.reverse(); + } + this.rootDOMNode = null; this.focusedDOMNode = null; WebInspector.hoveredDOMNode = null; - if (InspectorController.searchingForNode()) { - InspectorController.toggleNodeSearch(); + if (InspectorBackend.searchingForNode()) { + InspectorBackend.toggleNodeSearch(); this.nodeSearchButton.toggled = false; } @@ -178,31 +189,48 @@ WebInspector.ElementsPanel.prototype = { delete this.currentQuery; this.searchCanceled(); + }, - var domWindow = WebInspector.domAgent.domWindow; - if (!domWindow || !domWindow.document || !domWindow.document.firstChild) - return; + setDocument: function(inspectedRootDocument) + { + this.reset(); - // If the window isn't visible, return early so the DOM tree isn't built - // and mutation event listeners are not added. - if (!InspectorController.isWindowVisible()) + if (!inspectedRootDocument) return; - var inspectedRootDocument = domWindow.document; inspectedRootDocument.addEventListener("DOMNodeInserted", this._nodeInserted.bind(this)); inspectedRootDocument.addEventListener("DOMNodeRemoved", this._nodeRemoved.bind(this)); + this.treeOutline.suppressSelectHighlight = true; this.rootDOMNode = inspectedRootDocument; + this.treeOutline.suppressSelectHighlight = false; - var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; - if (canidateFocusNode) { - this.treeOutline.suppressSelectHighlight = true; - this.focusedDOMNode = canidateFocusNode; - this.treeOutline.suppressSelectHighlight = false; + function selectNode(candidateFocusNode) + { + if (!candidateFocusNode) + candidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; + + if (!candidateFocusNode) + return; + this.treeOutline.suppressSelectHighlight = true; + this.focusedDOMNode = candidateFocusNode; if (this.treeOutline.selectedTreeElement) this.treeOutline.selectedTreeElement.expand(); + this.treeOutline.suppressSelectHighlight = false; + } + + function selectLastSelectedNode(nodeId) + { + var node = nodeId ? WebInspector.domAgent.nodeForId(nodeId) : 0; + selectNode.call(this, node); } + + if (this._selectedPathOnReset) + InjectedScriptAccess.nodeByPath(this._selectedPathOnReset, selectLastSelectedNode.bind(this)); + else + selectNode.call(this); + delete this._selectedPathOnReset; }, searchCanceled: function() @@ -525,7 +553,7 @@ WebInspector.ElementsPanel.prototype = { _mouseMovedOutOfCrumbs: function(event) { var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); - if (nodeUnderMouse.isDescendant(this.crumbsElement)) + if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.crumbsElement)) return; WebInspector.hoveredDOMNode = null; @@ -998,6 +1026,21 @@ WebInspector.ElementsPanel.prototype = { handleKeyEvent: function(event) { + // Cmd/Control + Shift + C should be a shortcut to clicking the Node Search Button. + // This shortcut matches Firebug. + if (event.keyIdentifier === "U+0043") { // C key + if (WebInspector.isMac()) + var isNodeSearchKey = event.metaKey && !event.ctrlKey && !event.altKey && event.shiftKey; + else + var isNodeSearchKey = event.ctrlKey && !event.metaKey && !event.altKey && event.shiftKey; + + if (isNodeSearchKey) { + this._nodeSearchButtonClicked(event); + event.preventDefault(); + return; + } + } + this.treeOutline.handleKeyEvent(event); }, @@ -1008,7 +1051,7 @@ WebInspector.ElementsPanel.prototype = { return; event.clipboardData.clearData(); event.preventDefault(); - InspectorController.copyNode(this.focusedDOMNode.id); + InspectorBackend.copyNode(this.focusedDOMNode.id); }, rightSidebarResizerDragStart: function(event) @@ -1037,9 +1080,9 @@ WebInspector.ElementsPanel.prototype = { _nodeSearchButtonClicked: function(event) { - InspectorController.toggleNodeSearch(); + InspectorBackend.toggleNodeSearch(); - this.nodeSearchButton.toggled = InspectorController.searchingForNode(); + this.nodeSearchButton.toggled = InspectorBackend.searchingForNode(); } } diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js index be01647..a035e7d 100644 --- a/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -41,6 +41,8 @@ WebInspector.ElementsTreeOutline = function() { this.showInElementsPanelEnabled = false; this.rootDOMNode = null; this.focusedDOMNode = null; + + this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); } WebInspector.ElementsTreeOutline.prototype = { @@ -83,7 +85,7 @@ WebInspector.ElementsTreeOutline.prototype = { this.focusedNodeChanged(); if (x && !this.suppressSelectHighlight) { - InspectorController.highlightDOMNode(x.id); + InspectorBackend.highlightDOMNode(x.id); if ("_restorePreviousHighlightNodeTimeout" in this) clearTimeout(this._restorePreviousHighlightNodeTimeout); @@ -92,9 +94,9 @@ WebInspector.ElementsTreeOutline.prototype = { { var hoveredNode = WebInspector.hoveredDOMNode; if (hoveredNode) - InspectorController.highlightDOMNode(hoveredNode.id); + InspectorBackend.highlightDOMNode(hoveredNode.id); else - InspectorController.hideDOMNodeHighlight(); + InspectorBackend.hideDOMNodeHighlight(); } this._restorePreviousHighlightNodeTimeout = setTimeout(restoreHighlightToHoveredNode, 2000); @@ -104,6 +106,8 @@ WebInspector.ElementsTreeOutline.prototype = { update: function() { + var selectedNode = this.selectedTreeElement ? this.selectedTreeElement.representedObject : null; + this.removeChildren(); if (!this.rootDOMNode) @@ -125,7 +129,8 @@ WebInspector.ElementsTreeOutline.prototype = { } } - this.updateSelection(); + if (selectedNode) + this.revealAndSelectNode(selectedNode); }, updateSelection: function() @@ -192,9 +197,10 @@ WebInspector.ElementsTreeOutline.prototype = { if (!selectedElement) return; - // Delete or backspace pressed, delete the node. - if (event.keyCode === 8 || event.keyCode === 46) { + if (event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Backspace || + event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Delete) { selectedElement.remove(); + event.preventDefault(); return; } @@ -255,6 +261,23 @@ WebInspector.ElementsTreeOutline.prototype = { } WebInspector.hoveredDOMNode = null; + }, + + _contextMenuEventFired: function(event) + { + var listItem = event.target.enclosingNodeOrSelfWithNodeName("LI"); + if (!listItem || !listItem.treeElement) + return; + + var contextMenu = new WebInspector.ContextMenu(); + + var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag"); + var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node"); + if (tag) + listItem.treeElement._populateTagContextMenu(contextMenu, event); + else if (textNode) + listItem.treeElement._populateTextContextMenu(contextMenu, textNode); + contextMenu.show(event); } } @@ -321,6 +344,26 @@ WebInspector.ElementsTreeElement.prototype = { } }, + createTooltipForImageNode: function(node, callback) + { + function createTooltipThenCallback(properties) + { + if (!properties) { + callback(); + return; + } + + var tooltipText = null; + if (properties.offsetHeight === properties.naturalHeight && properties.offsetWidth === properties.naturalWidth) + tooltipText = WebInspector.UIString("%d × %d pixels", properties.offsetWidth, properties.offsetHeight); + else + tooltipText = WebInspector.UIString("%d × %d pixels (Natural: %d × %d pixels)", properties.offsetWidth, properties.offsetHeight, properties.naturalWidth, properties.naturalHeight); + callback(tooltipText); + } + var objectProxy = new WebInspector.ObjectProxy(node.id); + WebInspector.ObjectProxy.getPropertiesAsync(objectProxy, ["naturalHeight", "naturalWidth", "offsetHeight", "offsetWidth"], createTooltipThenCallback); + }, + toggleNewAttributeButton: function(visible) { function removeAddAttributeSpan() @@ -525,12 +568,12 @@ WebInspector.ElementsTreeElement.prototype = { event.preventDefault(); }, - ondblclick: function(treeElement, event) + ondblclick: function(event) { if (this._editing) return; - if (this._startEditingFromEvent(event, treeElement)) + if (this._startEditingFromEvent(event)) return; if (this.hasChildren && !this.expanded) @@ -552,7 +595,7 @@ WebInspector.ElementsTreeElement.prototype = { this.updateSelection(); }, - _startEditingFromEvent: function(event, treeElement) + _startEditingFromEvent: function(event) { if (this.treeOutline.focusedDOMNode != this.representedObject) return; @@ -570,11 +613,31 @@ WebInspector.ElementsTreeElement.prototype = { var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute"); if (newAttribute) - return this._addNewAttribute(treeElement.listItemElement); + return this._addNewAttribute(); return false; }, + _populateTagContextMenu: function(contextMenu, event) + { + var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute"); + var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute"); + + // Add attribute-related actions. + contextMenu.appendItem(WebInspector.UIString("Add Attribute"), this._addNewAttribute.bind(this)); + if (attribute && !newAttribute) + contextMenu.appendItem(WebInspector.UIString("Edit Attribute"), this._startEditingAttribute.bind(this, attribute, event.target)); + contextMenu.appendSeparator(); + + // Add node-related actions. + contextMenu.appendItem(WebInspector.UIString("Delete Node"), this.remove.bind(this)); + }, + + _populateTextContextMenu: function(contextMenu, textNode) + { + contextMenu.appendItem(WebInspector.UIString("Edit Text"), this._startEditingTextNode.bind(this, textNode)); + }, + _startEditing: function() { if (this.treeOutline.focusedDOMNode !== this.representedObject) @@ -588,7 +651,7 @@ WebInspector.ElementsTreeElement.prototype = { if (attribute) return this._startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]); - return this._addNewAttribute(listItem); + return this._addNewAttribute(); } if (this.representedObject.nodeType === Node.TEXT_NODE) { @@ -599,7 +662,7 @@ WebInspector.ElementsTreeElement.prototype = { } }, - _addNewAttribute: function(listItemElement) + _addNewAttribute: function() { var attr = document.createElement("span"); attr.className = "webkit-html-attribute"; @@ -613,7 +676,7 @@ WebInspector.ElementsTreeElement.prototype = { attr.appendChild(name); attr.appendChild(value); - var tag = listItemElement.getElementsByClassName("webkit-html-tag")[0]; + var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0]; this._insertInLastAttributePosition(tag, attr); return this._startEditingAttribute(attr, attr); }, @@ -731,7 +794,6 @@ WebInspector.ElementsTreeElement.prototype = { if (!parseElement.hasAttributes()) { this.representedObject.removeAttribute(attributeName); - this._updateTitle(); moveToNextAttributeIfNeeded.call(this); return; } @@ -748,8 +810,6 @@ WebInspector.ElementsTreeElement.prototype = { if (!foundOriginalAttribute) this.representedObject.removeAttribute(attributeName); - this._updateTitle(); - this.treeOutline.focusedNodeChanged(true); moveToNextAttributeIfNeeded.call(this); @@ -768,26 +828,42 @@ WebInspector.ElementsTreeElement.prototype = { textNode = this.representedObject; textNode.nodeValue = newText; - this._updateTitle(); + + // No need to call _updateTitle here, it will be called after the nodeValue is committed. }, _editingCancelled: function(element, context) { delete this._editing; - this._updateTitle(); + // No need to call _updateTitle here, the editing code will revert to the original text. }, _updateTitle: function() { - var title = this._nodeTitleInfo(this.representedObject, this.hasChildren, WebInspector.linkifyURL).title; - this.title = "<span class=\"highlight\">" + title + "</span>"; - delete this.selectionElement; - this.updateSelection(); - this._preventFollowingLinksOnDoubleClick(); + // If we are editing, return early to prevent canceling the edit. + // After editing is committed _updateTitle will be called. + if (this._editing) + return; + + var self = this; + function callback(tooltipText) + { + var title = self._nodeTitleInfo(self.representedObject, self.hasChildren, WebInspector.linkifyURL, tooltipText).title; + self.title = "<span class=\"highlight\">" + title + "</span>"; + delete self.selectionElement; + self.updateSelection(); + self._preventFollowingLinksOnDoubleClick(); + }; + + // TODO: Replace with InjectedScriptAccess.getBasicProperties(obj, [names]). + if (this.representedObject.nodeName.toLowerCase() !== "img") + callback(); + else + this.createTooltipForImageNode(this.representedObject, callback); }, - _nodeTitleInfo: function(node, hasChildren, linkify) + _nodeTitleInfo: function(node, hasChildren, linkify, tooltipText) { var info = {title: "", hasChildren: hasChildren}; @@ -807,7 +883,7 @@ WebInspector.ElementsTreeElement.prototype = { var value = attr.value; if (linkify && (attr.name === "src" || attr.name === "href")) { var value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); - info.title += linkify(attr.value, value, "webkit-html-attribute-value", node.nodeName.toLowerCase() == "a"); + info.title += linkify(attr.value, value, "webkit-html-attribute-value", node.nodeName.toLowerCase() == "a", tooltipText); } else { var value = value.escapeHTML(); value = value.replace(/([\/;:\)\]\}])/g, "$1​"); @@ -847,8 +923,8 @@ WebInspector.ElementsTreeElement.prototype = { var newNode = document.createElement("span"); newNode.textContent = node.textContent; - var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighligher(null, null); - cssSyntaxHighlighter.syntaxHighlightLine(newNode, null); + var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighlighter(null, null); + cssSyntaxHighlighter.syntaxHighlightNode(newNode); info.title = "<span class=\"webkit-html-text-node webkit-html-css-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>"; } else { @@ -908,7 +984,7 @@ WebInspector.ElementsTreeElement.prototype = { } var callId = WebInspector.Callback.wrap(removeNodeCallback); - InspectorController.removeNode(callId, this.representedObject.id); + InspectorBackend.removeNode(callId, this.representedObject.id); } } diff --git a/WebCore/inspector/front-end/EventListenersSidebarPane.js b/WebCore/inspector/front-end/EventListenersSidebarPane.js index 2938196..c083c0e 100644 --- a/WebCore/inspector/front-end/EventListenersSidebarPane.js +++ b/WebCore/inspector/front-end/EventListenersSidebarPane.js @@ -108,7 +108,7 @@ WebInspector.EventListenersSidebarPane.prototype = { var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; Preferences.eventListenersFilter = selectedOption.value; - InspectorController.setSetting("event-listeners-filter", Preferences.eventListenersFilter); + InspectorFrontendHost.setSetting("event-listeners-filter", Preferences.eventListenersFilter); for (var i = 0; i < this.sections.length; ++i) this.sections[i].update(); diff --git a/WebCore/inspector/front-end/FontView.js b/WebCore/inspector/front-end/FontView.js index 4e1c931..8468cc9 100644 --- a/WebCore/inspector/front-end/FontView.js +++ b/WebCore/inspector/front-end/FontView.js @@ -36,7 +36,7 @@ WebInspector.FontView = function(resource) this.fontStyleElement = document.createElement("style"); this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }"; - document.getElementsByTagName("head").item(0).appendChild(this.fontStyleElement); + document.head.appendChild(this.fontStyleElement); this.fontPreviewElement = document.createElement("div"); this.fontPreviewElement.className = "preview"; diff --git a/WebCore/inspector/front-end/Images/consoleIcon.png b/WebCore/inspector/front-end/Images/consoleIcon.png Binary files differnew file mode 100644 index 0000000..94ffa95 --- /dev/null +++ b/WebCore/inspector/front-end/Images/consoleIcon.png diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index 3bed8da..209e99f 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -59,7 +59,8 @@ InjectedScript.getStyles = function(nodeId, authorOnly) var node = InjectedScript._nodeForId(nodeId); if (!node) return false; - var matchedRules = InjectedScript._window().getMatchedCSSRules(node, "", authorOnly); + var defaultView = node.ownerDocument.defaultView; + var matchedRules = defaultView.getMatchedCSSRules(node, "", authorOnly); var matchedCSSRules = []; for (var i = 0; matchedRules && i < matchedRules.length; ++i) matchedCSSRules.push(InjectedScript._serializeRule(matchedRules[i])); @@ -72,7 +73,7 @@ InjectedScript.getStyles = function(nodeId, authorOnly) } var result = {}; result.inlineStyle = InjectedScript._serializeStyle(node.style, true); - result.computedStyle = InjectedScript._serializeStyle(InjectedScript._window().getComputedStyle(node)); + result.computedStyle = InjectedScript._serializeStyle(defaultView.getComputedStyle(node)); result.matchedCSSRules = matchedCSSRules; result.styleAttributes = styleAttributes; return result; @@ -83,7 +84,7 @@ InjectedScript.getComputedStyle = function(nodeId) var node = InjectedScript._nodeForId(nodeId); if (!node) return false; - return InjectedScript._serializeStyle(InjectedScript._window().getComputedStyle(node)); + return InjectedScript._serializeStyle(node.ownerDocument.defaultView.getComputedStyle(node)); } InjectedScript.getInlineStyle = function(nodeId) @@ -230,15 +231,19 @@ InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId) InjectedScript.addStyleSelector = function(newContent, selectedNodeId) { - var stylesheet = InjectedScript.stylesheet; + var selectedNode = InjectedScript._nodeForId(selectedNodeId); + if (!selectedNode) + return false; + var ownerDocument = selectedNode.ownerDocument; + + var stylesheet = ownerDocument.__stylesheet; if (!stylesheet) { - var inspectedDocument = InjectedScript._window().document; - var head = inspectedDocument.getElementsByTagName("head")[0]; - var styleElement = inspectedDocument.createElement("style"); + var head = ownerDocument.head; + var styleElement = ownerDocument.createElement("style"); styleElement.type = "text/css"; head.appendChild(styleElement); - stylesheet = inspectedDocument.styleSheets[inspectedDocument.styleSheets.length - 1]; - InjectedScript.stylesheet = stylesheet; + stylesheet = ownerDocument.styleSheets[ownerDocument.styleSheets.length - 1]; + ownerDocument.__stylesheet = stylesheet; } try { @@ -248,7 +253,6 @@ InjectedScript.addStyleSelector = function(newContent, selectedNodeId) return false; } - var selectedNode = InjectedScript._nodeForId(selectedNodeId); var rule = stylesheet.cssRules[stylesheet.cssRules.length - 1]; rule.__isViaInspector = true; @@ -557,7 +561,7 @@ InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, obj { var result = {}; try { - result.value = InspectorController.wrapObject(InjectedScript._evaluateOn(evalFunction, object, expression), objectGroup); + result.value = InjectedScriptHost.wrapObject(InjectedScript._evaluateOn(evalFunction, object, expression), objectGroup); // Handle error that might have happened while describing result. if (result.value.errorText) { result.value = result.value.errorText; @@ -575,7 +579,7 @@ InjectedScript._evaluateOn = function(evalFunction, object, expression) InjectedScript._ensureCommandLineAPIInstalled(evalFunction, object); // Surround the expression in with statements to inject our command line API so that // the window object properties still take more precedent than our API functions. - expression = "with (window.console._inspectorCommandLineAPI) { with (window) { " + expression + " } }"; + expression = "with (window.console._inspectorCommandLineAPI) { with (window) {\n" + expression + "\n} }"; var value = evalFunction.call(object, expression); // When evaluating on call frame error is not thrown, but returned as a value. @@ -642,10 +646,10 @@ InjectedScript.performSearch = function(whitespaceTrimmedQuery) node[searchResultsProperty] = true; InjectedScript._searchResults.push(node); - var nodeId = InspectorController.pushNodePathToFrontend(node, false); + var nodeId = InjectedScriptHost.pushNodePathToFrontend(node, false); nodeIds.push(nodeId); } - InspectorController.addNodesToSearchResult(nodeIds.join(",")); + InjectedScriptHost.addNodesToSearchResult(nodeIds.join(",")); } function matchExactItems(doc) @@ -844,7 +848,7 @@ InjectedScript.openInInspectedWindow = function(url) InjectedScript.getCallFrames = function() { - var callFrame = InspectorController.currentCallFrame(); + var callFrame = InjectedScriptHost.currentCallFrame(); if (!callFrame) return false; @@ -867,7 +871,7 @@ InjectedScript.evaluateInCallFrame = function(callFrameId, code, objectGroup) InjectedScript._callFrameForId = function(id) { - var callFrame = InspectorController.currentCallFrame(); + var callFrame = InjectedScriptHost.currentCallFrame(); while (--id >= 0 && callFrame) callFrame = callFrame.caller; return callFrame; @@ -875,7 +879,7 @@ InjectedScript._callFrameForId = function(id) InjectedScript._clearConsoleMessages = function() { - InspectorController.clearMessages(true); + InjectedScriptHost.clearMessages(true); } InjectedScript._inspectObject = function(o) @@ -886,90 +890,105 @@ InjectedScript._inspectObject = function(o) var inspectedWindow = InjectedScript._window(); inspectedWindow.console.log(o); if (Object.type(o) === "node") { - InspectorController.pushNodePathToFrontend(o, true); + InjectedScriptHost.pushNodePathToFrontend(o, true); } else { switch (Object.describe(o)) { case "Database": - InspectorController.selectDatabase(o); + InjectedScriptHost.selectDatabase(o); break; case "Storage": - InspectorController.selectDOMStorage(o); + InjectedScriptHost.selectDOMStorage(o); break; } } } +InjectedScript._copy = function(o) +{ + if (Object.type(o) === "node") { + var nodeId = InjectedScriptHost.pushNodePathToFrontend(o, false); + InjectedScriptHost.copyNode(nodeId); + } else { + InjectedScriptHost.copyText(o); + } +} + InjectedScript._ensureCommandLineAPIInstalled = function(evalFunction, evalObject) { if (evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI")) return; - var inspectorCommandLineAPI = evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI = { \ - $: function() { return document.getElementById.apply(document, arguments) }, \ - $$: function() { return document.querySelectorAll.apply(document, arguments) }, \ - $x: function(xpath, context) { \ - var nodes = []; \ - try { \ - var doc = context || document; \ - var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \ - var node; \ - while (node = results.iterateNext()) nodes.push(node); \ - } catch (e) {} \ - return nodes; \ - }, \ - dir: function() { return console.dir.apply(console, arguments) }, \ - dirxml: function() { return console.dirxml.apply(console, arguments) }, \ - keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \ - values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \ - profile: function() { return console.profile.apply(console, arguments) }, \ - profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \ - _logEvent: function _inspectorCommandLineAPI_logEvent(e) { console.log(e.type, e); }, \ - _allEventTypes: [\"mouse\", \"key\", \"load\", \"unload\", \"abort\", \"error\", \ - \"select\", \"change\", \"submit\", \"reset\", \"focus\", \"blur\", \ - \"resize\", \"scroll\"], \ - _normalizeEventTypes: function(t) { \ - if (typeof t === \"undefined\") \ - t = _inspectorCommandLineAPI._allEventTypes; \ - else if (typeof t === \"string\") \ - t = [t]; \ - var i, te = []; \ - for (i = 0; i < t.length; i++) { \ - if (t[i] === \"mouse\") \ - te.splice(0, 0, \"mousedown\", \"mouseup\", \"click\", \"dblclick\", \ - \"mousemove\", \"mouseover\", \"mouseout\"); \ - else if (t[i] === \"key\") \ - te.splice(0, 0, \"keydown\", \"keyup\", \"keypress\"); \ - else \ - te.push(t[i]); \ - } \ - return te; \ - }, \ - monitorEvent: function(o, t) { \ - if (!o || !o.addEventListener || !o.removeEventListener) \ - return; \ - t = _inspectorCommandLineAPI._normalizeEventTypes(t); \ - for (i = 0; i < t.length; i++) { \ - o.removeEventListener(t[i], _inspectorCommandLineAPI._logEvent, false); \ - o.addEventListener(t[i], _inspectorCommandLineAPI._logEvent, false); \ - } \ - }, \ - unmonitorEvent: function(o, t) { \ - if (!o || !o.removeEventListener) \ - return; \ - t = _inspectorCommandLineAPI._normalizeEventTypes(t); \ - for (i = 0; i < t.length; i++) { \ - o.removeEventListener(t[i], _inspectorCommandLineAPI._logEvent, false); \ - } \ - }, \ - _inspectedNodes: [], \ - get $0() { return console._inspectorCommandLineAPI._inspectedNodes[0] }, \ - get $1() { return console._inspectorCommandLineAPI._inspectedNodes[1] }, \ - get $2() { return console._inspectorCommandLineAPI._inspectedNodes[2] }, \ - get $3() { return console._inspectorCommandLineAPI._inspectedNodes[3] }, \ - get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] } \ + var inspectorCommandLineAPI = evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI = { \n\ + $: function() { return document.getElementById.apply(document, arguments) }, \n\ + $$: function() { return document.querySelectorAll.apply(document, arguments) }, \n\ + $x: function(xpath, context) \n\ + { \n\ + var nodes = []; \n\ + try { \n\ + var doc = context || document; \n\ + var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \n\ + var node; \n\ + while (node = results.iterateNext()) nodes.push(node); \n\ + } catch (e) {} \n\ + return nodes; \n\ + }, \n\ + dir: function() { return console.dir.apply(console, arguments) }, \n\ + dirxml: function() { return console.dirxml.apply(console, arguments) }, \n\ + keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \n\ + values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \n\ + profile: function() { return console.profile.apply(console, arguments) }, \n\ + profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \n\ + _logEvent: function _inspectorCommandLineAPI_logEvent(e) { console.log(e.type, e); }, \n\ + _allEventTypes: [\"mouse\", \"key\", \"load\", \"unload\", \"abort\", \"error\", \n\ + \"select\", \"change\", \"submit\", \"reset\", \"focus\", \"blur\", \n\ + \"resize\", \"scroll\"], \n\ + _normalizeEventTypes: function(t) \n\ + { \n\ + if (typeof t === \"undefined\") \n\ + t = console._inspectorCommandLineAPI._allEventTypes; \n\ + else if (typeof t === \"string\") \n\ + t = [t]; \n\ + var i, te = []; \n\ + for (i = 0; i < t.length; i++) { \n\ + if (t[i] === \"mouse\") \n\ + te.splice(0, 0, \"mousedown\", \"mouseup\", \"click\", \"dblclick\", \n\ + \"mousemove\", \"mouseover\", \"mouseout\"); \n\ + else if (t[i] === \"key\") \n\ + te.splice(0, 0, \"keydown\", \"keyup\", \"keypress\"); \n\ + else \n\ + te.push(t[i]); \n\ + } \n\ + return te; \n\ + }, \n\ + monitorEvents: function(o, t) \n\ + { \n\ + if (!o || !o.addEventListener || !o.removeEventListener) \n\ + return; \n\ + t = console._inspectorCommandLineAPI._normalizeEventTypes(t); \n\ + for (i = 0; i < t.length; i++) { \n\ + o.removeEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\ + o.addEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\ + } \n\ + }, \n\ + unmonitorEvents: function(o, t) \n\ + { \n\ + if (!o || !o.removeEventListener) \n\ + return; \n\ + t = console._inspectorCommandLineAPI._normalizeEventTypes(t); \n\ + for (i = 0; i < t.length; i++) { \n\ + o.removeEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\ + } \n\ + }, \n\ + _inspectedNodes: [], \n\ + get $0() { return console._inspectorCommandLineAPI._inspectedNodes[0] }, \n\ + get $1() { return console._inspectorCommandLineAPI._inspectedNodes[1] }, \n\ + get $2() { return console._inspectorCommandLineAPI._inspectedNodes[2] }, \n\ + get $3() { return console._inspectorCommandLineAPI._inspectedNodes[3] }, \n\ + get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] }, \n\ };"); - inspectorCommandLineAPI.clear = InspectorController.wrapCallback(InjectedScript._clearConsoleMessages); - inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(InjectedScript._inspectObject); + inspectorCommandLineAPI.clear = InjectedScriptHost.wrapCallback(InjectedScript._clearConsoleMessages); + inspectorCommandLineAPI.inspect = InjectedScriptHost.wrapCallback(InjectedScript._inspectObject); + inspectorCommandLineAPI.copy = InjectedScriptHost.wrapCallback(InjectedScript._copy); } InjectedScript._resolveObject = function(objectProxy) @@ -993,14 +1012,14 @@ InjectedScript._window = function() { // TODO: replace with 'return window;' once this script is injected into // the page's context. - return InspectorController.inspectedWindow(); + return InjectedScriptHost.inspectedWindow(); } InjectedScript._nodeForId = function(nodeId) { if (!nodeId) return null; - return InspectorController.nodeForId(nodeId); + return InjectedScriptHost.nodeForId(nodeId); } InjectedScript._objectForId = function(objectId) @@ -1012,7 +1031,7 @@ InjectedScript._objectForId = function(objectId) if (typeof objectId === "number") { return InjectedScript._nodeForId(objectId); } else if (typeof objectId === "string") { - return InspectorController.unwrapObject(objectId); + return InjectedScriptHost.unwrapObject(objectId); } else if (typeof objectId === "object") { var callFrame = InjectedScript._callFrameForId(objectId.callFrame); if (objectId.thisObject) @@ -1028,7 +1047,14 @@ InjectedScript.pushNodeToFrontend = function(objectProxy) var object = InjectedScript._resolveObject(objectProxy); if (!object || Object.type(object) !== "node") return false; - return InspectorController.pushNodePathToFrontend(object, false); + return InjectedScriptHost.pushNodePathToFrontend(object, false); +} + +InjectedScript.nodeByPath = function(path) +{ + // We make this call through the injected script only to get a nice + // callback for it. + return InjectedScriptHost.pushNodeByPathToFrontend(path.join(",")); } // Called from within InspectorController on the 'inspected page' side. @@ -1111,23 +1137,23 @@ InjectedScript.executeSql = function(callId, databaseId, query) data[columnIdentifier] = String(text); } } - InspectorController.reportDidDispatchOnInjectedScript(callId, JSON.stringify(result), false); + InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, JSON.stringify(result), false); } function errorCallback(tx, error) { - InspectorController.reportDidDispatchOnInjectedScript(callId, JSON.stringify(error), false); + InjectedScriptHost.reportDidDispatchOnInjectedScript(callId, JSON.stringify(error), false); } function queryTransaction(tx) { - tx.executeSql(query, null, InspectorController.wrapCallback(successCallback), InspectorController.wrapCallback(errorCallback)); + tx.executeSql(query, null, InjectedScriptHost.wrapCallback(successCallback), InjectedScriptHost.wrapCallback(errorCallback)); } - var database = InspectorController.databaseForId(databaseId); + var database = InjectedScriptHost.databaseForId(databaseId); if (!database) errorCallback(null, { code : 2 }); // Return as unexpected version. - database.transaction(InspectorController.wrapCallback(queryTransaction), InspectorController.wrapCallback(errorCallback)); + database.transaction(InjectedScriptHost.wrapCallback(queryTransaction), InjectedScriptHost.wrapCallback(errorCallback)); return true; } @@ -1197,8 +1223,6 @@ Object.describe = function(obj, abbreviated) else if (abbreviated) objectText = /.*/.exec(obj)[0].replace(/ +$/g, ""); return objectText; - case "regexp": - return String(obj).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); default: return String(obj); } diff --git a/WebCore/inspector/front-end/InjectedScriptAccess.js b/WebCore/inspector/front-end/InjectedScriptAccess.js index c6d4b65..14a3a6b 100644 --- a/WebCore/inspector/front-end/InjectedScriptAccess.js +++ b/WebCore/inspector/front-end/InjectedScriptAccess.js @@ -47,11 +47,11 @@ InjectedScriptAccess._installHandler = function(methodName, async) WebInspector.console.addMessage(new WebInspector.ConsoleTextMessage("Error dispatching: " + methodName)); } var callId = WebInspector.Callback.wrap(myCallback); - InspectorController.dispatchOnInjectedScript(callId, methodName, argsString, !!async); + InspectorBackend.dispatchOnInjectedScript(callId, methodName, argsString, !!async); }; } -// InjectedScriptAccess message forwarding puts some constraints on the way methods are imlpemented and called: +// InjectedScriptAccess message forwarding puts some constraints on the way methods are implemented and called: // - Make sure corresponding methods in InjectedScript return non-null and non-undefined values, // - Make sure last parameter of all the InjectedSriptAccess.* calls is a callback function. // We keep these sorted. @@ -70,6 +70,7 @@ InjectedScriptAccess._installHandler("getStyles"); InjectedScriptAccess._installHandler("openInInspectedWindow"); InjectedScriptAccess._installHandler("performSearch"); InjectedScriptAccess._installHandler("pushNodeToFrontend"); +InjectedScriptAccess._installHandler("nodeByPath"); InjectedScriptAccess._installHandler("searchCanceled"); InjectedScriptAccess._installHandler("setPropertyValue"); InjectedScriptAccess._installHandler("setStyleProperty"); diff --git a/WebCore/inspector/front-end/InspectorBackendStub.js b/WebCore/inspector/front-end/InspectorBackendStub.js new file mode 100644 index 0000000..1710b12 --- /dev/null +++ b/WebCore/inspector/front-end/InspectorBackendStub.js @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2009 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. + */ + +if (!window.InspectorBackend) { + +WebInspector.InspectorBackendStub = function() +{ + this._searchingForNode = false; + this._attachedWindowHeight = 0; + this._debuggerEnabled = true; + this._profilerEnabled = true; + this._resourceTrackingEnabled = false; + this._timelineEnabled = false; + this._settings = {}; +} + +WebInspector.InspectorBackendStub.prototype = { + wrapCallback: function(func) + { + return func; + }, + + platform: function() + { + return "mac-leopard"; + }, + + port: function() + { + return "unknown"; + }, + + + closeWindow: function() + { + this._windowVisible = false; + }, + + attach: function() + { + }, + + detach: function() + { + }, + + storeLastActivePanel: function(panel) + { + }, + + clearMessages: function() + { + }, + + searchingForNode: function() + { + return this._searchingForNode; + }, + + search: function(sourceRow, query) + { + }, + + toggleNodeSearch: function() + { + this._searchingForNode = !this._searchingForNode; + }, + + setAttachedWindowHeight: function(height) + { + }, + + moveByUnrestricted: function(x, y) + { + }, + + + addResourceSourceToFrame: function(identifier, element) + { + }, + + addSourceToFrame: function(mimeType, source, element) + { + return false; + }, + + getResourceDocumentNode: function(identifier) + { + return undefined; + }, + + highlightDOMNode: function(node) + { + }, + + hideDOMNodeHighlight: function() + { + }, + + inspectedWindow: function() + { + return window; + }, + + loaded: function() + { + }, + + localizedStringsURL: function() + { + return undefined; + }, + + windowUnloading: function() + { + return false; + }, + + hiddenPanels: function() + { + return ""; + }, + + debuggerEnabled: function() + { + return this._debuggerEnabled; + }, + + enableResourceTracking: function() + { + this._resourceTrackingEnabled = true; + WebInspector.resourceTrackingWasEnabled(); + }, + + disableResourceTracking: function() + { + this._resourceTrackingEnabled = false; + WebInspector.resourceTrackingWasDisabled(); + }, + + resourceTrackingEnabled: function() + { + return this._resourceTrackingEnabled; + }, + + enableDebugger: function() + { + this._debuggerEnabled = true; + }, + + disableDebugger: function() + { + this._debuggerEnabled = false; + }, + + addBreakpoint: function(sourceID, line, condition) + { + }, + + removeBreakpoint: function(sourceID, line) + { + }, + + updateBreakpoint: function(sourceID, line, condition) + { + }, + + pauseInDebugger: function() + { + }, + + pauseOnExceptions: function() + { + return false; + }, + + setPauseOnExceptions: function(value) + { + }, + + resumeDebugger: function() + { + }, + + profilerEnabled: function() + { + return true; + }, + + enableProfiler: function() + { + this._profilerEnabled = true; + }, + + disableProfiler: function() + { + this._profilerEnabled = false; + }, + + startProfiling: function() + { + }, + + stopProfiling: function() + { + }, + + getProfileHeaders: function(callId) + { + WebInspector.didGetProfileHeaders(callId, []); + }, + + getProfile: function(callId, uid) + { + if (WebInspector.__fullProfiles && (uid in WebInspector.__fullProfiles)) + { + WebInspector.didGetProfile(callId, WebInspector.__fullProfiles[uid]); + } + }, + + takeHeapSnapshot: function() + { + }, + + databaseTableNames: function(database) + { + return []; + }, + + stepIntoStatementInDebugger: function() + { + }, + + stepOutOfFunctionInDebugger: function() + { + }, + + stepOverStatementInDebugger: function() + { + }, + + setSetting: function(setting, value) + { + this._settings[setting] = value; + }, + + dispatchOnInjectedScript: function() + { + }, + + releaseWrapperObjectGroup: function() + { + }, + + setting: function(setting) + { + return this._settings[setting]; + } +} + +InspectorBackend = new WebInspector.InspectorBackendStub(); + +} diff --git a/WebCore/inspector/front-end/InspectorControllerStub.js b/WebCore/inspector/front-end/InspectorControllerStub.js index 6fb5a1b..e69de29 100644 --- a/WebCore/inspector/front-end/InspectorControllerStub.js +++ b/WebCore/inspector/front-end/InspectorControllerStub.js @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2009 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. - */ - -if (!window.InspectorController) { - -WebInspector.InspectorControllerStub = function() -{ - this._searchingForNode = false; - this._windowVisible = true; - this._attachedWindowHeight = 0; - this._debuggerEnabled = true; - this._profilerEnabled = true; - this._resourceTrackingEnabled = false; - this._timelineEnabled = false; - this._settings = {}; -} - -WebInspector.InspectorControllerStub.prototype = { - wrapCallback: function(func) - { - return func; - }, - - isWindowVisible: function() - { - return this._windowVisible; - }, - - platform: function() - { - return "mac-leopard"; - }, - - - closeWindow: function() - { - this._windowVisible = false; - }, - - attach: function() - { - }, - - detach: function() - { - }, - - storeLastActivePanel: function(panel) - { - }, - - clearMessages: function() - { - }, - - searchingForNode: function() - { - return this._searchingForNode; - }, - - search: function(sourceRow, query) - { - }, - - toggleNodeSearch: function() - { - this._searchingForNode = !this._searchingForNode; - }, - - setAttachedWindowHeight: function(height) - { - }, - - moveByUnrestricted: function(x, y) - { - }, - - - addResourceSourceToFrame: function(identifier, element) - { - }, - - addSourceToFrame: function(mimeType, source, element) - { - return false; - }, - - getResourceDocumentNode: function(identifier) - { - return undefined; - }, - - highlightDOMNode: function(node) - { - }, - - hideDOMNodeHighlight: function() - { - }, - - inspectedWindow: function() - { - return window; - }, - - loaded: function() - { - }, - - localizedStringsURL: function() - { - return undefined; - }, - - windowUnloading: function() - { - return false; - }, - - hiddenPanels: function() - { - return ""; - }, - - debuggerEnabled: function() - { - return this._debuggerEnabled; - }, - - enableResourceTracking: function() - { - this._resourceTrackingEnabled = true; - WebInspector.resourceTrackingWasEnabled(); - }, - - disableResourceTracking: function() - { - this._resourceTrackingEnabled = false; - WebInspector.resourceTrackingWasDisabled(); - }, - - resourceTrackingEnabled: function() - { - return this._resourceTrackingEnabled; - }, - - enableDebugger: function() - { - this._debuggerEnabled = true; - }, - - disableDebugger: function() - { - this._debuggerEnabled = false; - }, - - addBreakpoint: function(sourceID, line, condition) - { - }, - - removeBreakpoint: function(sourceID, line) - { - }, - - updateBreakpoint: function(sourceID, line, condition) - { - }, - - pauseInDebugger: function() - { - }, - - pauseOnExceptions: function() - { - return false; - }, - - setPauseOnExceptions: function(value) - { - }, - - resumeDebugger: function() - { - }, - - profilerEnabled: function() - { - return true; - }, - - enableProfiler: function() - { - this._profilerEnabled = true; - }, - - disableProfiler: function() - { - this._profilerEnabled = false; - }, - - startProfiling: function() - { - }, - - stopProfiling: function() - { - }, - - getProfileHeaders: function(callId) - { - WebInspector.didGetProfileHeaders(callId, []); - }, - - getProfile: function(callId, uid) - { - if (WebInspector.__fullProfiles && (uid in WebInspector.__fullProfiles)) - { - WebInspector.didGetProfile(callId, WebInspector.__fullProfiles[uid]); - } - }, - - takeHeapSnapshot: function() - { - }, - - databaseTableNames: function(database) - { - return []; - }, - - stepIntoStatementInDebugger: function() - { - }, - - stepOutOfFunctionInDebugger: function() - { - }, - - stepOverStatementInDebugger: function() - { - }, - - setSetting: function(setting, value) - { - this._settings[setting] = value; - }, - - dispatchOnInjectedScript: function() - { - }, - - releaseWrapperObjectGroup: function() - { - }, - - setting: function(setting) - { - return this._settings[setting]; - } -} - -window.InspectorController = new WebInspector.InspectorControllerStub(); - -} diff --git a/WebCore/inspector/front-end/InspectorFrontendHostStub.js b/WebCore/inspector/front-end/InspectorFrontendHostStub.js new file mode 100644 index 0000000..facea4e --- /dev/null +++ b/WebCore/inspector/front-end/InspectorFrontendHostStub.js @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 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. + */ + +if (!window.InspectorFrontendHost) { + +WebInspector.InspectorFrontendHostStub = function() +{ + this._attachedWindowHeight = 0; + this._settings = {}; +} + +WebInspector.InspectorFrontendHostStub.prototype = { + platform: function() + { + return "mac-leopard"; + }, + + port: function() + { + return "unknown"; + }, + + closeWindow: function() + { + this._windowVisible = false; + }, + + attach: function() + { + }, + + detach: function() + { + }, + + search: function(sourceRow, query) + { + }, + + setAttachedWindowHeight: function(height) + { + }, + + moveWindowBy: function(x, y) + { + }, + + addResourceSourceToFrame: function(identifier, element) + { + }, + + addSourceToFrame: function(mimeType, source, element) + { + return false; + }, + + loaded: function() + { + }, + + localizedStringsURL: function() + { + return undefined; + }, + + hiddenPanels: function() + { + return ""; + }, + + setSetting: function(setting, value) + { + this._settings[setting] = value; + }, + + setting: function(setting) + { + return this._settings[setting]; + } +} + +InspectorFrontendHost = new WebInspector.InspectorFrontendHostStub(); + +} diff --git a/WebCore/inspector/front-end/KeyboardShortcut.js b/WebCore/inspector/front-end/KeyboardShortcut.js index ed28a48..0a068d5 100644 --- a/WebCore/inspector/front-end/KeyboardShortcut.js +++ b/WebCore/inspector/front-end/KeyboardShortcut.js @@ -44,6 +44,7 @@ WebInspector.KeyboardShortcut.Modifiers = { }; WebInspector.KeyboardShortcut.KeyCodes = { + Backspace: 8, Esc: 27, Space: 32, PageUp: 33, // also NUM_NORTH_EAST @@ -54,6 +55,7 @@ WebInspector.KeyboardShortcut.KeyCodes = { Up: 38, // also NUM_NORTH Right: 39, // also NUM_EAST Down: 40, // also NUM_SOUTH + Delete: 46, F1: 112, F2: 113, F3: 114, @@ -76,12 +78,14 @@ WebInspector.KeyboardShortcut.KeyCodes = { /** * Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits. - * It is usefull for matching pressed keys. - * @param {number} keyCode Code of the key. - * @param {number} optModifiers Optional list of modifiers passed as additional paramerters. + * It is useful for matching pressed keys. + * keyCode is the Code of the key, or a character "a-z" which is converted to a keyCode value. + * optModifiers is an Optional list of modifiers passed as additional paramerters. */ WebInspector.KeyboardShortcut.makeKey = function(keyCode, optModifiers) { + if (typeof keyCode === "string") + keyCode = keyCode.charCodeAt(0) - 32; var modifiers = WebInspector.KeyboardShortcut.Modifiers.None; for (var i = 1; i < arguments.length; i++) modifiers |= arguments[i]; diff --git a/WebCore/inspector/front-end/MetricsSidebarPane.js b/WebCore/inspector/front-end/MetricsSidebarPane.js index a33653b..f5e6758 100644 --- a/WebCore/inspector/front-end/MetricsSidebarPane.js +++ b/WebCore/inspector/front-end/MetricsSidebarPane.js @@ -35,27 +35,22 @@ WebInspector.MetricsSidebarPane = function() WebInspector.MetricsSidebarPane.prototype = { update: function(node) { - var body = this.bodyElement; - - body.removeChildren(); - if (node) this.node = node; else node = this.node; - if (!node || !node.ownerDocument.defaultView) - return; - - if (node.nodeType !== Node.ELEMENT_NODE) + if (!node || !node.ownerDocument.defaultView || node.nodeType !== Node.ELEMENT_NODE) { + this.bodyElement.removeChildren(); return; + } var self = this; var callback = function(stylePayload) { if (!stylePayload) return; var style = WebInspector.CSSStyleDeclaration.parseStyle(stylePayload); - self._update(node, body, style); + self._update(style); }; InjectedScriptAccess.getComputedStyle(node.id, callback); @@ -67,7 +62,7 @@ WebInspector.MetricsSidebarPane.prototype = { InjectedScriptAccess.getInlineStyle(node.id, inlineStyleCallback); }, - _update: function(node, body, style) + _update: function(style) { var metricsElement = document.createElement("div"); metricsElement.className = "metrics"; @@ -169,7 +164,8 @@ WebInspector.MetricsSidebarPane.prototype = { } metricsElement.appendChild(previousBox); - body.appendChild(metricsElement); + this.bodyElement.removeChildren(); + this.bodyElement.appendChild(metricsElement); }, startEditing: function(targetElement, box, styleProperty) diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js index 8bb4e35..7bdf17f 100644 --- a/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -150,7 +150,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { InjectedScriptAccess.getProperties(this.property.value, false, callback.bind(this)); }, - ondblclick: function(element, event) + ondblclick: function(event) { this.startEditing(); }, diff --git a/WebCore/inspector/front-end/ObjectProxy.js b/WebCore/inspector/front-end/ObjectProxy.js index bb4afa5..f4a59a7 100644 --- a/WebCore/inspector/front-end/ObjectProxy.js +++ b/WebCore/inspector/front-end/ObjectProxy.js @@ -45,6 +45,24 @@ WebInspector.ObjectProxy.wrapPrimitiveValue = function(value) return proxy; } +WebInspector.ObjectProxy.getPropertiesAsync = function(objectProxy, propertiesToQueryFor, callback) +{ + function createPropertiesMapThenCallback(propertiesPayload) + { + if (!propertiesPayload) { + callback(); + return; + } + + var result = []; + for (var i = 0; i < propertiesPayload.length; ++i) + if (propertiesToQueryFor.indexOf(propertiesPayload[i].name) !== -1) + result[propertiesPayload[i].name] = propertiesPayload[i].value.description; + callback(result); + }; + InjectedScriptAccess.getProperties(objectProxy, true, createPropertiesMapThenCallback); +} + WebInspector.ObjectPropertyProxy = function(name, value) { this.name = name; diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js index 6cd200b..d816ce5 100644 --- a/WebCore/inspector/front-end/Panel.js +++ b/WebCore/inspector/front-end/Panel.js @@ -231,8 +231,11 @@ WebInspector.Panel.prototype = { showFirstResult = true; } - if (currentView !== this.visibleView) - this.showView(currentView); + if (currentView !== this.visibleView) { + currentView = this.visibleView; + this._currentSearchResultIndex = 0; + showFirstResult = true; + } if (showFirstResult) currentView.jumpToFirstSearchResult(); diff --git a/WebCore/inspector/front-end/ProfileView.js b/WebCore/inspector/front-end/ProfileView.js index afced41..c164e94 100644 --- a/WebCore/inspector/front-end/ProfileView.js +++ b/WebCore/inspector/front-end/ProfileView.js @@ -83,7 +83,7 @@ WebInspector.CPUProfileView = function(profile) var self = this; function profileCallback(profile) { - self.profile.representedObject = profile; + self.profile = profile; self._assignParentsInProfile(); self.profileDataGridTree = self.bottomUpProfileDataGridTree; @@ -95,7 +95,7 @@ WebInspector.CPUProfileView = function(profile) } var callId = WebInspector.Callback.wrap(profileCallback); - InspectorController.getProfile(callId, this.profile.uid); + InspectorBackend.getProfile(callId, this.profile.uid); } WebInspector.CPUProfileView.prototype = { @@ -505,7 +505,7 @@ WebInspector.CPUProfileView.prototype = { _sortData: function(event) { - this._sortProfile(this.profile.representedObject); + this._sortProfile(this.profile); }, _sortProfile: function() @@ -594,9 +594,9 @@ WebInspector.CPUProfileType.prototype = { this._recording = !this._recording; if (this._recording) - InspectorController.startProfiling(); + InspectorBackend.startProfiling(); else - InspectorController.stopProfiling(); + InspectorBackend.stopProfiling(); }, setRecordingProfile: function(isProfiling) @@ -616,26 +616,3 @@ WebInspector.CPUProfileType.prototype = { } WebInspector.CPUProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype; - -WebInspector.CPUProfile = function(profile) -{ - this.representedObject = profile; - this.typeId = WebInspector.CPUProfileType.TypeId; -} - -WebInspector.CPUProfile.prototype = { - get title() - { - return this.representedObject.title; - }, - - get uid() - { - return this.representedObject.uid; - }, - - get head() - { - return this.representedObject.head; - } -} diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js index 74c2bb6..b276ecb 100644 --- a/WebCore/inspector/front-end/ProfilesPanel.js +++ b/WebCore/inspector/front-end/ProfilesPanel.js @@ -210,8 +210,9 @@ WebInspector.ProfilesPanel.prototype = { return escape(text) + '/' + escape(profileTypeId); }, - addProfileHeader: function(typeId, profile) + addProfileHeader: function(profile) { + var typeId = profile.typeId; var profileType = this.getProfileType(typeId); var sidebarParent = profileType.treeElement; var small = false; @@ -361,7 +362,8 @@ WebInspector.ProfilesPanel.prototype = { var profilesLength = this._profiles.length; for (var i = 0; i < profilesLength; ++i) { - var view = this._profiles[i].viewForProfile(); + var profile = this._profiles[i]; + var view = profile.__profilesPanelProfileType.viewForProfile(profile); if (!view.performSearch || view === visibleView) continue; views.push(view); @@ -398,7 +400,7 @@ WebInspector.ProfilesPanel.prototype = { _updateInterface: function() { // FIXME: Replace ProfileType-specific button visibility changes by a single ProfileType-agnostic "combo-button" visibility change. - if (InspectorController.profilerEnabled()) { + if (InspectorBackend.profilerEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable."); this.enableToggleButton.toggled = true; for (var typeId in this._profileTypeButtonsByIdMap) @@ -417,26 +419,27 @@ WebInspector.ProfilesPanel.prototype = { _enableProfiling: function() { - if (InspectorController.profilerEnabled()) + if (InspectorBackend.profilerEnabled()) return; this._toggleProfiling(this.panelEnablerView.alwaysEnabled); }, _toggleProfiling: function(optionalAlways) { - if (InspectorController.profilerEnabled()) - InspectorController.disableProfiler(true); + if (InspectorBackend.profilerEnabled()) + InspectorBackend.disableProfiler(true); else - InspectorController.enableProfiler(!!optionalAlways); + InspectorBackend.enableProfiler(!!optionalAlways); }, _populateProfiles: function() { - // FIXME: This code needs to be adjusted when more profiling types are added. - // Currently defaults to CPU profiles. - var cpuProfiles = this.getProfileType(WebInspector.CPUProfileType.TypeId).treeElement; - if (cpuProfiles.children.length) - return; + var sidebarTreeChildrenCount = this.sidebarTree.children.length; + for (var i = 0; i < sidebarTreeChildrenCount; ++i) { + var treeElement = this.sidebarTree.children[i]; + if (treeElement.children.length) + return; + } function populateCallback(profileHeaders) { profileHeaders.sort(function(a, b) { return a.uid - b.uid; }); @@ -446,7 +449,7 @@ WebInspector.ProfilesPanel.prototype = { } var callId = WebInspector.Callback.wrap(populateCallback); - InspectorController.getProfileHeaders(callId); + InspectorBackend.getProfileHeaders(callId); delete this._shouldPopulateProfiles; }, diff --git a/WebCore/inspector/front-end/PropertiesSidebarPane.js b/WebCore/inspector/front-end/PropertiesSidebarPane.js index ec08210..d84874e 100644 --- a/WebCore/inspector/front-end/PropertiesSidebarPane.js +++ b/WebCore/inspector/front-end/PropertiesSidebarPane.js @@ -36,12 +36,11 @@ WebInspector.PropertiesSidebarPane.prototype = { { var body = this.bodyElement; - body.removeChildren(); - - this.sections = []; - - if (!node) + if (!node) { + body.removeChildren(); + this.sections = []; return; + } var self = this; var callback = function(prototypes) { diff --git a/WebCore/inspector/front-end/Resource.js b/WebCore/inspector/front-end/Resource.js index 56696e3..d23b5da 100644 --- a/WebCore/inspector/front-end/Resource.js +++ b/WebCore/inspector/front-end/Resource.js @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComponent, identifier, mainResource, cached, requestMethod, requestFormData) +WebInspector.Resource = function(requestHeaders, url, documentURL, domain, path, lastPathComponent, identifier, mainResource, cached, requestMethod, requestFormData) { this.identifier = identifier; @@ -35,6 +35,7 @@ WebInspector.Resource = function(requestHeaders, url, domain, path, lastPathComp this.mainResource = mainResource; this.requestHeaders = requestHeaders; this.url = url; + this.documentURL = documentURL; this.domain = domain; this.path = path; this.lastPathComponent = lastPathComponent; @@ -111,7 +112,8 @@ WebInspector.Resource.Type = { Font: 3, Script: 4, XHR: 5, - Other: 6, + Media: 6, + Other: 7, isTextType: function(type) { @@ -161,6 +163,18 @@ WebInspector.Resource.prototype = { this.dispatchEventToListeners("url changed"); }, + get documentURL() + { + return this._documentURL; + }, + + set documentURL(x) + { + if (this._documentURL === x) + return; + this._documentURL = x; + }, + get domain() { return this._domain; @@ -587,7 +601,7 @@ WebInspector.Resource.prototype = { if (this.mimeType in WebInspector.MIMETypes) return this.type in WebInspector.MIMETypes[this.mimeType]; - return true; + return false; }, _checkWarnings: function() diff --git a/WebCore/inspector/front-end/ResourceView.js b/WebCore/inspector/front-end/ResourceView.js index 2ea7fdb..8175c2f 100644 --- a/WebCore/inspector/front-end/ResourceView.js +++ b/WebCore/inspector/front-end/ResourceView.js @@ -248,7 +248,7 @@ WebInspector.ResourceView.prototype = { } }, - _toggleURLdecoding: function(treeElement, event) + _toggleURLdecoding: function(event) { this._decodeRequestParameters = !this._decodeRequestParameters; this._refreshQueryString(); diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js index 940570f..60c1895 100644 --- a/WebCore/inspector/front-end/ResourcesPanel.js +++ b/WebCore/inspector/front-end/ResourcesPanel.js @@ -39,6 +39,7 @@ WebInspector.ResourcesPanel = function() this.viewsContainerElement.id = "resource-views"; this.element.appendChild(this.viewsContainerElement); + this.createFilterPanel(); this.createInterface(); this._createStatusbarButtons(); @@ -348,7 +349,7 @@ WebInspector.ResourcesPanel.prototype = { this.summaryBar.reset(); - if (InspectorController.resourceTrackingEnabled()) { + if (InspectorBackend.resourceTrackingEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable."); this.enableToggleButton.toggled = true; this.largerResourcesButton.visible = true; @@ -564,8 +565,8 @@ WebInspector.ResourcesPanel.prototype = { loadDividerPadding.style.left = percent + "%"; loadDividerPadding.title = WebInspector.UIString("Load event fired"); loadDividerPadding.appendChild(loadDivider); - - this.eventDividersElement.appendChild(loadDividerPadding); + + this.addEventDivider(loadDividerPadding); } if (this.mainResourceDOMContentTime !== -1) { @@ -579,8 +580,8 @@ WebInspector.ResourcesPanel.prototype = { domContentDividerPadding.style.left = percent + "%"; domContentDividerPadding.title = WebInspector.UIString("DOMContent event fired"); domContentDividerPadding.appendChild(domContentDivider); - - this.eventDividersElement.appendChild(domContentDividerPadding); + + this.addEventDivider(domContentDividerPadding); } }, @@ -615,7 +616,7 @@ WebInspector.ResourcesPanel.prototype = { this.itemsTreeElement.smallChildren = !this.itemsTreeElement.smallChildren; Preferences.resourcesLargeRows = !Preferences.resourcesLargeRows; - InspectorController.setSetting("resources-large-rows", Preferences.resourcesLargeRows); + InspectorFrontendHost.setSetting("resources-large-rows", Preferences.resourcesLargeRows); if (this.itemsTreeElement.smallChildren) { this.itemsGraphsElement.addStyleClass("small"); @@ -674,27 +675,27 @@ WebInspector.ResourcesPanel.prototype = { _enableResourceTracking: function() { - if (InspectorController.resourceTrackingEnabled()) + if (InspectorBackend.resourceTrackingEnabled()) return; this._toggleResourceTracking(this.panelEnablerView.alwaysEnabled); }, _toggleResourceTracking: function(optionalAlways) { - if (InspectorController.resourceTrackingEnabled()) { + if (InspectorBackend.resourceTrackingEnabled()) { this.largerResourcesButton.visible = false; this.sortingSelectElement.visible = false; - InspectorController.disableResourceTracking(true); + InspectorBackend.disableResourceTracking(true); } else { this.largerResourcesButton.visible = true; this.sortingSelectElement.visible = true; - InspectorController.enableResourceTracking(!!optionalAlways); + InspectorBackend.enableResourceTracking(!!optionalAlways); } }, get _resources() { - return this._items; + return this.items; } } @@ -958,6 +959,7 @@ WebInspector.ResourceSidebarTreeElement.prototype = { // FIXME: should actually add handler to parent, to be resolved via // https://bugs.webkit.org/show_bug.cgi?id=30227 this._listItemNode.addEventListener("dragstart", this.ondragstart.bind(this), false); + this.updateErrorsAndWarnings(); }, onselect: function() @@ -965,7 +967,7 @@ WebInspector.ResourceSidebarTreeElement.prototype = { WebInspector.panels.resources.showResource(this.resource); }, - ondblclick: function(treeElement, event) + ondblclick: function(event) { InjectedScriptAccess.openInInspectedWindow(this.resource.url, function() {}); }, @@ -1041,6 +1043,8 @@ WebInspector.ResourceSidebarTreeElement.prototype = { this.createIconElement(); } + + this.tooltip = this.resource.url; }, resetBubble: function() diff --git a/WebCore/inspector/front-end/ScriptView.js b/WebCore/inspector/front-end/ScriptView.js index 124190c..38157ac 100644 --- a/WebCore/inspector/front-end/ScriptView.js +++ b/WebCore/inspector/front-end/ScriptView.js @@ -59,7 +59,7 @@ WebInspector.ScriptView.prototype = { this.attach(); - if (!InspectorController.addSourceToFrame("text/javascript", this.script.source, this.sourceFrame.element)) + if (!InspectorFrontendHost.addSourceToFrame("text/javascript", this.script.source, this.sourceFrame.element)) return; delete this._frameNeedsSetup; diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js index 4aa0ab2..8b31a8b 100644 --- a/WebCore/inspector/front-end/ScriptsPanel.js +++ b/WebCore/inspector/front-end/ScriptsPanel.js @@ -161,36 +161,35 @@ WebInspector.ScriptsPanel = function() this._breakpointsURLMap = {}; this._shortcuts = {}; - - var isMac = InspectorController.platform().indexOf("mac-") === 0; - var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; + var handler, shortcut; + var platformSpecificModifier = WebInspector.isMac() ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; // Continue. - var handler = this.pauseButton.click.bind(this.pauseButton); - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F8); + handler = this.pauseButton.click.bind(this.pauseButton); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F8); this._shortcuts[shortcut] = handler; - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Slash, platformSpecificModifier); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Slash, platformSpecificModifier); this._shortcuts[shortcut] = handler; // Step over. - var handler = this.stepOverButton.click.bind(this.stepOverButton); - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F10); + handler = this.stepOverButton.click.bind(this.stepOverButton); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F10); this._shortcuts[shortcut] = handler; - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.SingleQuote, platformSpecificModifier); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.SingleQuote, platformSpecificModifier); this._shortcuts[shortcut] = handler; // Step into. - var handler = this.stepIntoButton.click.bind(this.stepIntoButton); - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11); + handler = this.stepIntoButton.click.bind(this.stepIntoButton); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11); this._shortcuts[shortcut] = handler; - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, platformSpecificModifier); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, platformSpecificModifier); this._shortcuts[shortcut] = handler; // Step out. - var handler = this.stepOutButton.click.bind(this.stepOutButton); - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11, WebInspector.KeyboardShortcut.Modifiers.Shift); + handler = this.stepOutButton.click.bind(this.stepOutButton); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.F11, WebInspector.KeyboardShortcut.Modifiers.Shift); this._shortcuts[shortcut] = handler; - var shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier); + shortcut = WebInspector.KeyboardShortcut.makeKey(WebInspector.KeyboardShortcut.KeyCodes.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier); this._shortcuts[shortcut] = handler; this.reset(); @@ -236,7 +235,7 @@ WebInspector.ScriptsPanel.prototype = { view.visible = false; } if (this._attachDebuggerWhenShown) { - InspectorController.enableDebugger(false); + InspectorBackend.enableDebugger(false); delete this._attachDebuggerWhenShown; } }, @@ -276,22 +275,29 @@ WebInspector.ScriptsPanel.prototype = { resource.addScript(script); } + sourceURL = script.sourceURL; + + if (sourceID) + this._sourceIDMap[sourceID] = (resource || script); + if (sourceURL in this._breakpointsURLMap && sourceID) { var breakpoints = this._breakpointsURLMap[sourceURL]; var breakpointsLength = breakpoints.length; for (var i = 0; i < breakpointsLength; ++i) { var breakpoint = breakpoints[i]; + if (startingLine <= breakpoint.line) { + // remove and add the breakpoint, to clean up things like the sidebar + this.removeBreakpoint(breakpoint); breakpoint.sourceID = sourceID; + this.addBreakpoint(breakpoint); + if (breakpoint.enabled) - InspectorController.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); + InspectorBackend.addBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.condition); } } } - if (sourceID) - this._sourceIDMap[sourceID] = (resource || script); - this._addScriptToFilesMenu(script); }, @@ -415,7 +421,7 @@ WebInspector.ScriptsPanel.prototype = { attachDebuggerWhenShown: function() { if (this.element.parentElement) { - InspectorController.enableDebugger(false); + InspectorBackend.enableDebugger(false); } else { this._attachDebuggerWhenShown = true; } @@ -438,7 +444,7 @@ WebInspector.ScriptsPanel.prototype = { delete this.currentQuery; this.searchCanceled(); - if (!InspectorController.debuggerEnabled()) { + if (!InspectorBackend.debuggerEnabled()) { this._paused = false; this._waitingToPause = false; this._stepping = false; @@ -489,17 +495,17 @@ WebInspector.ScriptsPanel.prototype = { canShowResource: function(resource) { - return resource && resource.scripts.length && InspectorController.debuggerEnabled(); + return resource && resource.scripts.length && InspectorBackend.debuggerEnabled(); }, showScript: function(script, line) { - this._showScriptOrResource(script, line, true); + this._showScriptOrResource(script, {line: line, shouldHighlightLine: true}); }, showResource: function(resource, line) { - this._showScriptOrResource(resource, line, true); + this._showScriptOrResource(resource, {line: line, shouldHighlightLine: true}); }, showView: function(view) @@ -567,8 +573,12 @@ WebInspector.ScriptsPanel.prototype = { return this.sourceFrameForScript(scriptOrResource); }, - _showScriptOrResource: function(scriptOrResource, line, shouldHighlightLine, fromBackForwardAction) + _showScriptOrResource: function(scriptOrResource, options) { + // options = {line:, shouldHighlightLine:, fromBackForwardAction:, initialLoad:} + if (!options) + options = {}; + if (!scriptOrResource) return; @@ -594,7 +604,11 @@ WebInspector.ScriptsPanel.prototype = { if (!view) return; - if (!fromBackForwardAction) { + var url = scriptOrResource.url || scriptOrResource.sourceURL; + if (url && !options.initialLoad) + InspectorFrontendHost.setSetting("LastViewedScriptFile", url); + + if (!options.fromBackForwardAction) { var oldIndex = this._currentBackForwardIndex; if (oldIndex >= 0) this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex); @@ -615,19 +629,26 @@ WebInspector.ScriptsPanel.prototype = { this.visibleView = view; - if (line) { + if (options.line) { if (view.revealLine) - view.revealLine(line); - if (view.highlightLine && shouldHighlightLine) - view.highlightLine(line); + view.revealLine(options.line); + if (view.highlightLine && options.shouldHighlightLine) + view.highlightLine(options.line); } var option; if (scriptOrResource instanceof WebInspector.Script) { option = scriptOrResource.filesSelectOption; + + // hasn't been added yet - happens for stepping in evals, + // so use the force option to force the script into the menu. + if (!option) { + this._addScriptToFilesMenu(scriptOrResource, {force: true}); + option = scriptOrResource.filesSelectOption; + } + console.assert(option); } else { - var url = scriptOrResource.url; var script = this._scriptsForURLsInFilesSelect[url]; if (script) option = script.filesSelectOption; @@ -637,8 +658,13 @@ WebInspector.ScriptsPanel.prototype = { this.filesSelectElement.selectedIndex = option.index; }, - _addScriptToFilesMenu: function(script) + _addScriptToFilesMenu: function(script, options) { + var force = options && options.force; + + if (!script.sourceURL && !force) + return; + if (script.resource && this._scriptsForURLsInFilesSelect[script.sourceURL]) return; @@ -679,7 +705,14 @@ WebInspector.ScriptsPanel.prototype = { // Call _showScriptOrResource if the option we just appended ended up being selected. // This will happen for the first item added to the menu. if (select.options[select.selectedIndex] === option) - this._showScriptOrResource(option.representedObject); + this._showScriptOrResource(option.representedObject, {initialLoad: true}); + else { + // if not first item, check to see if this was the last viewed + var url = option.representedObject.url || option.representedObject.sourceURL; + var lastURL = InspectorFrontendHost.setting("LastViewedScriptFile"); + if (url && url === lastURL) + this._showScriptOrResource(option.representedObject, {initialLoad: true}); + } }, _clearCurrentExecutionLine: function() @@ -702,7 +735,7 @@ WebInspector.ScriptsPanel.prototype = { this.sidebarPanes.watchExpressions.refreshExpressions(); var scriptOrResource = this._sourceIDMap[currentFrame.sourceID]; - this._showScriptOrResource(scriptOrResource, currentFrame.line); + this._showScriptOrResource(scriptOrResource, {line: currentFrame.line}); this._executionSourceFrame = this._sourceFrameForScriptOrResource(scriptOrResource); if (this._executionSourceFrame) @@ -748,7 +781,7 @@ WebInspector.ScriptsPanel.prototype = { _updatePauseOnExceptionsButton: function() { - if (InspectorController.pauseOnExceptions()) { + if (InspectorBackend.pauseOnExceptions()) { this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions."); this.pauseOnExceptionButton.toggled = true; } else { @@ -759,7 +792,7 @@ WebInspector.ScriptsPanel.prototype = { _updateDebuggerButtons: function() { - if (InspectorController.debuggerEnabled()) { + if (InspectorBackend.debuggerEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable."); this.enableToggleButton.toggled = true; this.pauseOnExceptionButton.visible = true; @@ -821,7 +854,7 @@ WebInspector.ScriptsPanel.prototype = { return; } - this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], null, false, true); + this._showScriptOrResource(this._backForwardList[--this._currentBackForwardIndex], {fromBackForwardAction: true}); this._updateBackAndForwardButtons(); }, @@ -832,13 +865,13 @@ WebInspector.ScriptsPanel.prototype = { return; } - this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], null, false, true); + this._showScriptOrResource(this._backForwardList[++this._currentBackForwardIndex], {fromBackForwardAction: true}); this._updateBackAndForwardButtons(); }, _enableDebugging: function() { - if (InspectorController.debuggerEnabled()) + if (InspectorBackend.debuggerEnabled()) return; this._toggleDebugging(this.panelEnablerView.alwaysEnabled); }, @@ -849,15 +882,15 @@ WebInspector.ScriptsPanel.prototype = { this._waitingToPause = false; this._stepping = false; - if (InspectorController.debuggerEnabled()) - InspectorController.disableDebugger(true); + if (InspectorBackend.debuggerEnabled()) + InspectorBackend.disableDebugger(true); else - InspectorController.enableDebugger(!!optionalAlways); + InspectorBackend.enableDebugger(!!optionalAlways); }, _togglePauseOnExceptions: function() { - InspectorController.setPauseOnExceptions(!InspectorController.pauseOnExceptions()); + InspectorBackend.setPauseOnExceptions(!InspectorBackend.pauseOnExceptions()); this._updatePauseOnExceptionsButton(); }, @@ -866,11 +899,11 @@ WebInspector.ScriptsPanel.prototype = { if (this._paused) { this._paused = false; this._waitingToPause = false; - InspectorController.resumeDebugger(); + InspectorBackend.resumeDebugger(); } else { this._stepping = false; this._waitingToPause = true; - InspectorController.pauseInDebugger(); + InspectorBackend.pauseInDebugger(); } this._clearInterface(); @@ -883,7 +916,7 @@ WebInspector.ScriptsPanel.prototype = { this._clearInterface(); - InspectorController.stepOverStatementInDebugger(); + InspectorBackend.stepOverStatementInDebugger(); }, _stepIntoClicked: function() @@ -893,7 +926,7 @@ WebInspector.ScriptsPanel.prototype = { this._clearInterface(); - InspectorController.stepIntoStatementInDebugger(); + InspectorBackend.stepIntoStatementInDebugger(); }, _stepOutClicked: function() @@ -903,7 +936,7 @@ WebInspector.ScriptsPanel.prototype = { this._clearInterface(); - InspectorController.stepOutOfFunctionInDebugger(); + InspectorBackend.stepOutOfFunctionInDebugger(); } } diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js index 1c11f76..b5cf4c0 100644 --- a/WebCore/inspector/front-end/SourceFrame.js +++ b/WebCore/inspector/front-end/SourceFrame.js @@ -207,12 +207,11 @@ WebInspector.SourceFrame.prototype = { this.element.contentDocument.addEventListener("webkitAnimationEnd", this._highlightLineEnds.bind(this), false); // Register 'eval' shortcut. - var isMac = InspectorController.platform().indexOf("mac-") === 0; - var platformSpecificModifier = isMac ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; + var platformSpecificModifier = WebInspector.isMac() ? WebInspector.KeyboardShortcut.Modifiers.Meta : WebInspector.KeyboardShortcut.Modifiers.Ctrl; var shortcut = WebInspector.KeyboardShortcut.makeKey(69 /* 'E' */, platformSpecificModifier | WebInspector.KeyboardShortcut.Modifiers.Shift); this._shortcuts[shortcut] = this._evalSelectionInCallFrame.bind(this); - var headElement = this.element.contentDocument.getElementsByTagName("head")[0]; + var headElement = this.element.contentDocument.head; if (!headElement) { headElement = this.element.contentDocument.createElement("head"); this.element.contentDocument.documentElement.insertBefore(headElement, this.element.contentDocument.documentElement.firstChild); @@ -264,6 +263,7 @@ WebInspector.SourceFrame.prototype = { this.element.contentWindow.Element.prototype.addStyleClass = Element.prototype.addStyleClass; this.element.contentWindow.Element.prototype.removeStyleClass = Element.prototype.removeStyleClass; + this.element.contentWindow.Element.prototype.removeChildren = Element.prototype.removeChildren; this.element.contentWindow.Element.prototype.positionAt = Element.prototype.positionAt; this.element.contentWindow.Element.prototype.removeMatchingStyleClasses = Element.prototype.removeMatchingStyleClasses; this.element.contentWindow.Element.prototype.hasStyleClass = Element.prototype.hasStyleClass; @@ -336,6 +336,8 @@ WebInspector.SourceFrame.prototype = { WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject); else if (this.addBreakpointDelegate) this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); + + event.preventDefault(); }, _editBreakpointCondition: function(eventTarget, sourceRow, breakpoint) @@ -729,20 +731,20 @@ WebInspector.SourceFrame.prototype = { if (!table) return; - var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighligher(table, this); + var cssSyntaxHighlighter = new WebInspector.CSSSourceSyntaxHighlighter(table, this); cssSyntaxHighlighter.process(); } } WebInspector.SourceFrame.prototype.__proto__ = WebInspector.Object.prototype; -WebInspector.SourceSyntaxHighligher = function(table, sourceFrame) +WebInspector.SourceSyntaxHighlighter = function(table, sourceFrame) { this.table = table; this.sourceFrame = sourceFrame; } -WebInspector.SourceSyntaxHighligher.prototype = { +WebInspector.SourceSyntaxHighlighter.prototype = { createSpan: function(content, className) { var span = document.createElement("span"); @@ -751,234 +753,1089 @@ WebInspector.SourceSyntaxHighligher.prototype = { return span; }, - generateFinder: function(regex, matchNumber, className) - { - return function(str) { - var match = regex.exec(str); - if (!match) - return null; - this.previousMatchLength = match[matchNumber].length; - return this.createSpan(match[matchNumber], className); - }; - }, - process: function() { // Split up the work into chunks so we don't block the // UI thread while processing. - var i = 0; var rows = this.table.rows; var rowsLength = rows.length; - var previousCell = null; - const linesPerChunk = 10; - + const tokensPerChunk = 100; + const lineLengthLimit = 20000; + + var boundProcessChunk = processChunk.bind(this); + var processChunkInterval = setInterval(boundProcessChunk, 25); + boundProcessChunk(); + function processChunk() { - for (var end = Math.min(i + linesPerChunk, rowsLength); i < end; ++i) { - var row = rows[i]; - if (!row) - continue; - var cell = row.cells[1]; - if (!cell) - continue; - this.syntaxHighlightLine(cell, previousCell); - if (i < (end - 1)) - this.deleteContinueFlags(previousCell); - previousCell = cell; - } + for (var i = 0; i < tokensPerChunk; i++) { + if (this.cursor >= this.lineCode.length) + moveToNextLine.call(this); + if (this.lineIndex >= rowsLength) { + this.sourceFrame.dispatchEventToListeners("syntax highlighting complete"); + return; + } + if (this.cursor > lineLengthLimit) { + var codeFragment = this.lineCode.substring(this.cursor); + this.nonToken += codeFragment; + this.cursor += codeFragment.length; + } - if (i >= rowsLength && processChunkInterval) { - this.deleteContinueFlags(previousCell); - delete this.previousMatchLength; + this.lex(); + } + } + + function moveToNextLine() + { + this.appendNonToken(); + + var row = rows[this.lineIndex]; + var line = row ? row.cells[1] : null; + if (line && this.newLine) { + line.removeChildren(); + + if (this.messageBubble) + this.newLine.appendChild(this.messageBubble); + + line.parentNode.insertBefore(this.newLine, line); + line.parentNode.removeChild(line); + + this.newLine = null; + } + this.lineIndex++; + if (this.lineIndex >= rowsLength && processChunkInterval) { clearInterval(processChunkInterval); - this.sourceFrame.dispatchEventToListeners("syntax highlighting complete"); + return; + } + row = rows[this.lineIndex]; + line = row ? row.cells[1] : null; + + this.messageBubble = null; + if (line.lastChild && line.lastChild.nodeType === Node.ELEMENT_NODE && line.lastChild.hasStyleClass("webkit-html-message-bubble")) { + this.messageBubble = line.lastChild; + line.removeChild(this.messageBubble); } - } - - var boundProcessChunk = processChunk.bind(this); - var processChunkInterval = setInterval(boundProcessChunk, 25); - boundProcessChunk(); - } -} - -WebInspector.CSSSourceSyntaxHighligher = function(table, sourceFrame) { - WebInspector.SourceSyntaxHighligher.call(this, table, sourceFrame); - - this.findNumber = this.generateFinder(/^((-?(\d+|\d*\.\d+))|^(#[a-fA-F0-9]{3,6}))(?:\D|$)/, 1, "webkit-css-number"); - this.findUnits = this.generateFinder(/^(px|em|pt|in|cm|mm|pc|ex)(?:\W|$)/, 1, "webkit-css-unit"); - this.findKeyword = this.generateFinder(/^(rgba?|hsla?|var)(?:\W|$)/, 1, "webkit-css-keyword"); - this.findSingleLineString = this.generateFinder(/^"(?:[^"\\]|\\.)*"|^'([^'\\]|\\.)*'/, 0, "webkit-css-string"); // " this quote keeps Xcode happy - this.findSingleLineComment = this.generateFinder(/^\/\*.*?\*\//, 0, "webkit-css-comment"); - this.findMultilineCommentStart = this.generateFinder(/^\/\*.*$/, 0, "webkit-css-comment"); - this.findMultilineCommentEnd = this.generateFinder(/^.*?\*\//, 0, "webkit-css-comment"); - this.findSelector = this.generateFinder(/^([#\.]?[_a-zA-Z].*?)(?:\W|$)/, 1, "webkit-css-selector"); - this.findProperty = this.generateFinder(/^(-?[_a-z0-9][_a-z0-9-]*\s*)(?:\:)/, 1, "webkit-css-property"); - this.findGenericIdent = this.generateFinder(/^([@-]?[_a-z0-9][_a-z0-9-]*)(?:\W|$)/, 1, "webkit-css-string"); -} -WebInspector.CSSSourceSyntaxHighligher.prototype = { - deleteContinueFlags: function(cell) - { - if (!cell) - return; - delete cell._commentContinues; - delete cell._inSelector; + this.lineCode = line.textContent; + this.newLine = line.cloneNode(false); + this.cursor = 0; + if (!line) + moveToNextLine(); + } }, - - findPseudoClass: function(str) + + lex: function() { - var match = /^(::?)([_a-z0-9][_a-z0-9-]*)/.exec(str); - if (!match) - return null; - this.previousMatchLength = match[0].length; - var span = document.createElement("span"); - span.appendChild(document.createTextNode(match[1])); - span.appendChild(this.createSpan(match[2], "webkit-css-pseudo-class")); - return span; - }, - - findURL: function(str) - { - var match = /^(?:local|url)\(([^\)]*?)\)/.exec(str); - if (!match) - return null; - this.previousMatchLength = match[0].length; - var innerUrlSpan = this.createSpan(match[1], "webkit-css-url"); - var outerSpan = document.createElement("span"); - outerSpan.appendChild(this.createSpan("url", "webkit-css-keyword")); - outerSpan.appendChild(document.createTextNode("(")); - outerSpan.appendChild(innerUrlSpan); - outerSpan.appendChild(document.createTextNode(")")); - return outerSpan; + var token = null; + var codeFragment = this.lineCode.substring(this.cursor); + + for (var i = 0; i < this.rules.length; i++) { + var rule = this.rules[i]; + var ruleContinueStateCondition = typeof rule.continueStateCondition === "undefined" ? this.ContinueState.None : rule.continueStateCondition; + if (this.continueState === ruleContinueStateCondition) { + if (typeof rule.lexStateCondition !== "undefined" && this.lexState !== rule.lexStateCondition) + continue; + var match = rule.pattern.exec(codeFragment); + if (match) { + token = match[0]; + if (token) { + if (!rule.dontAppendNonToken) + this.appendNonToken(); + return rule.action.call(this, token); + } + } + } + } + this.nonToken += codeFragment[0]; + this.cursor++; }, - - findAtRule: function(str) + + appendNonToken: function () { - var match = /^@[_a-z0-9][_a-z0-9-]*(?:\W|$)/.exec(str); - if (!match) - return null; - this.previousMatchLength = match[0].length; - return this.createSpan(match[0], "webkit-css-at-rule"); + if (this.nonToken.length > 0) { + this.newLine.appendChild(document.createTextNode(this.nonToken)); + this.nonToken = ""; + } }, - - syntaxHighlightLine: function(line, prevLine) + + syntaxHighlightNode: function(node) { - var code = line.textContent; - while (line.firstChild) - line.removeChild(line.firstChild); - - var token; - var tmp = 0; - var i = 0; - this.previousMatchLength = 0; - - if (prevLine) { - if (prevLine._commentContinues) { - if (!(token = this.findMultilineCommentEnd(code))) { - token = this.createSpan(code, "webkit-javascript-comment"); - line._commentContinues = true; - } - } - if (token) { - i += this.previousMatchLength ? this.previousMatchLength : code.length; - tmp = i; - line.appendChild(token); + this.lineCode = node.textContent; + node.removeChildren(); + this.newLine = node; + this.cursor = 0; + while (true) { + if (this.cursor >= this.lineCode.length) { + var codeFragment = this.lineCode.substring(this.cursor); + this.nonToken += codeFragment; + this.cursor += codeFragment.length; + this.appendNonToken(); + this.newLine = null; + return; } - } - var inSelector = (prevLine && prevLine._inSelector); // inside a selector, we can now parse properties and values - var inAtRuleBlock = (prevLine && prevLine._inAtRuleBlock); // inside an @rule block, but not necessarily inside a selector yet - var atRuleStarted = (prevLine && prevLine._atRuleStarted); // we received an @rule, we may stop the @rule at a semicolon or open a block and become inAtRuleBlock - var atRuleIsSelector = (prevLine && prevLine._atRuleIsSelector); // when this @rule opens a block it immediately goes into parsing properties and values instead of selectors - - for ( ; i < code.length; ++i) { - var codeFragment = code.substr(i); - var prevChar = code[i - 1]; - var currChar = codeFragment[0]; - token = this.findSingleLineComment(codeFragment); - if (!token) { - if ((token = this.findMultilineCommentStart(codeFragment))) - line._commentContinues = true; - else if (currChar === ";" && !inAtRuleBlock) - atRuleStarted = false; - else if (currChar === "}") { - if (inSelector && inAtRuleBlock && atRuleIsSelector) { - inSelector = false; - inAtRuleBlock = false; - atRuleStarted = false; - } else if (inSelector) { - inSelector = false; - } else if (inAtRuleBlock) { - inAtRuleBlock = false; - atRuleStarted = false; - } - } else if (currChar === "{") { - if (!atRuleStarted || inAtRuleBlock) { - inSelector = true; - } else if (!inAtRuleBlock && atRuleIsSelector) { - inAtRuleBlock = true; - inSelector = true; - } else if (!inAtRuleBlock) { - inAtRuleBlock = true; - inSelector = false; - } - } else if (inSelector) { - if (!prevChar || /^\d/.test(prevChar)) { - token = this.findUnits(codeFragment); - } else if (!prevChar || /^\W/.test(prevChar)) { - token = this.findNumber(codeFragment) || - this.findKeyword(codeFragment) || - this.findURL(codeFragment) || - this.findProperty(codeFragment) || - this.findAtRule(codeFragment) || - this.findGenericIdent(codeFragment) || - this.findSingleLineString(codeFragment); - } - } else if (!inSelector) { - if (atRuleStarted && !inAtRuleBlock) - token = this.findURL(codeFragment); // for @import - if (!token) { - token = this.findSelector(codeFragment) || - this.findPseudoClass(codeFragment) || - this.findAtRule(codeFragment); - } - } - } + this.lex(); + } + } +} - if (token) { - if (currChar === "@") { - atRuleStarted = true; +WebInspector.CSSSourceSyntaxHighlighter = function(table, sourceFrame) { + WebInspector.SourceSyntaxHighlighter.call(this, table, sourceFrame); - // The @font-face, @page, and @variables at-rules do not contain selectors like other at-rules - // instead it acts as a selector and contains properties and values. - var text = token.textContent; - atRuleIsSelector = /font-face/.test(text) || /page/.test(text) || /variables/.test(text); - } + this.LexState = { + Initial: 1, + DeclarationProperty: 2, + DeclarationValue: 3, + AtMedia: 4, + AtRule: 5, + AtKeyframes: 6 + }; + this.ContinueState = { + None: 0, + Comment: 1 + }; + + this.nonToken = ""; + this.cursor = 0; + this.lineIndex = -1; + this.lineCode = ""; + this.newLine = null; + this.lexState = this.LexState.Initial; + this.continueState = this.ContinueState.None; + + const urlPattern = /^url\(\s*(?:(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*')|(?:[!#$%&*-~\w]|(?:\\[\da-f]{1,6}\s?|\.))*)\s*\)/i; + const stringPattern = /^(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*')/i; + const identPattern = /^-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*/i; + const startBlockPattern = /^{/i; + const endBlockPattern = /^}/i; + this.rules = [{ + pattern: /^\/\*[^\*]*\*+([^\/*][^*]*\*+)*\//i, + action: commentAction + }, { + pattern: /^(?:\/\*(?:[^\*]|\*[^\/])*)/i, + action: commentStartAction + }, { + pattern: /^(?:(?:[^\*]|\*[^\/])*\*+\/)/i, + action: commentEndAction, + continueStateCondition: this.ContinueState.Comment + }, { + pattern: /^.*/i, + action: commentMiddleAction, + continueStateCondition: this.ContinueState.Comment + }, { + pattern: /^(?:(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|\*)(?:#-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|\.-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|\[\s*-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*\s*(?:(?:=|~=|\|=)\s*(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*'))\s*)?\]|:(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*\(\s*(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*\s*)?\)))*|(?:#-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|\.-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|\[\s*-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*\s*(?:(?:=|~=|\|=)\s*(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|(?:"(?:[^\\\"]|(?:\\[\da-f]{1,6}\s?|\.))*"|'(?:[^\\\']|(?:\\[\da-f]{1,6}\s?|\.))*'))\s*)?\]|:(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*|-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*\(\s*(?:-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*\s*)?\)))+)/i, + action: selectorAction, + lexStateCondition: this.LexState.Initial + }, { + pattern: startBlockPattern, + action: startRulesetBlockAction, + lexStateCondition: this.LexState.Initial, + dontAppendNonToken: true + }, { + pattern: identPattern, + action: propertyAction, + lexStateCondition: this.LexState.DeclarationProperty, + dontAppendNonToken: true + }, { + pattern: /^:/i, + action: declarationColonAction, + lexStateCondition: this.LexState.DeclarationProperty, + dontAppendNonToken: true + }, { + pattern: /^(?:#(?:[\da-f]{6}|[\da-f]{3})|rgba\(\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*\)|hsla\(\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*\)|rgb\(\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*\)|hsl\(\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*,\s*(?:\d+|\d*\.\d+)%?\s*\))/i, + action: colorAction, + lexStateCondition: this.LexState.DeclarationValue + }, { + pattern: /^(?:-?(?:\d+|\d*\.\d+)(?:em|rem|__qem|ex|px|cm|mm|in|pt|pc|deg|rad|grad|turn|ms|s|Hz|kHz|%)?)/i, + action: numvalueAction, + lexStateCondition: this.LexState.DeclarationValue + }, { + pattern: urlPattern, + action: urlAction, + lexStateCondition: this.LexState.DeclarationValue + }, { + pattern: stringPattern, + action: stringAction, + lexStateCondition: this.LexState.DeclarationValue + }, { + pattern: /^!\s*important/i, + action: importantAction, + lexStateCondition: this.LexState.DeclarationValue + }, { + pattern: identPattern, + action: valueIdentAction, + lexStateCondition: this.LexState.DeclarationValue, + dontAppendNonToken: true + }, { + pattern: /^;/i, + action: declarationSemicolonAction, + lexStateCondition: this.LexState.DeclarationValue, + dontAppendNonToken: true + }, { + pattern: endBlockPattern, + action: endRulesetBlockAction, + lexStateCondition: this.LexState.DeclarationProperty, + dontAppendNonToken: true + }, { + pattern: endBlockPattern, + action: endRulesetBlockAction, + lexStateCondition: this.LexState.DeclarationValue, + dontAppendNonToken: true + }, { + pattern: /^@media/i, + action: atMediaAction, + lexStateCondition: this.LexState.Initial + }, { + pattern: startBlockPattern, + action: startAtMediaBlockAction, + lexStateCondition: this.LexState.AtMedia, + dontAppendNonToken: true + }, { + pattern: /^@-webkit-keyframes/i, + action: atKeyframesAction, + lexStateCondition: this.LexState.Initial + }, { + pattern: startBlockPattern, + action: startAtMediaBlockAction, + lexStateCondition: this.LexState.AtKeyframes, + dontAppendNonToken: true + }, { + pattern: /^@-?(?:\w|(?:\\[\da-f]{1,6}\s?|\.))(?:[-\w]|(?:\\[\da-f]{1,6}\s?|\.))*/i, + action: atRuleAction, + lexStateCondition: this.LexState.Initial + }, { + pattern: /^;/i, + action: endAtRuleAction, + lexStateCondition: this.LexState.AtRule + }, { + pattern: urlPattern, + action: urlAction, + lexStateCondition: this.LexState.AtRule + }, { + pattern: stringPattern, + action: stringAction, + lexStateCondition: this.LexState.AtRule + }, { + pattern: stringPattern, + action: stringAction, + lexStateCondition: this.LexState.AtKeyframes + }, { + pattern: identPattern, + action: atRuleIdentAction, + lexStateCondition: this.LexState.AtRule, + dontAppendNonToken: true + }, { + pattern: identPattern, + action: atRuleIdentAction, + lexStateCondition: this.LexState.AtMedia, + dontAppendNonToken: true + }, { + pattern: startBlockPattern, + action: startAtRuleBlockAction, + lexStateCondition: this.LexState.AtRule, + dontAppendNonToken: true + }]; + + function commentAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-comment")); + } + + function commentStartAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-comment")); + this.continueState = this.ContinueState.Comment; + } + + function commentEndAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-comment")); + this.continueState = this.ContinueState.None; + } - if (tmp !== i) - line.appendChild(document.createTextNode(code.substring(tmp, i))); - line.appendChild(token); - i += this.previousMatchLength - 1; - tmp = i + 1; - } - } + function commentMiddleAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-comment")); + } + + function selectorAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-selector")); + } + + function startRulesetBlockAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.DeclarationProperty; + } + + function endRulesetBlockAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.Initial; + } + + const propertyKeywords = { + "background": true, + "background-attachment": true, + "background-clip": true, + "background-color": true, + "background-image": true, + "background-origin": true, + "background-position": true, + "background-position-x": true, + "background-position-y": true, + "background-repeat": true, + "background-repeat-x": true, + "background-repeat-y": true, + "background-size": true, + "border": true, + "border-bottom": true, + "border-bottom-color": true, + "border-bottom-left-radius": true, + "border-bottom-right-radius": true, + "border-bottom-style": true, + "border-bottom-width": true, + "border-collapse": true, + "border-color": true, + "border-left": true, + "border-left-color": true, + "border-left-style": true, + "border-left-width": true, + "border-radius": true, + "border-right": true, + "border-right-color": true, + "border-right-style": true, + "border-right-width": true, + "border-spacing": true, + "border-style": true, + "border-top": true, + "border-top-color": true, + "border-top-left-radius": true, + "border-top-right-radius": true, + "border-top-style": true, + "border-top-width": true, + "border-width": true, + "bottom": true, + "caption-side": true, + "clear": true, + "clip": true, + "color": true, + "content": true, + "counter-increment": true, + "counter-reset": true, + "cursor": true, + "direction": true, + "display": true, + "empty-cells": true, + "float": true, + "font": true, + "font-family": true, + "font-size": true, + "font-stretch": true, + "font-style": true, + "font-variant": true, + "font-weight": true, + "height": true, + "left": true, + "letter-spacing": true, + "line-height": true, + "list-style": true, + "list-style-image": true, + "list-style-position": true, + "list-style-type": true, + "margin": true, + "margin-bottom": true, + "margin-left": true, + "margin-right": true, + "margin-top": true, + "max-height": true, + "max-width": true, + "min-height": true, + "min-width": true, + "opacity": true, + "orphans": true, + "outline": true, + "outline-color": true, + "outline-offset": true, + "outline-style": true, + "outline-width": true, + "overflow": true, + "overflow-x": true, + "overflow-y": true, + "padding": true, + "padding-bottom": true, + "padding-left": true, + "padding-right": true, + "padding-top": true, + "page": true, + "page-break-after": true, + "page-break-before": true, + "page-break-inside": true, + "pointer-events": true, + "position": true, + "quotes": true, + "resize": true, + "right": true, + "size": true, + "src": true, + "table-layout": true, + "text-align": true, + "text-decoration": true, + "text-indent": true, + "text-line-through": true, + "text-line-through-color": true, + "text-line-through-mode": true, + "text-line-through-style": true, + "text-line-through-width": true, + "text-overflow": true, + "text-overline": true, + "text-overline-color": true, + "text-overline-mode": true, + "text-overline-style": true, + "text-overline-width": true, + "text-rendering": true, + "text-shadow": true, + "text-transform": true, + "text-underline": true, + "text-underline-color": true, + "text-underline-mode": true, + "text-underline-style": true, + "text-underline-width": true, + "top": true, + "unicode-bidi": true, + "unicode-range": true, + "vertical-align": true, + "visibility": true, + "white-space": true, + "widows": true, + "width": true, + "word-break": true, + "word-spacing": true, + "word-wrap": true, + "z-index": true, + "zoom": true, + "-webkit-animation": true, + "-webkit-animation-delay": true, + "-webkit-animation-direction": true, + "-webkit-animation-duration": true, + "-webkit-animation-iteration-count": true, + "-webkit-animation-name": true, + "-webkit-animation-play-state": true, + "-webkit-animation-timing-function": true, + "-webkit-appearance": true, + "-webkit-backface-visibility": true, + "-webkit-background-clip": true, + "-webkit-background-composite": true, + "-webkit-background-origin": true, + "-webkit-background-size": true, + "-webkit-binding": true, + "-webkit-border-fit": true, + "-webkit-border-horizontal-spacing": true, + "-webkit-border-image": true, + "-webkit-border-radius": true, + "-webkit-border-vertical-spacing": true, + "-webkit-box-align": true, + "-webkit-box-direction": true, + "-webkit-box-flex": true, + "-webkit-box-flex-group": true, + "-webkit-box-lines": true, + "-webkit-box-ordinal-group": true, + "-webkit-box-orient": true, + "-webkit-box-pack": true, + "-webkit-box-reflect": true, + "-webkit-box-shadow": true, + "-webkit-box-sizing": true, + "-webkit-column-break-after": true, + "-webkit-column-break-before": true, + "-webkit-column-break-inside": true, + "-webkit-column-count": true, + "-webkit-column-gap": true, + "-webkit-column-rule": true, + "-webkit-column-rule-color": true, + "-webkit-column-rule-style": true, + "-webkit-column-rule-width": true, + "-webkit-column-width": true, + "-webkit-columns": true, + "-webkit-font-size-delta": true, + "-webkit-font-smoothing": true, + "-webkit-highlight": true, + "-webkit-line-break": true, + "-webkit-line-clamp": true, + "-webkit-margin-bottom-collapse": true, + "-webkit-margin-collapse": true, + "-webkit-margin-start": true, + "-webkit-margin-top-collapse": true, + "-webkit-marquee": true, + "-webkit-marquee-direction": true, + "-webkit-marquee-increment": true, + "-webkit-marquee-repetition": true, + "-webkit-marquee-speed": true, + "-webkit-marquee-style": true, + "-webkit-mask": true, + "-webkit-mask-attachment": true, + "-webkit-mask-box-image": true, + "-webkit-mask-clip": true, + "-webkit-mask-composite": true, + "-webkit-mask-image": true, + "-webkit-mask-origin": true, + "-webkit-mask-position": true, + "-webkit-mask-position-x": true, + "-webkit-mask-position-y": true, + "-webkit-mask-repeat": true, + "-webkit-mask-repeat-x": true, + "-webkit-mask-repeat-y": true, + "-webkit-mask-size": true, + "-webkit-match-nearest-mail-blockquote-color": true, + "-webkit-nbsp-mode": true, + "-webkit-padding-start": true, + "-webkit-perspective": true, + "-webkit-perspective-origin": true, + "-webkit-perspective-origin-x": true, + "-webkit-perspective-origin-y": true, + "-webkit-rtl-ordering": true, + "-webkit-text-decorations-in-effect": true, + "-webkit-text-fill-color": true, + "-webkit-text-security": true, + "-webkit-text-size-adjust": true, + "-webkit-text-stroke": true, + "-webkit-text-stroke-color": true, + "-webkit-text-stroke-width": true, + "-webkit-transform": true, + "-webkit-transform-origin": true, + "-webkit-transform-origin-x": true, + "-webkit-transform-origin-y": true, + "-webkit-transform-origin-z": true, + "-webkit-transform-style": true, + "-webkit-transition": true, + "-webkit-transition-delay": true, + "-webkit-transition-duration": true, + "-webkit-transition-property": true, + "-webkit-transition-timing-function": true, + "-webkit-user-drag": true, + "-webkit-user-modify": true, + "-webkit-user-select": true, + "-webkit-variable-declaration-block": true + }; + function propertyAction(token) + { + this.cursor += token.length; + if (token in propertyKeywords) { + this.appendNonToken.call(this); + this.newLine.appendChild(this.createSpan(token, "webkit-css-property")); + } else + this.nonToken += token; + } + + function declarationColonAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.DeclarationValue; + } - line._inSelector = inSelector; - line._inAtRuleBlock = inAtRuleBlock; - line._atRuleStarted = atRuleStarted; - line._atRuleIsSelector = atRuleIsSelector; + const valueKeywords = { + "inherit": true, + "initial": true, + "none": true, + "hidden": true, + "inset": true, + "groove": true, + "ridge": true, + "outset": true, + "dotted": true, + "dashed": true, + "solid": true, + "double": true, + "caption": true, + "icon": true, + "menu": true, + "message-box": true, + "small-caption": true, + "-webkit-mini-control": true, + "-webkit-small-control": true, + "-webkit-control": true, + "status-bar": true, + "italic": true, + "oblique": true, + "all": true, + "small-caps": true, + "normal": true, + "bold": true, + "bolder": true, + "lighter": true, + "xx-small": true, + "x-small": true, + "small": true, + "medium": true, + "large": true, + "x-large": true, + "xx-large": true, + "-webkit-xxx-large": true, + "smaller": true, + "larger": true, + "wider": true, + "narrower": true, + "ultra-condensed": true, + "extra-condensed": true, + "condensed": true, + "semi-condensed": true, + "semi-expanded": true, + "expanded": true, + "extra-expanded": true, + "ultra-expanded": true, + "serif": true, + "sans-serif": true, + "cursive": true, + "fantasy": true, + "monospace": true, + "-webkit-body": true, + "aqua": true, + "black": true, + "blue": true, + "fuchsia": true, + "gray": true, + "green": true, + "lime": true, + "maroon": true, + "navy": true, + "olive": true, + "orange": true, + "purple": true, + "red": true, + "silver": true, + "teal": true, + "white": true, + "yellow": true, + "transparent": true, + "-webkit-link": true, + "-webkit-activelink": true, + "activeborder": true, + "activecaption": true, + "appworkspace": true, + "background": true, + "buttonface": true, + "buttonhighlight": true, + "buttonshadow": true, + "buttontext": true, + "captiontext": true, + "graytext": true, + "highlight": true, + "highlighttext": true, + "inactiveborder": true, + "inactivecaption": true, + "inactivecaptiontext": true, + "infobackground": true, + "infotext": true, + "match": true, + "menutext": true, + "scrollbar": true, + "threeddarkshadow": true, + "threedface": true, + "threedhighlight": true, + "threedlightshadow": true, + "threedshadow": true, + "window": true, + "windowframe": true, + "windowtext": true, + "-webkit-focus-ring-color": true, + "currentcolor": true, + "grey": true, + "-webkit-text": true, + "repeat": true, + "repeat-x": true, + "repeat-y": true, + "no-repeat": true, + "clear": true, + "copy": true, + "source-over": true, + "source-in": true, + "source-out": true, + "source-atop": true, + "destination-over": true, + "destination-in": true, + "destination-out": true, + "destination-atop": true, + "xor": true, + "plus-darker": true, + "plus-lighter": true, + "baseline": true, + "middle": true, + "sub": true, + "super": true, + "text-top": true, + "text-bottom": true, + "top": true, + "bottom": true, + "-webkit-baseline-middle": true, + "-webkit-auto": true, + "left": true, + "right": true, + "center": true, + "justify": true, + "-webkit-left": true, + "-webkit-right": true, + "-webkit-center": true, + "outside": true, + "inside": true, + "disc": true, + "circle": true, + "square": true, + "decimal": true, + "decimal-leading-zero": true, + "lower-roman": true, + "upper-roman": true, + "lower-greek": true, + "lower-alpha": true, + "lower-latin": true, + "upper-alpha": true, + "upper-latin": true, + "hebrew": true, + "armenian": true, + "georgian": true, + "cjk-ideographic": true, + "hiragana": true, + "katakana": true, + "hiragana-iroha": true, + "katakana-iroha": true, + "inline": true, + "block": true, + "list-item": true, + "run-in": true, + "compact": true, + "inline-block": true, + "table": true, + "inline-table": true, + "table-row-group": true, + "table-header-group": true, + "table-footer-group": true, + "table-row": true, + "table-column-group": true, + "table-column": true, + "table-cell": true, + "table-caption": true, + "-webkit-box": true, + "-webkit-inline-box": true, + "-wap-marquee": true, + "auto": true, + "crosshair": true, + "default": true, + "pointer": true, + "move": true, + "vertical-text": true, + "cell": true, + "context-menu": true, + "alias": true, + "progress": true, + "no-drop": true, + "not-allowed": true, + "-webkit-zoom-in": true, + "-webkit-zoom-out": true, + "e-resize": true, + "ne-resize": true, + "nw-resize": true, + "n-resize": true, + "se-resize": true, + "sw-resize": true, + "s-resize": true, + "w-resize": true, + "ew-resize": true, + "ns-resize": true, + "nesw-resize": true, + "nwse-resize": true, + "col-resize": true, + "row-resize": true, + "text": true, + "wait": true, + "help": true, + "all-scroll": true, + "-webkit-grab": true, + "-webkit-grabbing": true, + "ltr": true, + "rtl": true, + "capitalize": true, + "uppercase": true, + "lowercase": true, + "visible": true, + "collapse": true, + "above": true, + "absolute": true, + "always": true, + "avoid": true, + "below": true, + "bidi-override": true, + "blink": true, + "both": true, + "close-quote": true, + "crop": true, + "cross": true, + "embed": true, + "fixed": true, + "hand": true, + "hide": true, + "higher": true, + "invert": true, + "landscape": true, + "level": true, + "line-through": true, + "local": true, + "loud": true, + "lower": true, + "-webkit-marquee": true, + "mix": true, + "no-close-quote": true, + "no-open-quote": true, + "nowrap": true, + "open-quote": true, + "overlay": true, + "overline": true, + "portrait": true, + "pre": true, + "pre-line": true, + "pre-wrap": true, + "relative": true, + "scroll": true, + "separate": true, + "show": true, + "static": true, + "thick": true, + "thin": true, + "underline": true, + "-webkit-nowrap": true, + "stretch": true, + "start": true, + "end": true, + "reverse": true, + "horizontal": true, + "vertical": true, + "inline-axis": true, + "block-axis": true, + "single": true, + "multiple": true, + "forwards": true, + "backwards": true, + "ahead": true, + "up": true, + "down": true, + "slow": true, + "fast": true, + "infinite": true, + "slide": true, + "alternate": true, + "read-only": true, + "read-write": true, + "read-write-plaintext-only": true, + "element": true, + "ignore": true, + "intrinsic": true, + "min-intrinsic": true, + "clip": true, + "ellipsis": true, + "discard": true, + "dot-dash": true, + "dot-dot-dash": true, + "wave": true, + "continuous": true, + "skip-white-space": true, + "break-all": true, + "break-word": true, + "space": true, + "after-white-space": true, + "checkbox": true, + "radio": true, + "push-button": true, + "square-button": true, + "button": true, + "button-bevel": true, + "default-button": true, + "list-button": true, + "listbox": true, + "listitem": true, + "media-fullscreen-button": true, + "media-mute-button": true, + "media-play-button": true, + "media-seek-back-button": true, + "media-seek-forward-button": true, + "media-rewind-button": true, + "media-return-to-realtime-button": true, + "media-slider": true, + "media-sliderthumb": true, + "media-volume-slider-container": true, + "media-volume-slider": true, + "media-volume-sliderthumb": true, + "media-controls-background": true, + "media-current-time-display": true, + "media-time-remaining-display": true, + "menulist": true, + "menulist-button": true, + "menulist-text": true, + "menulist-textfield": true, + "slider-horizontal": true, + "slider-vertical": true, + "sliderthumb-horizontal": true, + "sliderthumb-vertical": true, + "caret": true, + "searchfield": true, + "searchfield-decoration": true, + "searchfield-results-decoration": true, + "searchfield-results-button": true, + "searchfield-cancel-button": true, + "textfield": true, + "textarea": true, + "caps-lock-indicator": true, + "round": true, + "border": true, + "border-box": true, + "content": true, + "content-box": true, + "padding": true, + "padding-box": true, + "contain": true, + "cover": true, + "logical": true, + "visual": true, + "lines": true, + "running": true, + "paused": true, + "flat": true, + "preserve-3d": true, + "ease": true, + "linear": true, + "ease-in": true, + "ease-out": true, + "ease-in-out": true, + "document": true, + "reset": true, + "visiblePainted": true, + "visibleFill": true, + "visibleStroke": true, + "painted": true, + "fill": true, + "stroke": true, + "antialiased": true, + "subpixel-antialiased": true, + "optimizeSpeed": true, + "optimizeLegibility": true, + "geometricPrecision": true + }; + function valueIdentAction(token) { + this.cursor += token.length; + if (token in valueKeywords) { + this.appendNonToken.call(this); + this.newLine.appendChild(this.createSpan(token, "webkit-css-keyword")); + } else + this.nonToken += token; + } - if (tmp < code.length) - line.appendChild(document.createTextNode(code.substring(tmp, i))); + function numvalueAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-number")); + } + + function declarationSemicolonAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.DeclarationProperty; + } + + function urlAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-url")); + } + + function stringAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-string")); + } + + function colorAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-color")); + } + + function importantAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-important")); + } + + function atMediaAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-at-rule")); + this.lexState = this.LexState.AtMedia; + } + + function startAtMediaBlockAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.Initial; + } + + function atKeyframesAction(token) + { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-at-rule")); + this.lexState = this.LexState.AtKeyframes; + } + + function startAtKeyframesBlockAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.Initial; + } + + function atRuleAction(token) { + this.cursor += token.length; + this.newLine.appendChild(this.createSpan(token, "webkit-css-at-rule")); + this.lexState = this.LexState.AtRule; + } + + function endAtRuleAction(token) { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.Initial; + } + + function startAtRuleBlockAction(token) + { + this.cursor += token.length; + this.nonToken += token; + this.lexState = this.LexState.DeclarationProperty; + } + + const mediaTypes = ["all", "aural", "braille", "embossed", "handheld", "print", "projection", "screen", "tty", "tv"]; + function atRuleIdentAction(token) { + this.cursor += token.length; + if (mediaTypes.indexOf(token) === -1) + this.nonToken += token; + else { + this.appendNonToken.call(this); + this.newLine.appendChild(this.createSpan(token, "webkit-css-keyword")); + } } } -WebInspector.CSSSourceSyntaxHighligher.prototype.__proto__ = WebInspector.SourceSyntaxHighligher.prototype; +WebInspector.CSSSourceSyntaxHighlighter.prototype.__proto__ = WebInspector.SourceSyntaxHighlighter.prototype; WebInspector.JavaScriptSourceSyntaxHighlighter = function(table, sourceFrame) { - WebInspector.SourceSyntaxHighligher.call(this, table, sourceFrame); + WebInspector.SourceSyntaxHighlighter.call(this, table, sourceFrame); this.LexState = { Initial: 1, @@ -996,212 +1853,282 @@ WebInspector.JavaScriptSourceSyntaxHighlighter = function(table, sourceFrame) { this.cursor = 0; this.lineIndex = -1; this.lineCode = ""; - this.lineFragment = null; + this.newLine = null; this.lexState = this.LexState.Initial; this.continueState = this.ContinueState.None; this.rules = [{ - pattern: /^(?:\/\/.*)/, - action: singleLineCommentAction - }, { - pattern: /^(?:\/\*(?:[^\*]|\*[^\/])*\*+\/)/, - action: multiLineSingleLineCommentAction - }, { - pattern: /^(?:\/\*(?:[^\*]|\*[^\/])*)/, - action: multiLineCommentStartAction - }, { - pattern: /^(?:(?:[^\*]|\*[^\/])*\*+\/)/, - action: multiLineCommentEndAction, - continueStateCondition: this.ContinueState.Comment - }, { - pattern: /^.*/, - action: multiLineCommentMiddleAction, - continueStateCondition: this.ContinueState.Comment - }, { - pattern: /^(?:(?:0|[1-9]\d*)\.\d+?(?:[eE](?:\d+|\+\d+|-\d+))?|\.\d+(?:[eE](?:\d+|\+\d+|-\d+))?|(?:0|[1-9]\d*)(?:[eE](?:\d+|\+\d+|-\d+))?|0x[0-9a-fA-F]+|0X[0-9a-fA-F]+)/, - action: numericLiteralAction - }, { - pattern: /^(?:"(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*"|'(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*')/, - action: stringLiteralAction - }, { - pattern: /^(?:'(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, - action: singleQuoteStringStartAction - }, { - pattern: /^(?:(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*')/, - action: singleQuoteStringEndAction, - continueStateCondition: this.ContinueState.SingleQuoteString - }, { - pattern: /^(?:(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, - action: singleQuoteStringMiddleAction, - continueStateCondition: this.ContinueState.SingleQuoteString - }, { - pattern: /^(?:"(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, - action: doubleQuoteStringStartAction - }, { - pattern: /^(?:(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*")/, - action: doubleQuoteStringEndAction, - continueStateCondition: this.ContinueState.DoubleQuoteString - }, { - pattern: /^(?:(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, - action: doubleQuoteStringMiddleAction, - continueStateCondition: this.ContinueState.DoubleQuoteString - }, { - pattern: /^(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))|[0-9])*)/, - action: identOrKeywordAction, - dontAppendNonToken: true - }, { - pattern: /^\)/, - action: rightParenAction, - dontAppendNonToken: true - }, { - pattern: /^(?:<=|>=|===|==|!=|!==|\+\+|\-\-|<<|>>|>>>|&&|\|\||\+=|\-=|\*=|%=|<<=|>>=|>>>=|&=|\|=|^=|[{}\(\[\]\.;,<>\+\-\*%&\|\^!~\?:=])/, - action: punctuatorAction, - dontAppendNonToken: true - }, { - pattern: /^(?:\/=?)/, - action: divPunctuatorAction, - stateCondition: this.LexState.DivisionAllowed, - dontAppendNonToken: true - }, { - pattern: /^(?:\/(?:(?:\\.)|[^\\*\/])(?:(?:\\.)|[^\\/])*\/(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))|[0-9])*)/, - action: regExpLiteralAction - }, { - pattern: /^(?:\/(?:(?:\\.)|[^\\*\/])(?:(?:\\.)|[^\\/])*)\\$/, - action: regExpStartAction - }, { - pattern: /^(?:(?:(?:\\.)|[^\\/])*\/(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))|[0-9])*)/, - action: regExpEndAction, - continueStateCondition: this.ContinueState.RegExp - }, { - pattern: /^(?:(?:(?:\\.)|[^\\/])*)\\$/, - action: regExpMiddleAction, - continueStateCondition: this.ContinueState.RegExp - }]; + pattern: /^(?:\/\/.*)/, + action: singleLineCommentAction + }, { + pattern: /^(?:\/\*(?:[^\*]|\*[^\/])*\*+\/)/, + action: multiLineSingleLineCommentAction + }, { + pattern: /^(?:\/\*(?:[^\*]|\*[^\/])*)/, + action: multiLineCommentStartAction + }, { + pattern: /^(?:(?:[^\*]|\*[^\/])*\*+\/)/, + action: multiLineCommentEndAction, + continueStateCondition: this.ContinueState.Comment + }, { + pattern: /^.*/, + action: multiLineCommentMiddleAction, + continueStateCondition: this.ContinueState.Comment + }, { + pattern: /^(?:(?:0|[1-9]\d*)\.\d+?(?:[eE](?:\d+|\+\d+|-\d+))?|\.\d+(?:[eE](?:\d+|\+\d+|-\d+))?|(?:0|[1-9]\d*)(?:[eE](?:\d+|\+\d+|-\d+))?|0x[0-9a-fA-F]+|0X[0-9a-fA-F]+)/, + action: numericLiteralAction + }, { + pattern: /^(?:"(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*"|'(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*')/, + action: stringLiteralAction + }, { + pattern: /^(?:'(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, + action: singleQuoteStringStartAction + }, { + pattern: /^(?:(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*')/, + action: singleQuoteStringEndAction, + continueStateCondition: this.ContinueState.SingleQuoteString + }, { + pattern: /^(?:(?:[^'\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, + action: singleQuoteStringMiddleAction, + continueStateCondition: this.ContinueState.SingleQuoteString + }, { + pattern: /^(?:"(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, + action: doubleQuoteStringStartAction + }, { + pattern: /^(?:(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*")/, + action: doubleQuoteStringEndAction, + continueStateCondition: this.ContinueState.DoubleQuoteString + }, { + pattern: /^(?:(?:[^"\\]|\\(?:['"\bfnrtv]|[^'"\bfnrtv0-9xu]|0|x[0-9a-fA-F][0-9a-fA-F]|(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])))*)\\$/, + action: doubleQuoteStringMiddleAction, + continueStateCondition: this.ContinueState.DoubleQuoteString + }, { + pattern: /^(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))|[0-9])*)/, + action: identOrKeywordAction + }, { + pattern: /^\)/, + action: rightParenAction, + dontAppendNonToken: true + }, { + pattern: /^(?:<=|>=|===|==|!=|!==|\+\+|\-\-|<<|>>|>>>|&&|\|\||\+=|\-=|\*=|%=|<<=|>>=|>>>=|&=|\|=|^=|[{}\(\[\]\.;,<>\+\-\*%&\|\^!~\?:=])/, + action: punctuatorAction, + dontAppendNonToken: true + }, { + pattern: /^(?:\/=?)/, + action: divPunctuatorAction, + lexStateCondition: this.LexState.DivisionAllowed, + dontAppendNonToken: true + }, { + pattern: /^(?:\/(?:(?:\\.)|[^\\*\/])(?:(?:\\.)|[^\\/])*\/(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))|[0-9])*)/, + action: regExpLiteralAction + }, { + pattern: /^(?:\/(?:(?:\\.)|[^\\*\/])(?:(?:\\.)|[^\\/])*)\\$/, + action: regExpStartAction + }, { + pattern: /^(?:(?:(?:\\.)|[^\\/])*\/(?:(?:[a-zA-Z]|[$_]|\\(?:u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]))|[0-9])*)/, + action: regExpEndAction, + continueStateCondition: this.ContinueState.RegExp + }, { + pattern: /^(?:(?:(?:\\.)|[^\\/])*)\\$/, + action: regExpMiddleAction, + continueStateCondition: this.ContinueState.RegExp + }]; function singleLineCommentAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-comment")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-comment")); } function multiLineSingleLineCommentAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-comment")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-comment")); } function multiLineCommentStartAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-comment")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-comment")); this.continueState = this.ContinueState.Comment; } function multiLineCommentEndAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-comment")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-comment")); this.continueState = this.ContinueState.None; } function multiLineCommentMiddleAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-comment")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-comment")); } function numericLiteralAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-number")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-number")); this.lexState = this.LexState.DivisionAllowed; } function stringLiteralAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); this.lexState = this.LexState.Initial; } function singleQuoteStringStartAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); this.continueState = this.ContinueState.SingleQuoteString; } function singleQuoteStringEndAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); this.continueState = this.ContinueState.None; } function singleQuoteStringMiddleAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); } function doubleQuoteStringStartAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); this.continueState = this.ContinueState.DoubleQuoteString; } function doubleQuoteStringEndAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); this.continueState = this.ContinueState.None; } function doubleQuoteStringMiddleAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-string")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-string")); } function regExpLiteralAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-regexp")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-regexp")); this.lexState = this.LexState.Initial; } function regExpStartAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-regexp")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-regexp")); this.continueState = this.ContinueState.RegExp; } function regExpEndAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-regexp")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-regexp")); this.continueState = this.ContinueState.None; } function regExpMiddleAction(token) { this.cursor += token.length; - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-regexp")); + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-regexp")); } + const keywords = { + "null": true, + "true": true, + "false": true, + "break": true, + "case": true, + "catch": true, + "const": true, + "default": true, + "finally": true, + "for": true, + "instanceof": true, + "new": true, + "var": true, + "continue": true, + "function": true, + "return": true, + "void": true, + "delete": true, + "if": true, + "this": true, + "do": true, + "while": true, + "else": true, + "in": true, + "switch": true, + "throw": true, + "try": true, + "typeof": true, + "debugger": true, + "class": true, + "enum": true, + "export": true, + "extends": true, + "import": true, + "super": true, + "get": true, + "set": true + }; function identOrKeywordAction(token) { - const keywords = ["null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for", "instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if", "this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "with", "debugger", "class", "enum", "export", "extends", "import", "super", "get", "set"]; this.cursor += token.length; - if (keywords.indexOf(token) === -1) { - this.nonToken += token; - this.lexState = this.LexState.DivisionAllowed; - } else { - this.appendNonToken(); - this.lineFragment.appendChild(this.createSpan(token, "webkit-javascript-keyword")); + + if (token in keywords) { + this.newLine.appendChild(this.createSpan(token, "webkit-javascript-keyword")); this.lexState = this.LexState.Initial; + } else { + var identElement = this.createSpan(token, "webkit-javascript-ident"); + identElement.addEventListener("mouseover", showDatatip, false); + this.newLine.appendChild(identElement); + this.lexState = this.LexState.DivisionAllowed; + } + } + + function showDatatip(event) { + if (!WebInspector.panels.scripts || !WebInspector.panels.scripts.paused) + return; + + var node = event.target; + var parts = [node.textContent]; + while (node.previousSibling && node.previousSibling.textContent === ".") { + node = node.previousSibling.previousSibling; + if (!node || !node.hasStyleClass("webkit-javascript-ident")) + break; + parts.unshift(node.textContent); + } + + var expression = parts.join("."); + + WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, false, "console", callback); + function callback(result, exception) + { + if (exception) + return; + event.target.setAttribute("title", result.description); + event.target.addEventListener("mouseout", onmouseout, false); + + function onmouseout(event) + { + event.target.removeAttribute("title"); + event.target.removeEventListener("mouseout", onmouseout, false); + } } } @@ -1227,131 +2154,4 @@ WebInspector.JavaScriptSourceSyntaxHighlighter = function(table, sourceFrame) { } } -WebInspector.JavaScriptSourceSyntaxHighlighter.prototype = { - process: function() - { - // Split up the work into chunks so we don't block the - // UI thread while processing. - - var rows = this.table.rows; - var rowsLength = rows.length; - const tokensPerChunk = 100; - const lineLengthLimit = 20000; - - var boundProcessChunk = processChunk.bind(this); - var processChunkInterval = setInterval(boundProcessChunk, 25); - boundProcessChunk(); - - function processChunk() - { - for (var i = 0; i < tokensPerChunk; i++) { - if (this.cursor >= this.lineCode.length) - moveToNextLine.call(this); - if (this.lineIndex >= rowsLength) { - this.sourceFrame.dispatchEventToListeners("syntax highlighting complete"); - return; - } - if (this.cursor > lineLengthLimit) { - var codeFragment = this.lineCode.substring(this.cursor); - this.nonToken += codeFragment; - this.cursor += codeFragment.length; - } - - this.lex(); - } - } - - function moveToNextLine() - { - this.appendNonToken(); - - var row = rows[this.lineIndex]; - var line = row ? row.cells[1] : null; - if (line && this.lineFragment) { - var messageBubble = null; - if (line.lastChild && line.lastChild.nodeType === Node.ELEMENT_NODE && line.lastChild.hasStyleClass("webkit-html-message-bubble")) { - messageBubble = line.lastChild; - line.removeChild(messageBubble); - } - - Element.prototype.removeChildren.call(line); - - line.appendChild(this.lineFragment); - if (messageBubble) - line.appendChild(messageBubble); - this.lineFragment = null; - } - this.lineIndex++; - if (this.lineIndex >= rowsLength && processChunkInterval) { - clearInterval(processChunkInterval); - this.sourceFrame.dispatchEventToListeners("syntax highlighting complete"); - return; - } - row = rows[this.lineIndex]; - line = row ? row.cells[1] : null; - this.lineCode = line.textContent; - this.lineFragment = document.createDocumentFragment(); - this.cursor = 0; - if (!line) - moveToNextLine(); - } - }, - - lex: function() - { - var token = null; - var codeFragment = this.lineCode.substring(this.cursor); - - for (var i = 0; i < this.rules.length; i++) { - var rule = this.rules[i]; - var ruleContinueStateCondition = typeof rule.continueStateCondition === "undefined" ? this.ContinueState.None : rule.continueStateCondition; - if (this.continueState === ruleContinueStateCondition) { - if (typeof rule.stateCondition !== "undefined" && this.lexState !== rule.stateCondition) - continue; - var match = rule.pattern.exec(codeFragment); - if (match) { - token = match[0]; - if (token) { - if (!rule.dontAppendNonToken) - this.appendNonToken(); - return rule.action.call(this, token); - } - } - } - } - this.nonToken += codeFragment[0]; - this.cursor++; - }, - - appendNonToken: function () - { - if (this.nonToken.length > 0) { - this.lineFragment.appendChild(document.createTextNode(this.nonToken)); - this.nonToken = ""; - } - }, - - syntaxHighlightNode: function(node) - { - this.lineCode = node.textContent; - this.lineFragment = document.createDocumentFragment(); - this.cursor = 0; - while (true) { - if (this.cursor >= this.lineCode.length) { - var codeFragment = this.lineCode.substring(this.cursor); - this.nonToken += codeFragment; - this.cursor += codeFragment.length; - this.appendNonToken(); - while (node.firstChild) - node.removeChild(node.firstChild); - node.appendChild(this.lineFragment); - this.lineFragment =null; - return; - } - - this.lex(); - } - } -} - -WebInspector.JavaScriptSourceSyntaxHighlighter.prototype.__proto__ = WebInspector.SourceSyntaxHighligher.prototype; +WebInspector.JavaScriptSourceSyntaxHighlighter.prototype.__proto__ = WebInspector.SourceSyntaxHighlighter.prototype; diff --git a/WebCore/inspector/front-end/SourceView.js b/WebCore/inspector/front-end/SourceView.js index c1b1bbf..7ab7b5b 100644 --- a/WebCore/inspector/front-end/SourceView.js +++ b/WebCore/inspector/front-end/SourceView.js @@ -97,7 +97,7 @@ WebInspector.SourceView.prototype = { delete this._frameNeedsSetup; this.sourceFrame.addEventListener("content loaded", this._contentLoaded, this); - InspectorController.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element); + InspectorFrontendHost.addResourceSourceToFrame(this.resource.identifier, this.sourceFrame.element); }, _contentLoaded: function() @@ -180,13 +180,13 @@ WebInspector.SourceView.prototype = { { if (isNaN(lineToSearch)) { // Search the whole document since there was no line to search. - this._searchResults = (InspectorController.search(this.sourceFrame.element.contentDocument, query) || []); + this._searchResults = (InspectorFrontendHost.search(this.sourceFrame.element.contentDocument, query) || []); } else { var sourceRow = this.sourceFrame.sourceRow(lineToSearch); if (sourceRow) { if (filterlessQuery) { // There is still a query string, so search for that string in the line. - this._searchResults = (InspectorController.search(sourceRow, filterlessQuery) || []); + this._searchResults = (InspectorFrontendHost.search(sourceRow, filterlessQuery) || []); } else { // Match the whole line, since there was no remaining query string to match. var rowRange = this.sourceFrame.element.contentDocument.createRange(); @@ -196,7 +196,7 @@ WebInspector.SourceView.prototype = { } // Attempt to search for the whole query, just incase it matches a color like "#333". - var wholeQueryMatches = InspectorController.search(this.sourceFrame.element.contentDocument, query); + var wholeQueryMatches = InspectorFrontendHost.search(this.sourceFrame.element.contentDocument, query); if (wholeQueryMatches) this._searchResults = this._searchResults.concat(wholeQueryMatches); } diff --git a/WebCore/inspector/front-end/StoragePanel.js b/WebCore/inspector/front-end/StoragePanel.js index 1aa11ee..dd558df 100644 --- a/WebCore/inspector/front-end/StoragePanel.js +++ b/WebCore/inspector/front-end/StoragePanel.js @@ -97,7 +97,6 @@ WebInspector.StoragePanel.prototype = { this._domStorage = []; - this._cookieDomains = {}; this._cookieViews = {}; this.databasesListTreeElement.removeChildren(); @@ -124,13 +123,8 @@ WebInspector.StoragePanel.prototype = { addCookieDomain: function(domain) { - // Eliminate duplicate domains from the list. - if (typeof this._cookieDomains[domain] !== "undefined") - return; - var cookieDomainTreeElement = new WebInspector.CookieSidebarTreeElement(domain); this.cookieListTreeElement.appendChild(cookieDomainTreeElement); - this._cookieDomains[domain] = true; }, addDOMStorage: function(domStorage) diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js index a95dae3..5178a98 100644 --- a/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/WebCore/inspector/front-end/StylesSidebarPane.js @@ -93,13 +93,12 @@ WebInspector.StylesSidebarPane.prototype = { node = this.node; var body = this.bodyElement; - if (!refresh || !node) { + + if (!node) { body.removeChildren(); this.sections = []; - } - - if (!node) return; + } var self = this; function callback(styles) @@ -335,7 +334,7 @@ WebInspector.StylesSidebarPane.prototype = { var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; Preferences.colorFormat = selectedOption.value; - InspectorController.setSetting("color-format", Preferences.colorFormat); + InspectorFrontendHost.setSetting("color-format", Preferences.colorFormat); for (var i = 0; i < this.sections.length; ++i) this.sections[i].update(true); @@ -1099,7 +1098,7 @@ WebInspector.StylePropertyTreeElement.prototype = { } }, - ondblclick: function(element, event) + ondblclick: function(event) { this.startEditing(event.target); event.stopPropagation(); @@ -1354,7 +1353,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (updateInterface) self.updateAll(true); - if (!self.rule) + if (!section.rule) WebInspector.panels.elements.treeOutline.update(); } diff --git a/WebCore/inspector/front-end/TestController.js b/WebCore/inspector/front-end/TestController.js index 12e1ac7..b2630ae 100644 --- a/WebCore/inspector/front-end/TestController.js +++ b/WebCore/inspector/front-end/TestController.js @@ -42,8 +42,8 @@ WebInspector.TestController.prototype = { notifyDone: function(result) { - var message = typeof result === "undefined" ? "<undefined>" : JSON.stringify(result); - InspectorController.didEvaluateForTestInFrontend(this._callId, message); + var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result); + InspectorBackend.didEvaluateForTestInFrontend(this._callId, message); }, runAfterPendingDispatches: function(callback) @@ -52,7 +52,6 @@ WebInspector.TestController.prototype = { callback(); return; } - setTimeout(this.runAfterPendingDispatches.bind(this), 0, callback); } } @@ -60,16 +59,20 @@ WebInspector.TestController.prototype = { WebInspector.evaluateForTestInFrontend = function(callId, script) { var controller = new WebInspector.TestController(callId); - try { - var result; - if (window[script] && typeof window[script] === "function") - result = window[script].call(this, controller); - else - result = window.eval(script); + function invokeMethod() + { + try { + var result; + if (window[script] && typeof window[script] === "function") + result = window[script].call(WebInspector, controller); + else + result = window.eval(script); - if (!controller._waitUntilDone) - controller.notifyDone(result); - } catch (e) { - controller.notifyDone(e.toString()); + if (!controller._waitUntilDone) + controller.notifyDone(result); + } catch (e) { + controller.notifyDone(e.toString()); + } } + controller.runAfterPendingDispatches(invokeMethod); } diff --git a/WebCore/inspector/front-end/TextPrompt.js b/WebCore/inspector/front-end/TextPrompt.js index f73ab0d..2230eaa 100644 --- a/WebCore/inspector/front-end/TextPrompt.js +++ b/WebCore/inspector/front-end/TextPrompt.js @@ -55,6 +55,13 @@ WebInspector.TextPrompt.prototype = { handleKeyEvent: function(event) { + function defaultAction() + { + this.clearAutoComplete(); + this.autoCompleteSoon(); + } + + var handled = false; switch (event.keyIdentifier) { case "Up": this._upKeyPressed(event); @@ -70,11 +77,36 @@ WebInspector.TextPrompt.prototype = { if (!this.acceptAutoComplete()) this.autoCompleteSoon(); break; + case "Alt": + case "Meta": + case "Shift": + case "Control": + break; + case "U+0050": // Ctrl+P = Previous + if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) { + handled = true; + this._moveBackInHistory(); + break; + } + defaultAction.call(this); + break; + case "U+004E": // Ctrl+N = Next + if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) { + handled = true; + this._moveForwardInHistory(); + break; + } + defaultAction.call(this); + break; default: - this.clearAutoComplete(); - this.autoCompleteSoon(); + defaultAction.call(this); break; } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } }, acceptAutoComplete: function() @@ -118,7 +150,7 @@ WebInspector.TextPrompt.prototype = { this._userEnteredRange.deleteContents(); var userTextNode = document.createTextNode(this._userEnteredText); - this._userEnteredRange.insertNode(userTextNode); + this._userEnteredRange.insertNode(userTextNode); var selectionRange = document.createRange(); selectionRange.setStart(userTextNode, this._userEnteredText.length); @@ -174,10 +206,9 @@ WebInspector.TextPrompt.prototype = { var currentText = fullWordRange.toString(); var foundIndex = null; - for (var i = 0; i < completions.length; ++i) { + for (var i = 0; i < completions.length; ++i) if (completions[i] === currentText) foundIndex = i; - } if (foundIndex === null || (foundIndex + 1) >= completions.length) var completionText = completions[0]; @@ -199,7 +230,7 @@ WebInspector.TextPrompt.prototype = { var suffixText = completionText.substring(wordPrefixLength); var prefixTextNode = document.createTextNode(prefixText); - fullWordRange.insertNode(prefixTextNode); + fullWordRange.insertNode(prefixTextNode); this.autoCompleteElement = document.createElement("span"); this.autoCompleteElement.className = "auto-complete-text"; @@ -211,7 +242,7 @@ WebInspector.TextPrompt.prototype = { finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); } else { var completionTextNode = document.createTextNode(completionText); - fullWordRange.insertNode(completionTextNode); + fullWordRange.insertNode(completionTextNode); if (completions.length > 1) finalSelectionRange.setStart(completionTextNode, wordPrefixLength); @@ -258,6 +289,50 @@ WebInspector.TextPrompt.prototype = { return true; }, + isCaretOnFirstLine: function() + { + var selection = window.getSelection(); + var focusNode = selection.focusNode; + if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element) + return true; + + if (focusNode.textContent.substring(0, selection.focusOffset).indexOf("\n") !== -1) + return false; + focusNode = focusNode.previousSibling; + + while (focusNode) { + if (focusNode.nodeType !== Node.TEXT_NODE) + return true; + if (focusNode.textContent.indexOf("\n") !== -1) + return false; + focusNode = focusNode.previousSibling; + } + + return true; + }, + + isCaretOnLastLine: function() + { + var selection = window.getSelection(); + var focusNode = selection.focusNode; + if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element) + return true; + + if (focusNode.textContent.substring(selection.focusOffset).indexOf("\n") !== -1) + return false; + focusNode = focusNode.nextSibling; + + while (focusNode) { + if (focusNode.nodeType !== Node.TEXT_NODE) + return true; + if (focusNode.textContent.indexOf("\n") !== -1) + return false; + focusNode = focusNode.nextSibling; + } + + return true; + }, + moveCaretToEndOfPrompt: function() { var selection = window.getSelection(); @@ -281,39 +356,71 @@ WebInspector.TextPrompt.prototype = { _upKeyPressed: function(event) { + if (!this.isCaretOnFirstLine()) + return; + + event.preventDefault(); + event.stopPropagation(); + + this._moveBackInHistory(); + }, + + _downKeyPressed: function(event) + { + if (!this.isCaretOnLastLine()) + return; + event.preventDefault(); event.stopPropagation(); + this._moveForwardInHistory(); + }, + + _moveBackInHistory: function() + { if (this.historyOffset == this.history.length) return; this.clearAutoComplete(true); - if (this.historyOffset == 0) + if (this.historyOffset === 0) this.tempSavedCommand = this.text; ++this.historyOffset; this.text = this.history[this.history.length - this.historyOffset]; + + this.element.scrollIntoViewIfNeeded(); + var firstNewlineIndex = this.text.indexOf("\n"); + if (firstNewlineIndex === -1) + this.moveCaretToEndOfPrompt(); + else { + var selection = window.getSelection(); + var selectionRange = document.createRange(); + + selectionRange.setStart(this.element.firstChild, firstNewlineIndex); + selectionRange.setEnd(this.element.firstChild, firstNewlineIndex); + + selection.removeAllRanges(); + selection.addRange(selectionRange); + } }, - _downKeyPressed: function(event) + _moveForwardInHistory: function() { - event.preventDefault(); - event.stopPropagation(); - - if (this.historyOffset == 0) + if (this.historyOffset === 0) return; this.clearAutoComplete(true); --this.historyOffset; - if (this.historyOffset == 0) { + if (this.historyOffset === 0) { this.text = this.tempSavedCommand; delete this.tempSavedCommand; return; } this.text = this.history[this.history.length - this.historyOffset]; + this.element.scrollIntoViewIfNeeded(); } } diff --git a/WebCore/inspector/front-end/TimelineAgent.js b/WebCore/inspector/front-end/TimelineAgent.js index cbbb736..c9e9d64 100644 --- a/WebCore/inspector/front-end/TimelineAgent.js +++ b/WebCore/inspector/front-end/TimelineAgent.js @@ -34,17 +34,21 @@ WebInspector.TimelineAgent = function() { // Must be kept in sync with TimelineItem.h WebInspector.TimelineAgent.RecordType = { - DOMDispatch : 0, - Layout : 1, - RecalculateStyles : 2, - Paint : 3, - ParseHTML : 4, - TimerInstall : 5, - TimerRemove : 6, - TimerFire : 7, + EventDispatch : 0, + Layout : 1, + RecalculateStyles : 2, + Paint : 3, + ParseHTML : 4, + TimerInstall : 5, + TimerRemove : 6, + TimerFire : 7, XHRReadyStateChange : 8, - XHRLoad : 9, - EvaluateScriptTag : 10 + XHRLoad : 9, + EvaluateScript : 10, + MarkTimeline : 11, + ResourceSendRequest : 12, + ResourceReceiveResponse : 13, + ResourceFinish : 14 }; WebInspector.addRecordToTimeline = function(record) { diff --git a/WebCore/inspector/front-end/TimelineGrid.js b/WebCore/inspector/front-end/TimelineGrid.js new file mode 100644 index 0000000..2866ecd --- /dev/null +++ b/WebCore/inspector/front-end/TimelineGrid.js @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org> + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +WebInspector.TimelineGrid = function() +{ + this.element = document.createElement("div"); + + this._itemsGraphsElement = document.createElement("div"); + this._itemsGraphsElement.id = "resources-graphs"; + this.element.appendChild(this._itemsGraphsElement); + + this._dividersElement = document.createElement("div"); + this._dividersElement.id = "resources-dividers"; + this.element.appendChild(this._dividersElement); + + this._eventDividersElement = document.createElement("div"); + this._eventDividersElement.id = "resources-event-dividers"; + this.element.appendChild(this._eventDividersElement); + + this._dividersLabelBarElement = document.createElement("div"); + this._dividersLabelBarElement.id = "resources-dividers-label-bar"; + this.element.appendChild(this._dividersLabelBarElement); +} + +WebInspector.TimelineGrid.prototype = { + get itemsGraphsElement() + { + return this._itemsGraphsElement; + }, + + updateDividers: function(force, calculator, paddingLeft) + { + var dividerCount = Math.round(this._dividersElement.offsetWidth / 64); + var slice = calculator.boundarySpan / dividerCount; + if (!force && this._currentDividerSlice === slice) + return false; + + if (!(typeof paddingLeft === "number")) + paddingLeft = 0; + this._currentDividerSlice = slice; + + this._eventDividersElement.removeChildren(); + // Reuse divider elements and labels. + var divider = this._dividersElement.firstChild; + var dividerLabelBar = this._dividersLabelBarElement.firstChild; + + var clientWidth = this._dividersLabelBarElement.clientWidth - paddingLeft; + for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) { + if (!divider) { + divider = document.createElement("div"); + divider.className = "resources-divider"; + this._dividersElement.appendChild(divider); + + dividerLabelBar = document.createElement("div"); + dividerLabelBar.className = "resources-divider"; + var label = document.createElement("div"); + label.className = "resources-divider-label"; + dividerLabelBar._labelElement = label; + dividerLabelBar.appendChild(label); + this._dividersLabelBarElement.appendChild(dividerLabelBar); + } + + if (i === dividerCount) + divider.addStyleClass("last"); + else + divider.removeStyleClass("last"); + + var left = paddingLeft + clientWidth * (i / dividerCount); + var percentLeft = 100 * left / this._dividersLabelBarElement.clientWidth + "%"; + divider.style.left = percentLeft; + dividerLabelBar.style.left = percentLeft; + + if (!isNaN(slice)) + dividerLabelBar._labelElement.textContent = calculator.formatValue(slice * i); + + divider = divider.nextSibling; + dividerLabelBar = dividerLabelBar.nextSibling; + } + + // Remove extras. + while (divider) { + var nextDivider = divider.nextSibling; + this._dividersElement.removeChild(divider); + divider = nextDivider; + } + while (dividerLabelBar) { + var nextDivider = dividerLabelBar.nextSibling; + this._dividersLabelBarElement.removeChild(dividerLabelBar); + dividerLabelBar = nextDivider; + } + return true; + }, + + addEventDivider: function(divider) + { + this._eventDividersElement.appendChild(divider); + }, + + setScrollAndDividerTop: function(scrollTop, dividersTop) + { + this._dividersElement.style.top = scrollTop + "px"; + this._eventDividersElement.style.top = scrollTop + "px"; + this._dividersLabelBarElement.style.top = dividersTop + "px"; + } +} diff --git a/WebCore/inspector/front-end/TimelineOverviewPane.js b/WebCore/inspector/front-end/TimelineOverviewPane.js new file mode 100644 index 0000000..b673abe --- /dev/null +++ b/WebCore/inspector/front-end/TimelineOverviewPane.js @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2009 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.TimelineOverviewPane = function(categories) +{ + this.element = document.createElement("div"); + this.element.id = "timeline-overview-panel"; + + this._categories = categories; + this._overviewSidebarElement = document.createElement("div"); + this._overviewSidebarElement.id = "timeline-overview-sidebar"; + this.element.appendChild(this._overviewSidebarElement); + + var overviewTreeElement = document.createElement("ol"); + overviewTreeElement.className = "sidebar-tree"; + this._overviewSidebarElement.appendChild(overviewTreeElement); + var sidebarTree = new TreeOutline(overviewTreeElement); + + var categoriesTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("TIMELINES"), {}, true); + categoriesTreeElement.expanded = true; + sidebarTree.appendChild(categoriesTreeElement); + for (var categoryName in this._categories) { + var category = this._categories[categoryName]; + categoriesTreeElement.appendChild(new WebInspector.TimelineCategoryTreeElement(category, this._onCheckboxClicked.bind(this, category))); + } + + this._overviewGrid = new WebInspector.TimelineGrid(); + this._overviewGrid.element.id = "timeline-overview-grid"; + this._overviewGrid.itemsGraphsElement.id = "timeline-overview-graphs"; + this.element.appendChild(this._overviewGrid.element); + + this._categoryGraphs = {}; + var i = 0; + for (var category in this._categories) { + var categoryGraph = new WebInspector.TimelineCategoryGraph(this._categories[category], i++ % 2); + this._categoryGraphs[category] = categoryGraph; + this._overviewGrid.itemsGraphsElement.appendChild(categoryGraph.graphElement); + } + this._overviewGrid.setScrollAndDividerTop(0, 0); + + this._overviewWindowElement = document.createElement("div"); + this._overviewWindowElement.id = "timeline-overview-window"; + this._overviewWindowElement.addEventListener("mousedown", this._dragWindow.bind(this), false); + this._overviewGrid.element.appendChild(this._overviewWindowElement); + + this._leftResizeElement = document.createElement("div"); + this._leftResizeElement.className = "timeline-window-resizer"; + this._leftResizeElement.style.left = 0; + this._overviewGrid.element.appendChild(this._leftResizeElement); + this._leftResizeElement.addEventListener("mousedown", this._resizeWindow.bind(this, this._leftResizeElement), false); + + this._rightResizeElement = document.createElement("div"); + this._rightResizeElement.className = "timeline-window-resizer timeline-window-resizer-right"; + this._rightResizeElement.style.right = 0; + this._overviewGrid.element.appendChild(this._rightResizeElement); + this._rightResizeElement.addEventListener("mousedown", this._resizeWindow.bind(this, this._rightResizeElement), false); + + this._overviewCalculator = new WebInspector.TimelineOverviewCalculator(); + + var separatorElement = document.createElement("div"); + separatorElement.id = "timeline-overview-separator"; + this.element.appendChild(separatorElement); + + this.windowLeft = 0.0; + this.windowRight = 1.0; +} + + +WebInspector.TimelineOverviewPane.prototype = { + _onCheckboxClicked: function (category, event) { + if (event.target.checked) + category.hidden = false; + else + category.hidden = true; + this._categoryGraphs[category.name].dimmed = !event.target.checked; + this.dispatchEventToListeners("filter changed"); + }, + + update: function(records) + { + // Clear summary bars. + var timelines = {}; + for (var category in this._categories) { + timelines[category] = []; + this._categoryGraphs[category].clearChunks(); + } + + function forAllRecords(recordsArray, callback) + { + if (!recordsArray) + return; + for (var i = 0; i < recordsArray.length; ++i) { + callback(recordsArray[i]); + forAllRecords(recordsArray[i].children, callback); + } + } + + // Create sparse arrays with 101 cells each to fill with chunks for a given category. + this._overviewCalculator.reset(); + forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator)); + + function markTimeline(record) + { + var percentages = this._overviewCalculator.computeBarGraphPercentages(record); + + var end = Math.round(percentages.end); + var categoryName = record.category.name; + for (var j = Math.round(percentages.start); j <= end; ++j) + timelines[categoryName][j] = true; + } + forAllRecords(records, markTimeline.bind(this)); + + // Convert sparse arrays to continuous segments, render graphs for each. + for (var category in this._categories) { + var timeline = timelines[category]; + window.timelineSaved = timeline; + var chunkStart = -1; + for (var j = 0; j < 101; ++j) { + if (timeline[j]) { + if (chunkStart === -1) + chunkStart = j; + } else { + if (chunkStart !== -1) { + this._categoryGraphs[category].addChunk(chunkStart, j); + chunkStart = -1; + } + } + } + if (chunkStart !== -1) { + this._categoryGraphs[category].addChunk(chunkStart, 100); + chunkStart = -1; + } + } + this._overviewGrid.updateDividers(true, this._overviewCalculator); + }, + + setSidebarWidth: function(width) + { + this._overviewSidebarElement.style.width = width + "px"; + }, + + updateMainViewWidth: function(width) + { + this._overviewGrid.element.style.left = width + "px"; + }, + + reset: function() + { + this._overviewCalculator.reset(); + this._overviewGrid.updateDividers(true, this._overviewCalculator); + this.windowLeft = 0.0; + this.windowRight = 1.0; + }, + + _resizeWindow: function(resizeElement, event) + { + WebInspector.elementDragStart(resizeElement, this._windowResizeDragging.bind(this, resizeElement), this._endWindowDragging.bind(this), event, "col-resize"); + }, + + _windowResizeDragging: function(resizeElement, event) + { + if (resizeElement === this._leftResizeElement) + this._resizeWindowLeft(event.pageX - this._overviewGrid.element.offsetLeft); + else + this._resizeWindowRight(event.pageX - this._overviewGrid.element.offsetLeft); + event.preventDefault(); + }, + + _dragWindow: function(event) + { + WebInspector.elementDragStart(this._overviewWindowElement, this._windowDragging.bind(this, event.pageX, + this._leftResizeElement.offsetLeft, this._rightResizeElement.offsetLeft), this._endWindowDragging.bind(this), event, "ew-resize"); + }, + + _windowDragging: function(startX, windowLeft, windowRight, event) + { + var delta = event.pageX - startX; + var start = windowLeft + delta; + var end = windowRight + delta; + var windowSize = windowRight - windowLeft; + + if (start < 0) { + start = 0; + end = windowSize; + } + + if (end > this._overviewGrid.element.clientWidth) { + end = this._overviewGrid.element.clientWidth; + start = end - windowSize; + } + this._setWindowPosition(start, end); + + event.preventDefault(); + }, + + _resizeWindowLeft: function(start) + { + // Glue to edge. + if (start < 10) + start = 0; + this._setWindowPosition(start, null); + }, + + _resizeWindowRight: function(end) + { + // Glue to edge. + if (end > this._overviewGrid.element.clientWidth - 10) + end = this._overviewGrid.element.clientWidth; + this._setWindowPosition(null, end); + }, + + _setWindowPosition: function(start, end) + { + if (typeof start === "number") { + if (start > this._rightResizeElement.offsetLeft - 4) + start = this._rightResizeElement.offsetLeft - 4; + + this.windowLeft = start / this._overviewGrid.element.clientWidth; + this._leftResizeElement.style.left = this.windowLeft * 100 + "%"; + this._overviewWindowElement.style.left = this.windowLeft * 100 + "%"; + } + if (typeof end === "number") { + if (end < this._leftResizeElement.offsetLeft + 12) + end = this._leftResizeElement.offsetLeft + 12; + + this.windowRight = end / this._overviewGrid.element.clientWidth; + this._rightResizeElement.style.left = this.windowRight * 100 + "%"; + } + this._overviewWindowElement.style.width = (this.windowRight - this.windowLeft) * 100 + "%"; + this.dispatchEventToListeners("window changed"); + }, + + _endWindowDragging: function(event) + { + WebInspector.elementDragEnd(event); + } +} + +WebInspector.TimelineOverviewPane.prototype.__proto__ = WebInspector.Object.prototype; + + +WebInspector.TimelineOverviewCalculator = function() +{ + this._uiString = WebInspector.UIString.bind(WebInspector); +} + +WebInspector.TimelineOverviewCalculator.prototype = { + computeBarGraphPercentages: function(record) + { + var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100; + var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100; + return {start: start, end: end}; + }, + + reset: function() + { + delete this.minimumBoundary; + delete this.maximumBoundary; + }, + + updateBoundaries: function(record) + { + if (typeof this.minimumBoundary === "undefined" || record.startTime < this.minimumBoundary) { + this.minimumBoundary = record.startTime; + return true; + } + if (typeof this.maximumBoundary === "undefined" || record.endTime > this.maximumBoundary) { + this.maximumBoundary = record.endTime; + return true; + } + return false; + }, + + get boundarySpan() + { + return this.maximumBoundary - this.minimumBoundary; + }, + + formatValue: function(value) + { + return Number.secondsToString(value, this._uiString); + } +} + + +WebInspector.TimelineCategoryTreeElement = function(category, onCheckboxClicked) +{ + this._category = category; + this._onCheckboxClicked = onCheckboxClicked; + // Pass an empty title, the title gets made later in onattach. + TreeElement.call(this, "", null, false); +} + +WebInspector.TimelineCategoryTreeElement.prototype = { + onattach: function() + { + this.listItemElement.removeChildren(); + this.listItemElement.addStyleClass("timeline-category-tree-item"); + this.listItemElement.addStyleClass("timeline-category-" + this._category.name); + + var label = document.createElement("label"); + + var checkElement = document.createElement("input"); + checkElement.type = "checkbox"; + checkElement.className = "timeline-category-checkbox"; + checkElement.checked = true; + checkElement.addEventListener("click", this._onCheckboxClicked); + label.appendChild(checkElement); + + var typeElement = document.createElement("span"); + typeElement.className = "type"; + typeElement.textContent = this._category.title; + label.appendChild(typeElement); + + this.listItemElement.appendChild(label); + } +} + +WebInspector.TimelineCategoryTreeElement.prototype.__proto__ = TreeElement.prototype; + +WebInspector.TimelineCategoryGraph = function(category, isEven) +{ + this._category = category; + + this._graphElement = document.createElement("div"); + this._graphElement.className = "timeline-graph-side timeline-overview-graph-side" + (isEven ? " even" : ""); + + this._barAreaElement = document.createElement("div"); + this._barAreaElement.className = "timeline-graph-bar-area timeline-category-" + category.name; + this._graphElement.appendChild(this._barAreaElement); +} + +WebInspector.TimelineCategoryGraph.prototype = { + get graphElement() + { + return this._graphElement; + }, + + addChunk: function(start, end) + { + var chunk = document.createElement("div"); + chunk.className = "timeline-graph-bar"; + this._barAreaElement.appendChild(chunk); + chunk.style.setProperty("left", start + "%"); + chunk.style.setProperty("width", (end - start) + "%"); + }, + + clearChunks: function() + { + this._barAreaElement.removeChildren(); + }, + + set dimmed(dimmed) + { + if (dimmed) + this._barAreaElement.removeStyleClass("timeline-category-" + this._category.name); + else + this._barAreaElement.addStyleClass("timeline-category-" + this._category.name); + } +} diff --git a/WebCore/inspector/front-end/TimelinePanel.js b/WebCore/inspector/front-end/TimelinePanel.js index df63a0b..ac36fa5 100644 --- a/WebCore/inspector/front-end/TimelinePanel.js +++ b/WebCore/inspector/front-end/TimelinePanel.js @@ -30,19 +30,56 @@ WebInspector.TimelinePanel = function() { - WebInspector.AbstractTimelinePanel.call(this); - + WebInspector.Panel.call(this); this.element.addStyleClass("timeline"); - this.createInterface(); - this.summaryBar.element.id = "timeline-summary"; - this.itemsGraphsElement.id = "timeline-graphs"; + this._overviewPane = new WebInspector.TimelineOverviewPane(this.categories); + this._overviewPane.addEventListener("window changed", this._scheduleRefresh, this); + this._overviewPane.addEventListener("filter changed", this._refresh, this); + this.element.appendChild(this._overviewPane.element); - this._createStatusbarButtons(); + this._sidebarBackgroundElement = document.createElement("div"); + this._sidebarBackgroundElement.className = "sidebar timeline-sidebar-background"; + this.element.appendChild(this._sidebarBackgroundElement); + + this._containerElement = document.createElement("div"); + this._containerElement.id = "timeline-container"; + this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false); + this.element.appendChild(this._containerElement); + + this.createSidebar(this._containerElement, this._containerElement); + var itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true); + itemsTreeElement.expanded = true; + this.sidebarTree.appendChild(itemsTreeElement); + + this._sidebarListElement = document.createElement("div"); + this.sidebarElement.appendChild(this._sidebarListElement); + + this._containerContentElement = document.createElement("div"); + this._containerContentElement.id = "resources-container-content"; + this._containerElement.appendChild(this._containerContentElement); + + this._timelineGrid = new WebInspector.TimelineGrid(); + this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement; + this._itemsGraphsElement.id = "timeline-graphs"; + this._containerContentElement.appendChild(this._timelineGrid.element); + + this._topGapElement = document.createElement("div"); + this._topGapElement.className = "timeline-gap"; + this._itemsGraphsElement.appendChild(this._topGapElement); - this.calculator = new WebInspector.TimelineCalculator(); + this._graphRowsElement = document.createElement("div"); + this._itemsGraphsElement.appendChild(this._graphRowsElement); - this.filter(this.filterAllElement, false); + this._bottomGapElement = document.createElement("div"); + this._bottomGapElement.className = "timeline-gap"; + this._itemsGraphsElement.appendChild(this._bottomGapElement); + + this._createStatusbarButtons(); + + this._records = []; + this._sendRequestRecords = {}; + this._calculator = new WebInspector.TimelineCalculator(); } WebInspector.TimelinePanel.prototype = { @@ -64,20 +101,12 @@ WebInspector.TimelinePanel.prototype = { this._categories = { loading: new WebInspector.TimelineCategory("loading", WebInspector.UIString("Loading"), "rgb(47,102,236)"), scripting: new WebInspector.TimelineCategory("scripting", WebInspector.UIString("Scripting"), "rgb(157,231,119)"), - rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)"), - other: new WebInspector.TimelineCategory("other", WebInspector.UIString("Other"), "rgb(186,186,186)") + rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)") }; } return this._categories; }, - populateSidebar: function() - { - this.itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true); - this.itemsTreeElement.expanded = true; - this.sidebarTree.appendChild(this.itemsTreeElement); - }, - _createStatusbarButtons: function() { this.toggleTimelineButton = new WebInspector.StatusBarButton("", "record-profile-status-bar-item"); @@ -87,6 +116,14 @@ WebInspector.TimelinePanel.prototype = { this.clearButton.addEventListener("click", this.reset.bind(this), false); }, + _toggleTimelineButtonClicked: function() + { + if (this.toggleTimelineButton.toggled) + InspectorBackend.stopTimelineProfiler(); + else + InspectorBackend.startTimelineProfiler(); + }, + timelineWasStarted: function() { this.toggleTimelineButton.toggled = true; @@ -99,7 +136,14 @@ WebInspector.TimelinePanel.prototype = { addRecordToTimeline: function(record) { + this._innerAddRecordToTimeline(record, this._records); + this._scheduleRefresh(); + }, + + _innerAddRecordToTimeline: function(record, collection) + { var formattedRecord = this._formatRecord(record); + // Glue subsequent records with same category and title together if they are closer than 100ms to each other. if (this._lastRecord && (!record.children || !record.children.length) && this._lastRecord.category == formattedRecord.category && @@ -108,40 +152,25 @@ WebInspector.TimelinePanel.prototype = { formattedRecord.startTime - this._lastRecord.endTime < 0.1) { this._lastRecord.endTime = formattedRecord.endTime; this._lastRecord.count++; - this.refreshItem(this._lastRecord); } else { - this.addItem(formattedRecord); - - for (var i = 0; record.children && i < record.children.length; ++i) - this.addRecordToTimeline(record.children[i]); + collection.push(formattedRecord); + for (var i = 0; record.children && i < record.children.length; ++i) { + if (!formattedRecord.children) + formattedRecord.children = []; + var formattedChild = this._innerAddRecordToTimeline(record.children[i], formattedRecord.children); + formattedChild.parent = formattedRecord; + } this._lastRecord = record.children && record.children.length ? null : formattedRecord; } - }, - - createItemTreeElement: function(item) - { - return new WebInspector.TimelineRecordTreeElement(item); - }, - - createItemGraph: function(item) - { - return new WebInspector.TimelineGraph(item); - }, - - _toggleTimelineButtonClicked: function() - { - if (InspectorController.timelineProfilerEnabled()) - InspectorController.stopTimelineProfiler(); - else - InspectorController.startTimelineProfiler(); + return formattedRecord; }, _formatRecord: function(record) { + var recordTypes = WebInspector.TimelineAgent.RecordType; if (!this._recordStyles) { this._recordStyles = {}; - var recordTypes = WebInspector.TimelineAgent.RecordType; - this._recordStyles[recordTypes.DOMDispatch] = { title: WebInspector.UIString("DOM Event"), category: this.categories.scripting }; + this._recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: this.categories.scripting }; this._recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: this.categories.rendering }; this._recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: this.categories.rendering }; this._recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: this.categories.rendering }; @@ -151,13 +180,16 @@ WebInspector.TimelinePanel.prototype = { this._recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer Fired"), category: this.categories.scripting }; this._recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIString("XHR Ready State Change"), category: this.categories.scripting }; this._recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load"), category: this.categories.scripting }; - this._recordStyles[recordTypes.EvaluateScriptTag] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting }; - this._recordStyles["Other"] = { title: WebInspector.UIString("Other"), icon: 0, category: this.categories.other }; + this._recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting }; + this._recordStyles[recordTypes.MarkTimeline] = { title: WebInspector.UIString("Mark"), category: this.categories.scripting }; + this._recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIString("Send Request"), category: this.categories.loading }; + this._recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UIString("Receive Response"), category: this.categories.loading }; + this._recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("Finish Loading"), category: this.categories.loading }; } var style = this._recordStyles[record.type]; if (!style) - style = this._recordStyles["Other"]; + style = this._recordStyles[recordTypes.EventDispatch]; var formattedRecord = {}; formattedRecord.category = style.category; @@ -166,119 +198,278 @@ WebInspector.TimelinePanel.prototype = { formattedRecord.data = record.data; formattedRecord.count = 1; formattedRecord.type = record.type; - formattedRecord.details = this._getRecordDetails(record); formattedRecord.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : formattedRecord.startTime; + formattedRecord.record = record; + + // Make resource receive record last since request was sent; make finish record last since response received. + if (record.type === WebInspector.TimelineAgent.RecordType.ResourceSendRequest) { + this._sendRequestRecords[record.data.identifier] = formattedRecord; + } else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse) { + var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; + if (sendRequestRecord) { // False if we started instrumentation in the middle of request. + sendRequestRecord._responseReceivedFormattedTime = formattedRecord.startTime; + formattedRecord.startTime = sendRequestRecord.startTime; + sendRequestRecord.details = this._getRecordDetails(record); + } + } else if (record.type === WebInspector.TimelineAgent.RecordType.ResourceFinish) { + var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; + if (sendRequestRecord) // False for main resource. + formattedRecord.startTime = sendRequestRecord._responseReceivedFormattedTime; + } + formattedRecord.details = this._getRecordDetails(record); + return formattedRecord; }, - + _getRecordDetails: function(record) { switch (record.type) { - case WebInspector.TimelineAgent.RecordType.DOMDispatch: - return record.data.type; + case WebInspector.TimelineAgent.RecordType.EventDispatch: + return record.data ? record.data.type : ""; + case WebInspector.TimelineAgent.RecordType.Paint: + return record.data.width + "\u2009\u00d7\u2009" + record.data.height; case WebInspector.TimelineAgent.RecordType.TimerInstall: case WebInspector.TimelineAgent.RecordType.TimerRemove: case WebInspector.TimelineAgent.RecordType.TimerFire: return record.data.timerId; case WebInspector.TimelineAgent.RecordType.XHRReadyStateChange: case WebInspector.TimelineAgent.RecordType.XHRLoad: - case WebInspector.TimelineAgent.RecordType.EvaluateScriptTag: - return record.data.url; + case WebInspector.TimelineAgent.RecordType.EvaluateScript: + case WebInspector.TimelineAgent.RecordType.ResourceSendRequest: + return WebInspector.displayNameForURL(record.data.url); + case WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse: + case WebInspector.TimelineAgent.RecordType.ResourceFinish: + var sendRequestRecord = this._sendRequestRecords[record.data.identifier]; + return sendRequestRecord ? WebInspector.displayNameForURL(sendRequestRecord.data.url) : ""; + case WebInspector.TimelineAgent.RecordType.MarkTimeline: + return record.data.message; default: return ""; } }, + setSidebarWidth: function(width) + { + WebInspector.Panel.prototype.setSidebarWidth.call(this, width); + this._sidebarBackgroundElement.style.width = width + "px"; + this._overviewPane.setSidebarWidth(width); + }, + + updateMainViewWidth: function(width) + { + this._containerContentElement.style.left = width + "px"; + this._scheduleRefresh(); + this._overviewPane.updateMainViewWidth(width); + }, + + resize: function() { + this._scheduleRefresh(); + }, + reset: function() { - WebInspector.AbstractTimelinePanel.prototype.reset.call(this); this._lastRecord = null; - } -} + this._sendRequestRecords = {}; + this._overviewPane.reset(); + this._records = []; + this._refresh(); + }, -WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.AbstractTimelinePanel.prototype; + show: function() + { + WebInspector.Panel.prototype.show.call(this); + if (this._needsRefresh) + this._refresh(); + }, -WebInspector.TimelineCategory = function(name, title, color) -{ - WebInspector.AbstractTimelineCategory.call(this, name, title, color); -} + _onScroll: function(event) + { + var scrollTop = this._containerElement.scrollTop; + var dividersTop = Math.max(0, scrollTop); + this._timelineGrid.setScrollAndDividerTop(scrollTop, dividersTop); + this._scheduleRefresh(true); + }, -WebInspector.TimelineCategory.prototype = { -} + _scheduleRefresh: function(immediate) + { + if (this._needsRefresh) + return; + this._needsRefresh = true; + + if (this.visible && !("_refreshTimeout" in this)) + this._refreshTimeout = setTimeout(this._refresh.bind(this), immediate ? 0 : 100); + }, -WebInspector.TimelineCategory.prototype.__proto__ = WebInspector.AbstractTimelineCategory.prototype; + _refresh: function() + { + this._needsRefresh = false; + if ("_refreshTimeout" in this) { + clearTimeout(this._refreshTimeout); + delete this._refreshTimeout; + } + this._overviewPane.update(this._records); + this._refreshRecords(); + }, + _refreshRecords: function() + { + this._calculator.windowLeft = this._overviewPane.windowLeft; + this._calculator.windowRight = this._overviewPane.windowRight; + this._calculator.reset(); + + for (var i = 0; i < this._records.length; ++i) + this._calculator.updateBoundaries(this._records[i]); + + var recordsInWindow = []; + for (var i = 0; i < this._records.length; ++i) { + var record = this._records[i]; + var percentages = this._calculator.computeBarGraphPercentages(record); + if (percentages.start < 100 && percentages.end >= 0 && !record.category.hidden) + this._addToRecordsWindow(record, recordsInWindow); + } -WebInspector.TimelineRecordTreeElement = function(record) -{ - this._record = record; + // Calculate the visible area. + var visibleTop = this._containerElement.scrollTop; + var visibleBottom = visibleTop + this._containerElement.clientHeight; + + // Define row height, should be in sync with styles for timeline graphs. + const rowHeight = 18; + const expandOffset = 15; + + // Convert visible area to visible indexes. Always include top-level record for a visible nested record. + var startIndex = Math.max(0, Math.floor(visibleTop / rowHeight) - 1); + while (startIndex > 0 && recordsInWindow[startIndex].parent) + startIndex--; + var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight)); + while (endIndex < recordsInWindow.length - 1 && recordsInWindow[startIndex].parent) + endIndex++; + + // Resize gaps first. + const top = (startIndex * rowHeight) + "px"; + this._topGapElement.style.height = top; + this.sidebarElement.style.top = top; + this.sidebarResizeElement.style.top = top; + this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px"; + + // Update visible rows. + var listRowElement = this._sidebarListElement.firstChild; + var graphRowElement = this._graphRowsElement.firstChild; + var width = this._graphRowsElement.offsetWidth; + var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true); + for (var i = startIndex; i < endIndex; ++i) { + var record = recordsInWindow[i]; + var isEven = !(i % 2); + + if (!listRowElement) { + listRowElement = new WebInspector.TimelineRecordListRow().element; + this._sidebarListElement.appendChild(listRowElement); + } + if (!graphRowElement) { + graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback, rowHeight).element; + this._graphRowsElement.appendChild(graphRowElement); + } + + listRowElement.listRow.update(record, isEven); + graphRowElement.graphRow.update(record, isEven, this._calculator, width, expandOffset); + + listRowElement = listRowElement.nextSibling; + graphRowElement = graphRowElement.nextSibling; + } - // Pass an empty title, the title gets made later in onattach. - TreeElement.call(this, "", null, false); -} + // Remove extra rows. + while (listRowElement) { + var nextElement = listRowElement.nextSibling; + listRowElement.listRow.dispose(); + listRowElement = nextElement; + } + while (graphRowElement) { + var nextElement = graphRowElement.nextSibling; + graphRowElement.graphRow.dispose(); + graphRowElement = nextElement; + } + + // Reserve some room for expand / collapse controls to the left for records that start at 0ms. + var timelinePaddingLeft = this._calculator.windowLeft === 0 ? expandOffset : 0; + this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft); + this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight); + }, -WebInspector.TimelineRecordTreeElement.prototype = { - onattach: function() - { - this.listItemElement.removeChildren(); - this.listItemElement.addStyleClass("timeline-tree-item"); - this.listItemElement.addStyleClass("timeline-category-" + this._record.category.name); - - var iconElement = document.createElement("span"); - iconElement.className = "timeline-tree-icon"; - this.listItemElement.appendChild(iconElement); - - this.typeElement = document.createElement("span"); - this.typeElement.className = "type"; - this.typeElement.textContent = this._record.title; - this.listItemElement.appendChild(this.typeElement); - - if (this._record.details) { - var separatorElement = document.createElement("span"); - separatorElement.className = "separator"; - separatorElement.textContent = " "; - - var dataElement = document.createElement("span"); - dataElement.className = "data"; - dataElement.textContent = "(" + this._record.details + ")"; - dataElement.addStyleClass("dimmed"); - this.listItemElement.appendChild(separatorElement); - this.listItemElement.appendChild(dataElement); + _addToRecordsWindow: function(record, recordsWindow) + { + recordsWindow.push(record); + if (!record.collapsed) { + var index = recordsWindow.length; + for (var i = 0; record.children && i < record.children.length; ++i) + this._addToRecordsWindow(record.children[i], recordsWindow); + record.visibleChildrenCount = recordsWindow.length - index; } }, - refresh: function() + _adjustScrollPosition: function(totalHeight) { - if (this._record.count > 1) - this.typeElement.textContent = this._record.title + " x " + this._record.count; + // Prevent the container from being scrolled off the end. + if ((this._containerElement.scrollTop + this._containerElement.offsetHeight) > totalHeight + 1) + this._containerElement.scrollTop = (totalHeight - this._containerElement.offsetHeight); } } -WebInspector.TimelineRecordTreeElement.prototype.__proto__ = TreeElement.prototype; +WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.Panel.prototype; + + +WebInspector.TimelineCategory = function(name, title, color) +{ + this.name = name; + this.title = title; + this.color = color; +} WebInspector.TimelineCalculator = function() { - WebInspector.AbstractTimelineCalculator.call(this); + this.windowLeft = 0.0; + this.windowRight = 1.0; + this._uiString = WebInspector.UIString.bind(WebInspector); } WebInspector.TimelineCalculator.prototype = { computeBarGraphPercentages: function(record) { - var start = ((record.startTime - this.minimumBoundary) / this.boundarySpan) * 100; - var end = ((record.endTime - this.minimumBoundary) / this.boundarySpan) * 100; + var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100; + var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100; return {start: start, end: end}; }, - computePercentageFromEventTime: function(eventTime) + get minimumBoundary() + { + if (typeof this._minimumBoundary === "number") + return this._minimumBoundary; + + if (typeof this.windowLeft === "number") + this._minimumBoundary = this._absoluteMinimumBoundary + this.windowLeft * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary); + else + this._minimumBoundary = this._absoluteMinimumBoundary; + return this._minimumBoundary; + }, + + get maximumBoundary() { - return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100; + if (typeof this._maximumBoundary === "number") + return this._maximumBoundary; + + if (typeof this.windowLeft === "number") + this._maximumBoundary = this._absoluteMinimumBoundary + this.windowRight * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary); + else + this._maximumBoundary = this._absoluteMaximumBoundary; + return this._maximumBoundary; }, - computeBarGraphLabels: function(record) + reset: function() { - return {tooltip: record.title}; + delete this._absoluteMinimumBoundary; + delete this._absoluteMaximumBoundary; + delete this._minimumBoundary; + delete this._maximumBoundary; }, updateBoundaries: function(record) @@ -287,76 +478,153 @@ WebInspector.TimelineCalculator.prototype = { var lowerBound = record.startTime; - if (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary) { - this.minimumBoundary = lowerBound; + if (typeof this._absoluteMinimumBoundary === "undefined" || lowerBound < this._absoluteMinimumBoundary) { + this._absoluteMinimumBoundary = lowerBound; + delete this._minimumBoundary; didChange = true; } var upperBound = record.endTime; - if (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary) { - this.maximumBoundary = upperBound; + if (typeof this._absoluteMaximumBoundary === "undefined" || upperBound > this._absoluteMaximumBoundary) { + this._absoluteMaximumBoundary = upperBound; + delete this._maximumBoundary; didChange = true; } return didChange; }, - formatValue: function(value) + get boundarySpan() { - return Number.secondsToString(value, WebInspector.UIString.bind(WebInspector)); + return this.maximumBoundary - this.minimumBoundary; }, + formatValue: function(value) + { + return Number.secondsToString(value + this.minimumBoundary - this._absoluteMinimumBoundary, this._uiString); + } } -WebInspector.TimelineCalculator.prototype.__proto__ = WebInspector.AbstractTimelineCalculator.prototype; - -WebInspector.TimelineGraph = function(record) +WebInspector.TimelineRecordListRow = function() { - this.record = record; + this.element = document.createElement("div"); + this.element.listRow = this; + var iconElement = document.createElement("span"); + iconElement.className = "timeline-tree-icon"; + this.element.appendChild(iconElement); - this._graphElement = document.createElement("div"); - this._graphElement.className = "timeline-graph-side"; + this._typeElement = document.createElement("span"); + this._typeElement.className = "type"; + this.element.appendChild(this._typeElement); - this._barAreaElement = document.createElement("div"); - this._barAreaElement.className = "timeline-graph-bar-area hidden"; - this._graphElement.appendChild(this._barAreaElement); + var separatorElement = document.createElement("span"); + separatorElement.className = "separator"; + separatorElement.textContent = " "; - this._barElement = document.createElement("div"); - this._barElement.className = "timeline-graph-bar"; - this._barAreaElement.appendChild(this._barElement); + this._dataElement = document.createElement("span"); + this._dataElement.className = "data dimmed"; + + this._repeatCountElement = document.createElement("span"); + this._repeatCountElement.className = "count"; - this._graphElement.addStyleClass("timeline-category-" + record.category.name); + this.element.appendChild(separatorElement); + this.element.appendChild(this._dataElement); + this.element.appendChild(this._repeatCountElement); } -WebInspector.TimelineGraph.prototype = { - get graphElement() +WebInspector.TimelineRecordListRow.prototype = { + update: function(record, isEven) { - return this._graphElement; - }, + this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : ""); + this._typeElement.textContent = record.title; - refreshLabelPositions: function() - { + if (record.details) { + this._dataElement.textContent = "(" + record.details + ")"; + this._dataElement.title = record.details; + } else { + this._dataElement.textContent = ""; + this._dataElement.title = ""; + } + + if (record.count > 1) + this._repeatCountElement.textContent = "\u2009\u00d7\u2009" + record.count; + else + this._repeatCountElement.textContent = ""; }, - refresh: function(calculator) + dispose: function() { - var percentages = calculator.computeBarGraphPercentages(this.record); - var labels = calculator.computeBarGraphLabels(this.record); + this.element.parentElement.removeChild(this.element); + } +} - this._percentages = percentages; - this._barAreaElement.removeStyleClass("hidden"); +WebInspector.TimelineRecordGraphRow = function(graphContainer, refreshCallback, rowHeight) +{ + this.element = document.createElement("div"); + this.element.graphRow = this; - if (!this._graphElement.hasStyleClass("timeline-category-" + this.record.category.name)) { - this._graphElement.removeMatchingStyleClasses("timeline-category-\\w+"); - this._graphElement.addStyleClass("timeline-category-" + this.record.category.name); + this._barAreaElement = document.createElement("div"); + this._barAreaElement.className = "timeline-graph-bar-area"; + this.element.appendChild(this._barAreaElement); + + this._barElement = document.createElement("div"); + this._barElement.className = "timeline-graph-bar"; + this._barAreaElement.appendChild(this._barElement); + + this._expandElement = document.createElement("div"); + this._expandElement.className = "timeline-expandable"; + graphContainer.appendChild(this._expandElement); + + var leftBorder = document.createElement("div"); + leftBorder.className = "timeline-expandable-left"; + this._expandElement.appendChild(leftBorder); + + this._expandElement.addEventListener("click", this._onClick.bind(this)); + this._refreshCallback = refreshCallback; + this._rowHeight = rowHeight; +} + +WebInspector.TimelineRecordGraphRow.prototype = { + update: function(record, isEven, calculator, clientWidth, expandOffset) + { + this._record = record; + this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : ""); + var percentages = calculator.computeBarGraphPercentages(record); + var left = percentages.start / 100 * clientWidth; + var width = (percentages.end - percentages.start) / 100 * clientWidth; + this._barElement.style.left = (left + expandOffset) + "px"; + this._barElement.style.width = width + "px"; + + if (record.visibleChildrenCount) { + this._expandElement.style.top = this.element.offsetTop + "px"; + this._expandElement.style.left = left + "px"; + this._expandElement.style.width = Math.max(12, width + 25) + "px"; + if (!record.collapsed) { + this._expandElement.style.height = (record.visibleChildrenCount + 1) * this._rowHeight + "px"; + this._expandElement.addStyleClass("timeline-expandable-expanded"); + this._expandElement.removeStyleClass("timeline-expandable-collapsed"); + } else { + this._expandElement.style.height = this._rowHeight + "px"; + this._expandElement.addStyleClass("timeline-expandable-collapsed"); + this._expandElement.removeStyleClass("timeline-expandable-expanded"); + } + this._expandElement.removeStyleClass("hidden"); + } else { + this._expandElement.addStyleClass("hidden"); } + }, - this._barElement.style.setProperty("left", percentages.start + "%"); - this._barElement.style.setProperty("right", (100 - percentages.end) + "%"); + _onClick: function(event) + { + this._record.collapsed = !this._record.collapsed; + this._refreshCallback(); + }, - var tooltip = (labels.tooltip || ""); - this._barElement.title = tooltip; + dispose: function() + { + this.element.parentElement.removeChild(this.element); + this._expandElement.parentElement.removeChild(this._expandElement); } } diff --git a/WebCore/inspector/front-end/TopDownProfileDataGridTree.js b/WebCore/inspector/front-end/TopDownProfileDataGridTree.js index 1b07883..bfcc25e 100644 --- a/WebCore/inspector/front-end/TopDownProfileDataGridTree.js +++ b/WebCore/inspector/front-end/TopDownProfileDataGridTree.js @@ -82,6 +82,7 @@ WebInspector.TopDownProfileDataGridTree.prototype = { return; this._save(); + profileDataGrideNode.savePosition(); this.children = [profileDataGrideNode]; this.totalTime = profileDataGrideNode.totalTime; @@ -102,6 +103,16 @@ WebInspector.TopDownProfileDataGridTree.prototype = { this.sort(this.lastComparator, true); }, + restore: function() + { + if (!this._savedChildren) + return; + + this.children[0].restorePosition(); + + WebInspector.ProfileDataGridTree.prototype.restore.call(this); + }, + _merge: WebInspector.TopDownProfileDataGridNode.prototype._merge, _sharedPopulate: WebInspector.TopDownProfileDataGridNode.prototype._sharedPopulate diff --git a/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js b/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js index 96a20ab..4804897 100644 --- a/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js +++ b/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js @@ -67,6 +67,8 @@ WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.Side WebInspector.WatchExpressionsSection = function() { + this._watchObjectGroupId = "watch-group"; + WebInspector.ObjectPropertiesSection.call(this); this.watchExpressions = this.loadSavedExpressions(); @@ -75,8 +77,6 @@ WebInspector.WatchExpressionsSection = function() this.editable = true; this.expanded = true; this.propertiesElement.addStyleClass("watch-expressions"); - - this._watchObjectGroupId = "watch-group"; } WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0"; @@ -112,11 +112,22 @@ WebInspector.WatchExpressionsSection.prototype = { // method to get all the properties refreshed at once. properties.push(property); - if (properties.length == propertyCount) + if (properties.length == propertyCount) { this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties); + + // check to see if we just added a new watch expression, + // which will always be the last property + if (this._newExpressionAdded) { + delete this._newExpressionAdded; + + treeElement = this.findAddedTreeElement(); + if (treeElement) + treeElement.startEditing(); + } + } } - InspectorController.releaseWrapperObjectGroup(this._watchObjectGroupId) + InspectorBackend.releaseWrapperObjectGroup(this._watchObjectGroupId) var properties = []; // Count the properties, so we known when to call this.updateProperties() @@ -150,14 +161,9 @@ WebInspector.WatchExpressionsSection.prototype = { addExpression: function() { + this._newExpressionAdded = true; this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression); this.update(); - - // After update(), the new empty expression to be edited - // will be in the tree, but we have to find it. - treeElement = this.findAddedTreeElement(); - if (treeElement) - treeElement.startEditing(); }, updateExpression: function(element, value) @@ -177,7 +183,7 @@ WebInspector.WatchExpressionsSection.prototype = { loadSavedExpressions: function() { - var json = InspectorController.setting("watchExpressions"); + var json = InspectorFrontendHost.setting("watchExpressions"); if (!json) return []; @@ -198,7 +204,7 @@ WebInspector.WatchExpressionsSection.prototype = { toSave.push(this.watchExpressions[i]); var json = JSON.stringify({expressions: toSave}); - InspectorController.setSetting("watchExpressions", json); + InspectorFrontendHost.setSetting("watchExpressions", json); return toSave.length; } diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc index a1d671e..eb299fc 100644 --- a/WebCore/inspector/front-end/WebKit.qrc +++ b/WebCore/inspector/front-end/WebKit.qrc @@ -9,7 +9,9 @@ <file>CallStackSidebarPane.js</file> <file>ChangesView.js</file> <file>Color.js</file> + <file>ConsolePanel.js</file> <file>ConsoleView.js</file> + <file>ContextMenu.js</file> <file>CookieItemsView.js</file> <file>Database.js</file> <file>DatabaseQueryView.js</file> @@ -17,7 +19,6 @@ <file>DataGrid.js</file> <file>DOMAgent.js</file> <file>DOMStorage.js</file> - <file>DOMStorageDataGrid.js</file> <file>DOMStorageItemsView.js</file> <file>Drawer.js</file> <file>ElementsPanel.js</file> @@ -28,6 +29,8 @@ <file>InjectedScript.js</file> <file>InjectedScriptAccess.js</file> <file>inspector.js</file> + <file>InspectorBackendStub.js</file> + <file>InspectorFrontendHostStub.js</file> <file>KeyboardShortcut.js</file> <file>MetricsSidebarPane.js</file> <file>Object.js</file> @@ -61,6 +64,8 @@ <file>TestController.js</file> <file>TextPrompt.js</file> <file>TimelineAgent.js</file> + <file>TimelineGrid.js</file> + <file>TimelineOverviewPane.js</file> <file>TimelinePanel.js</file> <file>TopDownProfileDataGridTree.js</file> <file>treeoutline.js</file> @@ -75,6 +80,7 @@ <file>Images/closeButtons.png</file> <file>Images/consoleButtonGlyph.png</file> <file>Images/cookie.png</file> + <file>Images/consoleIcon.png</file> <file>Images/database.png</file> <file>Images/databaseTable.png</file> <file>Images/debuggerContinue.png</file> @@ -161,6 +167,15 @@ <file>Images/statusbarResizerVertical.png</file> <file>Images/storageIcon.png</file> <file>Images/successGreenDot.png</file> + <file>Images/timelineBarBlue.png</file> + <file>Images/timelineBarGray.png</file> + <file>Images/timelineBarGreen.png</file> + <file>Images/timelineBarOrange.png</file> + <file>Images/timelineBarPurple.png</file> + <file>Images/timelineBarRed.png</file> + <file>Images/timelineBarYellow.png</file> + <file>Images/timelineCheckmarks.png</file> + <file>Images/timelineDots.png</file> <file>Images/timelineHollowPillBlue.png</file> <file>Images/timelineHollowPillGray.png</file> <file>Images/timelineHollowPillGreen.png</file> @@ -168,6 +183,7 @@ <file>Images/timelineHollowPillPurple.png</file> <file>Images/timelineHollowPillRed.png</file> <file>Images/timelineHollowPillYellow.png</file> + <file>Images/timelineIcon.png</file> <file>Images/timelinePillBlue.png</file> <file>Images/timelinePillGray.png</file> <file>Images/timelinePillGreen.png</file> diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css index 78ab23d..7cae8b2 100644 --- a/WebCore/inspector/front-end/inspector.css +++ b/WebCore/inspector/front-end/inspector.css @@ -94,7 +94,7 @@ body.attached #toolbar { padding-left: 0; } -body.attached.platform-qt #toolbar { +body.attached.port-qt #toolbar { cursor: auto; } @@ -215,6 +215,10 @@ body.attached #search-results-matches { background-image: url(Images/profilesIcon.png); } +.toolbar-item.console .toolbar-icon { + background-image: url(Images/consoleIcon.png); +} + #close-button-left, #close-button-right { width: 14px; height: 14px; @@ -237,7 +241,7 @@ body.detached .toolbar-item.close-left, body.detached .toolbar-item.close-right display: none; } -body.attached.platform-qt .toolbar-item.close-left, body.attached.platform-qt .toolbar-item.close-right { +body.attached.port-qt .toolbar-item.close-left, body.attached.port-qt .toolbar-item.close-right { display: none; } @@ -392,7 +396,7 @@ body.detached #dock-status-bar-item .glyph { -webkit-mask-image: url(Images/dockButtonGlyph.png); } -body.platform-qt #dock-status-bar-item { +body.port-qt #dock-status-bar-item { display: none } @@ -1432,7 +1436,7 @@ body.inactive .placard.selected { } .event-bars .event-bar .header .subtitle { - color: rgba(90, 90, 90, 0.742188); + color: rgba(90, 90, 90, 0.75); } .event-bars .event-bar .header::before { @@ -1777,8 +1781,8 @@ li.editing .swatch, li.editing .enabled-button, li.editing-sub-part .delete-but .sidebar { position: absolute; top: 0; + min-height: 100%; left: 0; - bottom: 0; width: 200px; overflow-y: auto; overflow-x: hidden; @@ -1957,6 +1961,7 @@ body.inactive .sidebar { .data-grid td { vertical-align: top; height: 12px; + line-height: 12px; padding: 2px 4px; white-space: nowrap; border-right: 1px solid #aaa; @@ -2413,9 +2418,14 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png); } -#resources-filter { +#resources-filter, #console-filter.console-filter-top { background: -webkit-gradient(linear, left top, left bottom, from(rgb(236, 236, 236)), to(rgb(217, 217, 217))); border-bottom: 1px solid rgb(64%, 64%, 64%); + width: 100%; +} + +#console-messages.console-filter-top { + margin-top: 23px; } #console-filter { @@ -2589,7 +2599,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { #resources-dividers-label-bar { position: absolute; - top: 93px; + top: 0; left: 0px; right: 0; background-color: rgba(255, 255, 255, 0.8); @@ -2740,6 +2750,10 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { display: block; } +.console-user-command-result { + display: block; +} + .resources-graph-bar.waiting { opacity: 0.35; } @@ -2857,7 +2871,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { .sidebar-resizer-vertical { position: absolute; top: 0; - bottom: 0; + min-height: 100%; width: 5px; z-index: 500; cursor: col-resize; @@ -3266,20 +3280,148 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { /* Timeline Style */ -#timeline-summary { +#timeline-overview-panel { position: absolute; top: 0; left: 0; - width: 0; - height: 0; + right: 0; + height: 80px; +} + +.timeline-sidebar-background { + top: 90px; + bottom: 0; +} + +.timeline .sidebar { + overflow-y: hidden; + z-index: 100; +} + +#timeline-overview-separator { + position: absolute; + top: 80px; + left: 0; + right: 0; + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(253, 253, 253)), to(rgb(213, 213, 213))); + border-top: 1px solid rgb(140, 140, 140); + border-bottom: 1px solid rgb(115, 115, 115); + height: 10px; +} + +#timeline-overview-sidebar { + position: absolute; + width: 200px; + top: 0px; + bottom: 0px; + left: 0px; + padding-top: 1px; + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(242, 242, 242)), to(rgb(209, 209, 209))); + border-right: 1px solid rgb(163, 163, 163); +} + +#timeline-overview-grid { + position: absolute; + top: 0px; + bottom: 0px; + left: 200px; + right: 0px; + background-color: rgb(224, 224, 224); +} + +#timeline-overview-window { + background-color: white; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 150; +} + +.timeline-window-resizer { + position: absolute; + top: 35px; + bottom: 15px; + width: 5px; + margin-left: -3px; + margin-right: -2px; + background-color: rgb(153, 153, 153); + z-index: 500; + cursor: col-resize; + -webkit-border-radius: 2px; + -webkit-box-shadow: white 1px 0 0, white -1px 0 0, white 0 1px 0, white 0 -1px 0; +} + +#timeline-overview-grid #resources-graphs { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 80px; +} + +#timeline-container { + position: absolute; + top: 90px; + left: 0; + bottom: 0; + right: 0; + border-right: 0 none transparent; + overflow-y: auto; + overflow-x: hidden; } .timeline-clear-status-bar-item .glyph { -webkit-mask-image: url(Images/clearConsoleButtonGlyph.png); } +.timeline-category-tree-item { + height: 20px; + line-height: 20px; + padding-left: 6px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + font-weight: bold; +} + +.timeline-category-tree-item .timeline-category-checkbox { + width: 10px; + height: 11px; + margin: 0 3px 0 5px; + padding: 0; + background-image: url(Images/timelineCheckmarks.png); + background-repeat: no-repeat; + background-position: 0 -66px; + vertical-align: -1px; + -webkit-appearance: none; +} + +.timeline-category-tree-item .timeline-category-checkbox:checked { + background-position-x: -10px; +} + +.timeline-category-tree-item.timeline-category-loading .timeline-category-checkbox { + background-position-y: 0; +} + +.timeline-category-tree-item.timeline-category-scripting .timeline-category-checkbox { + background-position-y: -33px; +} + +.timeline-category-tree-item.timeline-category-rendering .timeline-category-checkbox { + background-position-y: -11px; +} + +.timeline-category-tree-item:nth-of-type(2n) { + background-color: rgba(0, 0, 0, 0.05); +} + .timeline-tree-item { height: 18px; + line-height: 15px; + padding-right: 5px; padding-left: 10px; padding-top: 2px; white-space: nowrap; @@ -3287,10 +3429,44 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { overflow: hidden; } +.timeline-expandable { + position: absolute; + border-left: 1px solid rgb(163, 163, 163); +} + +.timeline-expandable-left { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 3px; + border-top: 1px solid rgb(163, 163, 163); + border-bottom: 1px solid rgb(163, 163, 163); +} + +.timeline-expandable-collapsed { + background-image: url(Images/disclosureTriangleSmallRightBlack.png); + background-position-x: 1px; + background-position-y: 2px; + background-repeat: no-repeat; +} + +.timeline-expandable-expanded { + background-image: url(Images/disclosureTriangleSmallDownBlack.png); + background-position-x: 1px; + background-position-y: 3px; + background-repeat: no-repeat; +} + .timeline-tree-item .type { padding-left: 14px; } +.timeline-tree-item .count { + font-family: Helvetica, Arial, sans-serif; + font-weight: bold; +} + .timeline-tree-item .timeline-tree-icon { background-image: url(Images/timelineDots.png); margin-top: 2px; @@ -3299,7 +3475,7 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { position: absolute; } -.timeline-tree-item:nth-of-type(2n) { +.timeline-tree-item.even { background-color: rgba(0, 0, 0, 0.05); } @@ -3307,14 +3483,12 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { color: rgba(0, 0, 0, 0.7); } -.timeline-category-loading, .timeline-category-scripting, .timeline-category-rendering { - display: none; -} - -.filter-all .timeline-category-loading, .filter-loading .timeline-category-loading, -.filter-all .timeline-category-scripting, .filter-scripting .timeline-category-scripting, -.filter-all .timeline-category-rendering, .filter-rendering .timeline-category-rendering { - display: list-item; +#timeline-overview-graphs { + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 20px; } #timeline-graphs { @@ -3333,29 +3507,42 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { margin-top: 0px; border-top: 1px solid transparent; overflow: hidden; + pointer-events: none; +} + +.timeline-overview-graph-side { + height: 20px; + z-index: 170; + pointer-events: none; +} + +.timeline-overview-graph-side .timeline-graph-bar { + height: 13px; } .timeline-graph-bar-area { position: absolute; top: 0; bottom: 0; - right: 8px; - left: 9px; + right: 0; + left: 3px; + pointer-events: none; } .timeline-graph-bar { position: absolute; top: 0; bottom: 0; - margin: auto -5px; + margin: auto -2px; border-width: 4px 4px 5px; height: 9px; - min-width: 7px; + min-width: 5px; opacity: 0.8; -webkit-border-image: url(Images/timelineBarGray.png) 4 4 5 4; + pointer-events: none; } -.timeline-graph-side:nth-of-type(2n) { +.timeline-graph-side.even { background-color: rgba(0, 0, 0, 0.05); } diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html index 04ab07a..77c7760 100644 --- a/WebCore/inspector/front-end/inspector.html +++ b/WebCore/inspector/front-end/inspector.html @@ -34,8 +34,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="utilities.js"></script> <script type="text/javascript" src="treeoutline.js"></script> <script type="text/javascript" src="inspector.js"></script> - <script type="text/javascript" src="InspectorControllerStub.js"></script> + <script type="text/javascript" src="InspectorBackendStub.js"></script> + <script type="text/javascript" src="InspectorFrontendHostStub.js"></script> <script type="text/javascript" src="Object.js"></script> + <script type="text/javascript" src="ContextMenu.js"></script> <script type="text/javascript" src="KeyboardShortcut.js"></script> <script type="text/javascript" src="TextPrompt.js"></script> <script type="text/javascript" src="Popup.js"></script> @@ -46,6 +48,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="ChangesView.js"></script> <script type="text/javascript" src="ConsoleView.js"></script> <script type="text/javascript" src="Panel.js"></script> + <script type="text/javascript" src="TimelineGrid.js"></script> <script type="text/javascript" src="AbstractTimelinePanel.js"></script> <script type="text/javascript" src="Resource.js"></script> <script type="text/javascript" src="ResourceCategory.js"></script> @@ -53,7 +56,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="DOMStorage.js"></script> <script type="text/javascript" src="DOMStorageItemsView.js"></script> <script type="text/javascript" src="DataGrid.js"></script> - <script type="text/javascript" src="DOMStorageDataGrid.js"></script> <script type="text/javascript" src="CookieItemsView.js"></script> <script type="text/javascript" src="Script.js"></script> <script type="text/javascript" src="Breakpoint.js"></script> @@ -80,6 +82,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="ScriptsPanel.js"></script> <script type="text/javascript" src="StoragePanel.js"></script> <script type="text/javascript" src="ProfilesPanel.js"></script> + <script type="text/javascript" src="ConsolePanel.js"></script> <script type="text/javascript" src="ResourceView.js"></script> <script type="text/javascript" src="SourceFrame.js"></script> <script type="text/javascript" src="SourceView.js"></script> @@ -97,6 +100,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="InjectedScriptAccess.js"></script> <script type="text/javascript" src="TimelineAgent.js"></script> <script type="text/javascript" src="TimelinePanel.js"></script> + <script type="text/javascript" src="TimelineOverviewPane.js"></script> <script type="text/javascript" src="TestController.js"></script> </head> <body class="detached"> @@ -109,7 +113,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. </div> <div id="main"> <div id="main-panels" tabindex="0" spellcheck="false"></div> - <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item toggled"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="changes-status-bar-item" class="status-bar-item hidden"></button><div id="count-items"><div id="changes-count" class="hidden"></div><div id="error-warning-count" class="hidden"></div></div></div></div> + <div id="main-status-bar" class="status-bar"><div id="anchored-status-bar-items"><button id="dock-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="console-status-bar-item" class="status-bar-item"><div class="glyph"></div><div class="glyph shadow"></div></button><button id="changes-status-bar-item" class="status-bar-item hidden"></button><div id="count-items"><div id="changes-count" class="hidden"></div><div id="error-warning-count" class="hidden"></div></div></div></div> </div> <div id="drawer"> <div id="console-view"><div id="console-messages"><div id="console-prompt" spellcheck="false"><br></div></div></div> diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js index c24d589..3f21f4f 100644 --- a/WebCore/inspector/front-end/inspector.js +++ b/WebCore/inspector/front-end/inspector.js @@ -46,10 +46,57 @@ var Preferences = { resourcesLargeRows: true } +function preloadImages() +{ + (new Image()).src = "Images/clearConsoleButtonGlyph.png"; + (new Image()).src = "Images/consoleButtonGlyph.png"; + (new Image()).src = "Images/dockButtonGlyph.png"; + (new Image()).src = "Images/enableOutlineButtonGlyph.png"; + (new Image()).src = "Images/enableSolidButtonGlyph.png"; + (new Image()).src = "Images/excludeButtonGlyph.png"; + (new Image()).src = "Images/focusButtonGlyph.png"; + (new Image()).src = "Images/largerResourcesButtonGlyph.png"; + (new Image()).src = "Images/nodeSearchButtonGlyph.png"; + (new Image()).src = "Images/pauseOnExceptionButtonGlyph.png"; + (new Image()).src = "Images/percentButtonGlyph.png"; + (new Image()).src = "Images/recordButtonGlyph.png"; + (new Image()).src = "Images/recordToggledButtonGlyph.png"; + (new Image()).src = "Images/reloadButtonGlyph.png"; + (new Image()).src = "Images/undockButtonGlyph.png"; +} + +preloadImages(); + var WebInspector = { resources: {}, resourceURLMap: {}, + cookieDomains: {}, missingLocalizedStrings: {}, + pendingDispatches: 0, + + // RegExp groups: + // 1 - scheme + // 2 - hostname + // 3 - ?port + // 4 - ?path + // 5 - ?fragment + URLRegExp: /^(http[s]?|file):\/\/([^\/:]+)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i, + + get platform() + { + if (!("_platform" in this)) + this._platform = InspectorFrontendHost.platform(); + + return this._platform; + }, + + get port() + { + if (!("_port" in this)) + this._port = InspectorFrontendHost.port(); + + return this._port; + }, get previousFocusElement() { @@ -126,41 +173,43 @@ var WebInspector = { for (var panelName in WebInspector.panels) { if (WebInspector.panels[panelName] == x) - InspectorController.storeLastActivePanel(panelName); + InspectorBackend.storeLastActivePanel(panelName); } }, _createPanels: function() { - var hiddenPanels = (InspectorController.hiddenPanels() || "").split(','); + var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(','); if (hiddenPanels.indexOf("elements") === -1) this.panels.elements = new WebInspector.ElementsPanel(); if (hiddenPanels.indexOf("resources") === -1) this.panels.resources = new WebInspector.ResourcesPanel(); if (hiddenPanels.indexOf("scripts") === -1) this.panels.scripts = new WebInspector.ScriptsPanel(); + if (hiddenPanels.indexOf("timeline") === -1) + this.panels.timeline = new WebInspector.TimelinePanel(); if (hiddenPanels.indexOf("profiles") === -1) { this.panels.profiles = new WebInspector.ProfilesPanel(); this.panels.profiles.registerProfileType(new WebInspector.CPUProfileType()); } - if (hiddenPanels.indexOf("timeline") === -1 && hiddenPanels.indexOf("timeline") === -1) - this.panels.timeline = new WebInspector.TimelinePanel(); if (hiddenPanels.indexOf("storage") === -1 && hiddenPanels.indexOf("databases") === -1) this.panels.storage = new WebInspector.StoragePanel(); + if (hiddenPanels.indexOf("console") === -1) + this.panels.console = new WebInspector.ConsolePanel(); }, _loadPreferences: function() { - var colorFormat = InspectorController.setting("color-format"); + var colorFormat = InspectorFrontendHost.setting("color-format"); if (colorFormat) Preferences.colorFormat = colorFormat; - var eventListenersFilter = InspectorController.setting("event-listeners-filter"); + var eventListenersFilter = InspectorFrontendHost.setting("event-listeners-filter"); if (eventListenersFilter) Preferences.eventListenersFilter = eventListenersFilter; - var resourcesLargeRows = InspectorController.setting("resources-large-rows"); + var resourcesLargeRows = InspectorFrontendHost.setting("resources-large-rows"); if (typeof resourcesLargeRows !== "undefined") Preferences.resourcesLargeRows = resourcesLargeRows; }, @@ -183,12 +232,12 @@ var WebInspector = { var body = document.body; if (x) { - InspectorController.attach(); + InspectorFrontendHost.attach(); body.removeStyleClass("detached"); body.addStyleClass("attached"); dockToggleButton.title = WebInspector.UIString("Undock into separate window."); } else { - InspectorController.detach(); + InspectorFrontendHost.detach(); body.removeStyleClass("attached"); body.addStyleClass("detached"); dockToggleButton.title = WebInspector.UIString("Dock to main window."); @@ -357,10 +406,10 @@ var WebInspector = { } if (this._hoveredDOMNode) { - InspectorController.highlightDOMNode(this._hoveredDOMNode.id); + InspectorBackend.highlightDOMNode(this._hoveredDOMNode.id); this.showingDOMNodeHighlight = true; } else { - InspectorController.hideDOMNodeHighlight(); + InspectorBackend.hideDOMNodeHighlight(); this.showingDOMNodeHighlight = false; } } @@ -368,11 +417,12 @@ var WebInspector = { WebInspector.loaded = function() { - var platform = InspectorController.platform(); + var platform = WebInspector.platform; document.body.addStyleClass("platform-" + platform); + var port = WebInspector.port; + document.body.addStyleClass("port-" + port); this._loadPreferences(); - this.pendingDispatches = 0; this.drawer = new WebInspector.Drawer(); this.console = new WebInspector.ConsoleView(this.drawer); @@ -429,11 +479,9 @@ WebInspector.loaded = function() document.addEventListener("keyup", this.documentKeyUp.bind(this), true); document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true); document.addEventListener("copy", this.documentCopy.bind(this), true); - document.addEventListener("contextmenu", this.contextMenu.bind(this), true); + document.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true); var mainPanelsElement = document.getElementById("main-panels"); - mainPanelsElement.handleKeyEvent = this.mainKeyDown.bind(this); - mainPanelsElement.handleKeyUpEvent = this.mainKeyUp.bind(this); mainPanelsElement.handleCopyEvent = this.mainCopy.bind(this); // Focus the mainPanelsElement in a timeout so it happens after the initial focus, @@ -461,23 +509,24 @@ WebInspector.loaded = function() var searchField = document.getElementById("search"); searchField.addEventListener("search", this.performSearch.bind(this), false); // when the search is emptied + searchField.addEventListener("mousedown", this.searchFieldManualFocus.bind(this), false); // when the search field is manually selected toolbarElement.addEventListener("mousedown", this.toolbarDragStart, true); document.getElementById("close-button-left").addEventListener("click", this.close, true); document.getElementById("close-button-right").addEventListener("click", this.close, true); - InspectorController.loaded(); + InspectorFrontendHost.loaded(); } var windowLoaded = function() { - var localizedStringsURL = InspectorController.localizedStringsURL(); + var localizedStringsURL = InspectorFrontendHost.localizedStringsURL(); if (localizedStringsURL) { var localizedStringsScriptElement = document.createElement("script"); localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false); localizedStringsScriptElement.type = "text/javascript"; localizedStringsScriptElement.src = localizedStringsURL; - document.getElementsByTagName("head").item(0).appendChild(localizedStringsScriptElement); + document.head.appendChild(localizedStringsScriptElement); } else WebInspector.loaded(); @@ -504,13 +553,14 @@ WebInspector.dispatch = function() { WebInspector.windowUnload = function(event) { - InspectorController.windowUnloading(); + InspectorFrontendHost.windowUnloading(); } WebInspector.windowResize = function(event) { if (this.currentPanel && this.currentPanel.resize) this.currentPanel.resize(); + this.drawer.resize(); } WebInspector.windowFocused = function(event) @@ -543,7 +593,7 @@ WebInspector.setAttachedWindow = function(attached) WebInspector.close = function(event) { - InspectorController.closeWindow(); + InspectorFrontendHost.closeWindow(); } WebInspector.documentClick = function(event) @@ -588,20 +638,28 @@ WebInspector.documentClick = function(event) WebInspector.documentKeyDown = function(event) { - if (!this.currentFocusElement) - return; - if (this.currentFocusElement.handleKeyEvent) - this.currentFocusElement.handleKeyEvent(event); - else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "KeyDown"]) - WebInspector[this.currentFocusElement.id + "KeyDown"](event); + if (this.currentFocusElement) { + if (this.currentFocusElement.handleKeyEvent) + this.currentFocusElement.handleKeyEvent(event); + else if (this.currentFocusElement.id && this.currentFocusElement.id.length && WebInspector[this.currentFocusElement.id + "KeyDown"]) + WebInspector[this.currentFocusElement.id + "KeyDown"](event); + if (event.handled) + return; + } + + if (this.currentPanel && this.currentPanel.handleKeyEvent) + this.currentPanel.handleKeyEvent(event); if (!event.handled) { - var isMac = InspectorController.platform().indexOf("mac-") === 0; + var isMac = WebInspector.isMac(); switch (event.keyIdentifier) { case "U+001B": // Escape key - this.drawer.visible = !this.drawer.visible; event.preventDefault(); + if (this.drawer.fullPanel) + return; + + this.drawer.visible = !this.drawer.visible; break; case "U+0046": // F key @@ -675,9 +733,15 @@ WebInspector.documentKeyDown = function(event) WebInspector.documentKeyUp = function(event) { - if (!this.currentFocusElement || !this.currentFocusElement.handleKeyUpEvent) - return; - this.currentFocusElement.handleKeyUpEvent(event); + if (this.currentFocusElement) { + if (this.currentFocusElement.handleKeyUpEvent) + this.currentFocusElement.handleKeyUpEvent(event); + if (event.handled) + return; + } + + if (this.currentPanel && this.currentPanel.handleKeyUpEvent) + this.currentPanel.handleKeyUpEvent(event); } WebInspector.documentCanCopy = function(event) @@ -701,53 +765,43 @@ WebInspector.documentCopy = function(event) WebInspector[this.currentFocusElement.id + "Copy"](event); } -WebInspector.contextMenu = function(event) +WebInspector.contextMenuEventFired = function(event) { if (event.handled || event.target.hasStyleClass("popup-glasspane")) event.preventDefault(); } -WebInspector.mainKeyDown = function(event) -{ - if (this.currentPanel && this.currentPanel.handleKeyEvent) - this.currentPanel.handleKeyEvent(event); -} - -WebInspector.mainKeyUp = function(event) -{ - if (this.currentPanel && this.currentPanel.handleKeyUpEvent) - this.currentPanel.handleKeyUpEvent(event); -} - WebInspector.mainCopy = function(event) { if (this.currentPanel && this.currentPanel.handleCopyEvent) this.currentPanel.handleCopyEvent(event); } -WebInspector.animateStyle = function(animations, duration, callback, complete) +WebInspector.animateStyle = function(animations, duration, callback) { - if (complete === undefined) - complete = 0; - var slice = (1000 / 30); // 30 frames per second + var interval; + var complete = 0; + + const intervalDuration = (1000 / 30); // 30 frames per second. + const animationsLength = animations.length; + const propertyUnit = {opacity: ""}; + const defaultUnit = "px"; - var defaultUnit = "px"; - var propertyUnit = {opacity: ""}; + function cubicInOut(t, b, c, d) + { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + } - for (var i = 0; i < animations.length; ++i) { + // Pre-process animations. + for (var i = 0; i < animationsLength; ++i) { var animation = animations[i]; - var element = null; - var start = null; - var current = null; - var end = null; - var key = null; + var element = null, start = null, end = null, key = null; for (key in animation) { if (key === "element") element = animation[key]; else if (key === "start") start = animation[key]; - else if (key === "current") - current = animation[key]; else if (key === "end") end = animation[key]; } @@ -755,49 +809,54 @@ WebInspector.animateStyle = function(animations, duration, callback, complete) if (!element || !end) continue; - var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element); if (!start) { + var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element); start = {}; for (key in end) start[key] = parseInt(computedStyle.getPropertyValue(key)); animation.start = start; - } else if (complete == 0) + } else for (key in start) element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); + } - if (!current) { - current = {}; - for (key in start) - current[key] = start[key]; - animation.current = current; - } - - function cubicInOut(t, b, c, d) - { - if ((t/=d/2) < 1) return c/2*t*t*t + b; - return c/2*((t-=2)*t*t + 2) + b; + function animateLoop() + { + // Advance forward. + complete += intervalDuration; + var next = complete + intervalDuration; + + // Make style changes. + for (var i = 0; i < animationsLength; ++i) { + var animation = animations[i]; + var element = animation.element; + var start = animation.start; + var end = animation.end; + if (!element || !end) + continue; + + var style = element.style; + for (key in end) { + var endValue = end[key]; + if (next < duration) { + var startValue = start[key]; + var newValue = cubicInOut(complete, startValue, endValue - startValue, duration); + style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); + } else + style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); + } } - var style = element.style; - for (key in end) { - var startValue = start[key]; - var currentValue = current[key]; - var endValue = end[key]; - if ((complete + slice) < duration) { - var delta = (endValue - startValue) / (duration / slice); - var newValue = cubicInOut(complete, startValue, endValue - startValue, duration); - style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); - current[key] = newValue; - } else { - style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); - } + // End condition. + if (complete >= duration) { + clearInterval(interval); + if (callback) + callback(); } } - if (complete < duration) - setTimeout(WebInspector.animateStyle, slice, animations, duration, callback, complete + slice); - else if (callback) - callback(); + interval = setInterval(animateLoop, intervalDuration); + return interval; } WebInspector.updateSearchLabel = function() @@ -817,11 +876,12 @@ WebInspector.updateSearchLabel = function() WebInspector.toggleAttach = function() { this.attached = !this.attached; + this.drawer.resize(); } WebInspector.toolbarDragStart = function(event) { - if ((!WebInspector.attached && InspectorController.platform() !== "mac-leopard") || InspectorController.platform() == "qt") + if ((!WebInspector.attached && WebInspector.platform !== "mac-leopard") || WebInspector.port == "qt") return; var target = event.target; @@ -855,14 +915,14 @@ WebInspector.toolbarDrag = function(event) if (WebInspector.attached) { var height = window.innerHeight - (event.screenY - toolbar.lastScreenY); - InspectorController.setAttachedWindowHeight(height); + InspectorFrontendHost.setAttachedWindowHeight(height); } else { var x = event.screenX - toolbar.lastScreenX; var y = event.screenY - toolbar.lastScreenY; // We cannot call window.moveBy here because it restricts the movement // of the window at the edges. - InspectorController.moveByUnrestricted(x, y); + InspectorFrontendHost.moveWindowBy(x, y); } toolbar.lastScreenX = event.screenX; @@ -925,6 +985,11 @@ WebInspector.showScriptsPanel = function() this.currentPanel = this.panels.scripts; } +WebInspector.showTimelinePanel = function() +{ + this.currentPanel = this.panels.timeline; +} + WebInspector.showProfilesPanel = function() { this.currentPanel = this.panels.profiles; @@ -935,11 +1000,17 @@ WebInspector.showStoragePanel = function() this.currentPanel = this.panels.storage; } +WebInspector.showConsolePanel = function() +{ + this.currentPanel = this.panels.console; +} + WebInspector.addResource = function(identifier, payload) { var resource = new WebInspector.Resource( payload.requestHeaders, payload.requestURL, + payload.documentURL, payload.host, payload.path, payload.lastPathComponent, @@ -956,6 +1027,10 @@ WebInspector.addResource = function(identifier, payload) if (this.panels.resources) this.panels.resources.addResource(resource); + + var match = payload.documentURL.match(/^(http[s]?|file):\/\/([\/]*[^\/]+)/i); + if (match) + this.addCookieDomain(match[1].toLowerCase() === "file" ? "" : match[2]); } WebInspector.clearConsoleMessages = function() @@ -1021,7 +1096,7 @@ WebInspector.updateResource = function(identifier, payload) resource.responseReceivedTime = payload.responseReceivedTime; if (payload.endTime) resource.endTime = payload.endTime; - + if (payload.loadEventTime) { // This loadEventTime is for the main resource, and we want to show it // for all resources on this page. This means we want to set it as a member @@ -1029,7 +1104,7 @@ WebInspector.updateResource = function(identifier, payload) if (this.panels.resources) this.panels.resources.mainResourceLoadTime = payload.loadEventTime; } - + if (payload.domContentEventTime) { // This domContentEventTime is for the main resource, so it should go in // the resources panel for the same reasons as above. @@ -1055,6 +1130,8 @@ WebInspector.removeResource = function(identifier) WebInspector.addDatabase = function(payload) { + if (!this.panels.storage) + return; var database = new WebInspector.Database( payload.id, payload.domain, @@ -1065,12 +1142,20 @@ WebInspector.addDatabase = function(payload) WebInspector.addCookieDomain = function(domain) { - if (this.panels.storage) - this.panels.storage.addCookieDomain(domain); + // Eliminate duplicate domains from the list. + if (domain in this.cookieDomains) + return; + this.cookieDomains[domain] = true; + + if (!this.panels.storage) + return; + this.panels.storage.addCookieDomain(domain); } WebInspector.addDOMStorage = function(payload) { + if (!this.panels.storage) + return; var domStorage = new WebInspector.DOMStorage( payload.id, payload.host, @@ -1080,6 +1165,8 @@ WebInspector.addDOMStorage = function(payload) WebInspector.updateDOMStorage = function(storageId) { + if (!this.panels.storage) + return; this.panels.storage.updateDOMStorage(storageId); } @@ -1160,6 +1247,7 @@ WebInspector.reset = function() this.resources = {}; this.resourceURLMap = {}; + this.cookieDomains = {}; this.hoveredDOMNode = null; delete this.mainResource; @@ -1202,23 +1290,23 @@ WebInspector.log = function(message) { // remember 'this' for setInterval() callback var self = this; - + // return indication if we can actually log a message function isLogAvailable() { return WebInspector.ConsoleMessage && WebInspector.ObjectProxy && self.console; } - + // flush the queue of pending messages function flushQueue() { var queued = WebInspector.log.queued; - if (!queued) + if (!queued) return; - + for (var i = 0; i < queued.length; ++i) logMessage(queued[i]); - + delete WebInspector.log.queued; } @@ -1228,26 +1316,26 @@ WebInspector.log = function(message) { if (!isLogAvailable()) return; - + clearInterval(WebInspector.log.interval); delete WebInspector.log.interval; - + flushQueue(); } - + // actually log the message function logMessage(message) { var repeatCount = 1; if (message == WebInspector.log.lastMessage) repeatCount = WebInspector.log.repeatCount + 1; - + WebInspector.log.lastMessage = message; WebInspector.log.repeatCount = repeatCount; - + // ConsoleMessage expects a proxy object message = new WebInspector.ObjectProxy(null, [], 0, message, false); - + // post the message var msg = new WebInspector.ConsoleMessage( WebInspector.ConsoleMessage.MessageSource.Other, @@ -1258,20 +1346,20 @@ WebInspector.log = function(message) null, repeatCount, message); - + self.console.addMessage(msg); } - + // if we can't log the message, queue it if (!isLogAvailable()) { if (!WebInspector.log.queued) WebInspector.log.queued = []; - + WebInspector.log.queued.push(message); - + if (!WebInspector.log.interval) WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000); - + return; } @@ -1284,7 +1372,7 @@ WebInspector.log = function(message) WebInspector.addProfileHeader = function(profile) { - this.panels.profiles.addProfileHeader(WebInspector.CPUProfileType.TypeId, new WebInspector.CPUProfile(profile)); + this.panels.profiles.addProfileHeader(profile); } WebInspector.setRecordingProfile = function(isProfiling) @@ -1383,7 +1471,7 @@ WebInspector.showResourceForURL = function(url, line, preferredPanel) WebInspector.linkifyStringAsFragment = function(string) { var container = document.createDocumentFragment(); - var linkStringRegEx = new RegExp("(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}://|www\\.)[\\w$\\-_+*'=\\|/\\\\(){}[\\]%@&#~,:;.!?]{2,}[\\w$\\-_+*=\\|/\\\\({%@&#~]"); + var linkStringRegEx = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/|www\.)[\w$\-_+*'=\|\/\\(){}[\]%@&#~,:;.!?]{2,}[\w$\-_+*=\|\/\\({%@&#~]/; while (string) { var linkString = linkStringRegEx.exec(string); @@ -1411,12 +1499,13 @@ WebInspector.linkifyStringAsFragment = function(string) return container; } -WebInspector.showProfileForURL = function(url) { +WebInspector.showProfileForURL = function(url) +{ WebInspector.showProfilesPanel(); WebInspector.panels.profiles.showProfileForURL(url); } -WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal) +WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, tooltipText) { if (!linkText) linkText = url; @@ -1426,18 +1515,18 @@ WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal) var a = document.createElement("a"); a.href = url; a.className = classes; - a.title = url; + a.title = tooltipText || url; a.target = "_blank"; a.textContent = linkText; return a; } -WebInspector.linkifyURL = function(url, linkText, classes, isExternal) +WebInspector.linkifyURL = function(url, linkText, classes, isExternal, tooltipText) { // Use the DOM version of this function so as to avoid needing to escape attributes. // FIXME: Get rid of linkifyURL entirely. - return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal).outerHTML; + return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal, tooltipText).outerHTML; } WebInspector.addMainEventListeners = function(doc) @@ -1447,8 +1536,33 @@ WebInspector.addMainEventListeners = function(doc) doc.addEventListener("click", this.documentClick.bind(this), true); } +WebInspector.searchFieldManualFocus = function(event) +{ + this.currentFocusElement = event.target; + this._previousFocusElement = event.target; +} + WebInspector.searchKeyDown = function(event) { + // Escape Key will clear the field and clear the search results + if (event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Esc) { + event.preventDefault(); + // When search was selected manually and is currently blank, we'd like Esc stay unhandled + // and hit console drawer handler. + event.handled = !(this.previousFocusElement === event.target && event.target.value === ""); + event.target.value = ""; + + this.performSearch(event); + this.currentFocusElement = this.previousFocusElement; + if (this.currentFocusElement === event.target) + this.currentFocusElement.select(); + return false; + } else if (event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Backspace || + event.keyCode === WebInspector.KeyboardShortcut.KeyCodes.Delete) { + event.handled = true; + return false; + } + if (!isEnterKey(event)) return false; @@ -1558,7 +1672,7 @@ WebInspector.UIString = function(string) string = window.localizedStrings[string]; else { if (!(string in this.missingLocalizedStrings)) { - if (!WebInspector.InspectorControllerStub) + if (!WebInspector.InspectorBackendStub) console.error("Localized string \"" + string + "\" not found."); this.missingLocalizedStrings[string] = true; } @@ -1570,6 +1684,14 @@ WebInspector.UIString = function(string) return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); } +WebInspector.isMac = function() +{ + if (!("_isMac" in this)) + this._isMac = WebInspector.platform.indexOf("mac-") === 0; + + return this._isMac; +} + WebInspector.isBeingEdited = function(element) { return element.__editing; @@ -1645,6 +1767,8 @@ WebInspector.startEditing = function(element, committedCallback, cancelledCallba if (isEnterKey(event)) { editingCommitted.call(element); event.preventDefault(); + event.stopPropagation(); + event.handled = true; } else if (event.keyCode === 27) { // Escape key editingCancelled.call(element); event.preventDefault(); diff --git a/WebCore/inspector/front-end/inspectorSyntaxHighlight.css b/WebCore/inspector/front-end/inspectorSyntaxHighlight.css index 2cbb3c5..e3e3074 100644 --- a/WebCore/inspector/front-end/inspectorSyntaxHighlight.css +++ b/WebCore/inspector/front-end/inspectorSyntaxHighlight.css @@ -26,33 +26,29 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -.webkit-css-comment { - color: rgb(0, 116, 0); -} + .webkit-css-comment { + color: rgb(0, 116, 0); + } -.webkit-css-string, .webkit-css-keyword, .webkit-css-unit { - color: rgb(7, 144, 154); -} + .webkit-css-url, .webkit-css-color, .webkit-css-string, .webkit-css-keyword { + color: rgb(7, 144, 154); + } -.webkit-css-number { - color: rgb(50, 0, 255); -} + .webkit-css-number { + color: rgb(50, 0, 255); + } -.webkit-css-property, .webkit-css-at-rule { - color: rgb(200, 0, 0); -} + .webkit-css-property, .webkit-css-at-rule { + color: rgb(200, 0, 0); + } -.webkit-css-url { - color: rgb(0, 0, 0); -} - -.webkit-css-selector { - color: rgb(0, 0, 0); -} + .webkit-css-selector { + rgb(0, 0, 0); + } -.webkit-css-pseudo-class { - color: rgb(128, 128, 128); -} + .webkit-css-important { + color: rgb(200, 0, 180); + } .webkit-javascript-comment { color: rgb(0, 116, 0); diff --git a/WebCore/inspector/front-end/treeoutline.js b/WebCore/inspector/front-end/treeoutline.js index ecc322b..2cde151 100644 --- a/WebCore/inspector/front-end/treeoutline.js +++ b/WebCore/inspector/front-end/treeoutline.js @@ -624,7 +624,7 @@ TreeElement.treeElementDoubleClicked = function(event) return; if (element.treeElement.ondblclick) - element.treeElement.ondblclick(element.treeElement, event); + element.treeElement.ondblclick.call(element.treeElement, event); else if (element.treeElement.hasChildren && !element.treeElement.expanded) element.treeElement.expand(); } diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js index e9d185f..04c9032 100644 --- a/WebCore/inspector/front-end/utilities.js +++ b/WebCore/inspector/front-end/utilities.js @@ -147,13 +147,18 @@ Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, di Element.prototype.removeStyleClass = function(className) { - // Test for the simple case before using a RegExp. + // Test for the simple case first. if (this.className === className) { this.className = ""; return; } - this.removeMatchingStyleClasses(className.escapeForRegExp()); + var index = this.className.indexOf(className); + if (index === -1) + return; + + var newClassName = " " + this.className + " "; + this.className = newClassName.replace(" " + className + " ", " "); } Element.prototype.removeMatchingStyleClasses = function(classNameRegex) @@ -173,11 +178,15 @@ Element.prototype.hasStyleClass = function(className) { if (!className) return false; - // Test for the simple case before using a RegExp. + // Test for the simple case if (this.className === className) return true; - var regex = new RegExp("(^|\\s)" + className.escapeForRegExp() + "($|\\s)"); - return regex.test(this.className); + + var index = this.className.indexOf(className); + if (index === -1) + return false; + var toTest = " " + this.className + " "; + return toTest.indexOf(" " + className + " ", index) !== -1; } Element.prototype.positionAt = function(x, y) @@ -222,8 +231,7 @@ Element.prototype.query = function(query) Element.prototype.removeChildren = function() { - while (this.firstChild) - this.removeChild(this.firstChild); + this.innerHTML = ""; } Element.prototype.isInsertionCaretInside = function() @@ -342,7 +350,7 @@ String.prototype.trimWhitespace = function() String.prototype.trimURL = function(baseURLDomain) { - var result = this.replace(new RegExp("^http[s]?:\/\/", "i"), ""); + var result = this.replace(/^https?:\/\//i, ""); if (baseURLDomain) result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), ""); return result; @@ -542,6 +550,9 @@ Number.secondsToString = function(seconds, formatterFunction, higherResolution) if (!formatterFunction) formatterFunction = String.sprintf; + if (seconds === 0) + return "0"; + var ms = seconds * 1000; if (higherResolution && ms < 1000) return formatterFunction("%.3fms", ms); @@ -822,3 +833,7 @@ function isEnterKey(event) { // Check if in IME. return event.keyCode !== 229 && event.keyIdentifier === "Enter"; } + +function isFnKey(event) { + return event.keyCode >= 112 && event.keyCode <= 123; +} |