diff options
Diffstat (limited to 'WebCore/inspector/front-end')
28 files changed, 896 insertions, 1477 deletions
diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js index d4693b7..6851eea 100644 --- a/WebCore/inspector/front-end/ConsoleView.js +++ b/WebCore/inspector/front-end/ConsoleView.js @@ -175,7 +175,7 @@ WebInspector.ConsoleView.prototype = { clearMessages: function(clearInspectorController) { if (clearInspectorController) - InspectorController.clearMessages(false); + InspectorController.clearMessages(); if (WebInspector.panels.resources) WebInspector.panels.resources.clearMessages(); @@ -212,42 +212,10 @@ WebInspector.ConsoleView.prototype = { return; var reportCompletions = this._reportCompletions.bind(this, bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix); - // Collect comma separated object properties for the completion. - - if (!expressionString) { - if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) { - // Evaluate into properties in scope of the selected call frame. - reportCompletions(WebInspector.panels.scripts.variablesInSelectedCallFrame()); - return; - } else { - expressionString = "this"; - } - } - - function parsingCallback(result, isException) - { - if (!isException) - result = JSON.parse(result); - reportCompletions(result, isException); - } - - this._evalInInspectedWindow( - "(function() {" + - "var props = {};" + - "for (var prop in (" + expressionString + ")) props[prop] = true;" + - ((!dotNotation && !bracketNotation) ? - "for (var prop in window._inspectorCommandLineAPI)" + - "if (prop.charAt(0) !== '_') props[prop] = true;" - : "") + - "return JSON.stringify(props);" + - "})()", - parsingCallback); + this._evalInInspectedWindow(expressionString, reportCompletions); }, - _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result, isException) { - if (isException) - return; - + _reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, result) { if (bracketNotation) { if (prefix.length && prefix[0] === "'") var quoteUsed = "'"; @@ -256,7 +224,16 @@ WebInspector.ConsoleView.prototype = { } var results = []; - var properties = Object.sortedProperties(result); + var properties = Object.properties(result); + if (!dotNotation && !bracketNotation && result._inspectorCommandLineAPI) { + var commandLineAPI = Object.properties(result._inspectorCommandLineAPI); + for (var i = 0; i < commandLineAPI.length; ++i) { + var property = commandLineAPI[i]; + if (property.charAt(0) !== "_") + properties.push(property); + } + } + properties.sort(); for (var i = 0; i < properties.length; ++i) { var property = properties[i]; @@ -311,7 +288,7 @@ WebInspector.ConsoleView.prototype = { if (!link || !link.representedNode) return; - WebInspector.updateFocusedNode(link.representedNode.id); + WebInspector.updateFocusedNode(link.representedNode); event.stopPropagation(); event.preventDefault(); }, @@ -336,6 +313,74 @@ WebInspector.ConsoleView.prototype = { this.doEvalInWindow(expression, callback); }, + _ensureCommandLineAPIInstalled: function(inspectedWindow) + { + if (!inspectedWindow._inspectorCommandLineAPI) { + inspectedWindow.eval("window._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) }, \ + _inspectedNodes: [], \ + get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \ + get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \ + get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \ + get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \ + get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \ + };"); + + inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(this.clearMessages.bind(this)); + inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(inspectObject.bind(this)); + + function inspectObject(o) + { + if (arguments.length === 0) + return; + + InspectorController.inspectedWindow().console.log(o); + if (Object.type(o, InspectorController.inspectedWindow()) === "node") { + WebInspector.showElementsPanel(); + WebInspector.panels.elements.treeOutline.revealAndSelectNode(o); + } else { + switch (Object.describe(o)) { + case "Database": + WebInspector.showDatabasesPanel(); + WebInspector.panels.databases.selectDatabase(o); + break; + case "Storage": + WebInspector.showDatabasesPanel(); + WebInspector.panels.databases.selectDOMStorage(o); + break; + } + } + } + } + }, + + addInspectedNode: function(node) + { + var inspectedWindow = InspectorController.inspectedWindow(); + this._ensureCommandLineAPIInstalled(inspectedWindow); + var inspectedNodes = inspectedWindow._inspectorCommandLineAPI._inspectedNodes; + inspectedNodes.unshift(node); + if (inspectedNodes.length >= 5) + inspectedNodes.pop(); + }, + doEvalInWindow: function(expression, callback) { if (!expression) { @@ -343,15 +388,22 @@ WebInspector.ConsoleView.prototype = { expression = "this"; } + // 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._inspectorCommandLineAPI) { with (window) { " + expression + " } }"; + var self = this; - function evalCallback(result) + function delayedEvaluation() { - if (result.exception) - callback(result.exception, true); - else - callback(result.value, false); - }; - InspectorController.evaluate(expression, evalCallback); + var inspectedWindow = InspectorController.inspectedWindow(); + self._ensureCommandLineAPIInstalled(inspectedWindow); + try { + callback(inspectedWindow.eval(expression)); + } catch (e) { + callback(e, true); + } + } + setTimeout(delayedEvaluation, 0); }, _enterKeyPressed: function(event) @@ -384,10 +436,13 @@ WebInspector.ConsoleView.prototype = { _format: function(output, forceObjectFormat) { + var inspectedWindow = InspectorController.inspectedWindow(); if (forceObjectFormat) var type = "object"; + else if (output instanceof inspectedWindow.NodeList) + var type = "array"; else - var type = Object.proxyType(output); + var type = Object.type(output, inspectedWindow); // We don't perform any special formatting on these types, so we just // pass them through the simple _formatvalue function. @@ -396,6 +451,8 @@ WebInspector.ConsoleView.prototype = { "null": 1, "boolean": 1, "number": 1, + "date": 1, + "function": 1, }; var formatter; @@ -422,16 +479,6 @@ WebInspector.ConsoleView.prototype = { elem.appendChild(document.createTextNode(val)); }, - _formatfunction: function(func, elem) - { - elem.appendChild(document.createTextNode(func.description)); - }, - - _formatdate: function(date, elem) - { - elem.appendChild(document.createTextNode(date.description)); - }, - _formatstring: function(str, elem) { elem.appendChild(document.createTextNode("\"" + str + "\"")); @@ -439,7 +486,7 @@ WebInspector.ConsoleView.prototype = { _formatregexp: function(re, elem) { - var formatted = String(re.description).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); + var formatted = String(re).replace(/([\\\/])/g, "\\$1").replace(/\\(\/[gim]*)$/, "$1").substring(1); elem.appendChild(document.createTextNode(formatted)); }, @@ -454,10 +501,10 @@ WebInspector.ConsoleView.prototype = { elem.appendChild(document.createTextNode("]")); }, - _formatnode: function(object, elem) + _formatnode: function(node, elem) { var treeOutline = new WebInspector.ElementsTreeOutline(); - treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(object.nodeId); + treeOutline.rootDOMNode = node; treeOutline.element.addStyleClass("outline-disclosure"); if (!treeOutline.children[0].hasChildren) treeOutline.element.addStyleClass("single-node"); @@ -466,7 +513,7 @@ WebInspector.ConsoleView.prototype = { _formatobject: function(obj, elem) { - elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description, null, true).element); + elem.appendChild(new WebInspector.ObjectPropertiesSection(new WebInspector.ObjectProxy(obj), Object.describe(obj, true), null, null, true).element); }, _formaterror: function(obj, elem) diff --git a/WebCore/inspector/front-end/CookieItemsView.js b/WebCore/inspector/front-end/CookieItemsView.js deleted file mode 100644 index 2d69e7d..0000000 --- a/WebCore/inspector/front-end/CookieItemsView.js +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All rights reserved. - * 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.CookieItemsView = function() -{ - WebInspector.View.call(this); - - // Some Platforms have not yet implemented access to raw cookies - // Those platforms will return undefined instead of an Array - // For these platforms we: - // - resort to document.cookie - // - do not show the delete cookie status bar button - this._useFallback = typeof InspectorController.cookies() === "undefined"; - - this.element.addStyleClass("storage-view"); - this.element.addStyleClass("table"); - - this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); - this.deleteButton.visible = false; - this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); - - this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); - this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); -} - -WebInspector.CookieItemsView.prototype = { - get statusBarItems() - { - if (this._useFallback) - return [this.refreshButton.element]; - else - return [this.refreshButton.element, this.deleteButton.element]; - }, - - show: function(parentElement) - { - WebInspector.View.prototype.show.call(this, parentElement); - this.update(); - }, - - hide: function() - { - WebInspector.View.prototype.hide.call(this); - this.deleteButton.visible = false; - }, - - update: function() - { - if (this._useFallback) { - this.fallbackUpdate(); - return; - } - - this.element.removeChildren(); - var dataGrid = this.dataGridForCookies(); - if (dataGrid) { - this._dataGrid = dataGrid; - this.element.appendChild(dataGrid.element); - this.deleteButton.visible = true; - } else { - var emptyMsgElement = document.createElement("div"); - emptyMsgElement.className = "storage-table-empty"; - emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies."); - this.element.appendChild(emptyMsgElement); - this._dataGrid = null; - this.deleteButton.visible = false; - } - }, - - buildCookies: function() - { - var rawCookies = InspectorController.cookies(); - var cookies = []; - for (var i = 0; i < rawCookies.length; ++i) { - var cookie = rawCookies[i]; - cookie.expires = new Date(cookie.expires); - cookies.push(cookie); - } - - return cookies; - }, - - dataGridForCookies: function() - { - var cookies = this.buildCookies(); - if (!cookies.length) - return null; - - var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} }; - columns[0].title = WebInspector.UIString("Name"); - columns[0].width = columns[0].title.length; - columns[1].title = WebInspector.UIString("Value"); - columns[1].width = columns[1].title.length; - columns[2].title = WebInspector.UIString("Domain"); - columns[2].width = columns[2].title.length; - columns[3].title = WebInspector.UIString("Path"); - columns[3].width = columns[3].title.length; - columns[4].title = WebInspector.UIString("Expires"); - columns[4].width = columns[4].title.length; - columns[5].title = WebInspector.UIString("Size"); - columns[5].width = columns[5].title.length; - columns[5].aligned = "right"; - columns[6].title = WebInspector.UIString("HTTP"); - columns[6].width = columns[6].title.length; - columns[6].aligned = "centered"; - columns[7].title = WebInspector.UIString("Secure"); - columns[7].width = columns[7].title.length; - columns[7].aligned = "centered"; - - function updateDataAndColumn(index, value) { - data[index] = value; - if (value.length > columns[index].width) - columns[index].width = value.length; - } - - var data; - var nodes = []; - for (var i = 0; i < cookies.length; ++i) { - var cookie = cookies[i]; - data = {}; - - updateDataAndColumn(0, cookie.name); - updateDataAndColumn(1, cookie.value); - updateDataAndColumn(2, cookie.domain); - updateDataAndColumn(3, cookie.path); - updateDataAndColumn(4, (cookie.session ? "Session" : cookie.expires.toGMTString())); - updateDataAndColumn(5, Number.bytesToString(cookie.size, WebInspector.UIString)); - updateDataAndColumn(6, (cookie.httpOnly ? "\u2713" : "")); // Checkmark - updateDataAndColumn(7, (cookie.secure ? "\u2713" : "")); // Checkmark - - var node = new WebInspector.DataGridNode(data, false); - node.cookie = cookie; - node.selectable = true; - nodes.push(node); - } - - var totalColumnWidths = 0; - for (var columnIdentifier in columns) - totalColumnWidths += columns[columnIdentifier].width; - - // Enforce the Value column (the 2nd column) to be a max of 33% - // tweaking the raw total width because may massively outshadow the others - var valueColumnWidth = columns[1].width; - if (valueColumnWidth / totalColumnWidths > 0.33) { - totalColumnWidths -= valueColumnWidth; - totalColumnWidths *= 1.33; - columns[1].width = totalColumnWidths * 0.33; - } - - // Calculate the percentage width for the columns. - const minimumPrecent = 6; - var recoupPercent = 0; - for (var columnIdentifier in columns) { - var width = columns[columnIdentifier].width; - width = Math.round((width / totalColumnWidths) * 100); - if (width < minimumPrecent) { - recoupPercent += (minimumPrecent - width); - width = minimumPrecent; - } - columns[columnIdentifier].width = width; - } - - // Enforce the minimum percentage width. (need to narrow total percentage due to earlier additions) - while (recoupPercent > 0) { - for (var columnIdentifier in columns) { - if (columns[columnIdentifier].width > minimumPrecent) { - --columns[columnIdentifier].width; - --recoupPercent; - if (!recoupPercent) - break; - } - } - } - - for (var columnIdentifier in columns) - columns[columnIdentifier].width += "%"; - - var dataGrid = new WebInspector.DataGrid(columns); - var length = nodes.length; - for (var i = 0; i < length; ++i) - dataGrid.appendChild(nodes[i]); - if (length > 0) - nodes[0].selected = true; - - return dataGrid; - }, - - fallbackUpdate: function() - { - this.element.removeChildren(); - - var self = this; - function callback(rawCookieString) { - var cookies = self.fallbackBuildCookiesFromString(rawCookieString); - var dataGrid = self.fallbackDataGridForCookies(cookies); - if (dataGrid) { - self._dataGrid = dataGrid; - self.element.appendChild(dataGrid.element); - self.deleteButton.visible = true; - } else { - var emptyMsgElement = document.createElement("div"); - emptyMsgElement.className = "storage-table-empty"; - emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies."); - self.element.appendChild(emptyMsgElement); - self._dataGrid = null; - self.deleteButton.visible = false; - } - } - - InspectorController.getCookies(callback); - }, - - fallbackBuildCookiesFromString: function(rawCookieString) - { - var rawCookies = rawCookieString.split(/;\s*/); - var cookies = []; - - if (!(/^\s*$/.test(rawCookieString))) { - for (var i = 0; i < rawCookies.length; ++i) { - var cookie = rawCookies[i]; - var delimIndex = cookie.indexOf("="); - var name = cookie.substring(0, delimIndex); - var value = cookie.substring(delimIndex + 1); - var size = name.length + value.length; - cookies.push({ name: name, value: value, size: size }); - } - } - - return cookies; - }, - - fallbackDataGridForCookies: function(cookies) - { - if (!cookies.length) - return null; - - var columns = {}; - columns[0] = {}; - columns[1] = {}; - columns[0].title = WebInspector.UIString("Name"); - columns[0].width = columns[0].title.length; - columns[1].title = WebInspector.UIString("Value"); - columns[1].width = columns[1].title.length; - - var nodes = []; - for (var i = 0; i < cookies.length; ++i) { - var cookie = cookies[i]; - var data = {}; - - var name = cookie.name; - data[0] = name; - if (name.length > columns[0].width) - columns[0].width = name.length; - - var value = cookie.value; - data[1] = value; - if (value.length > columns[1].width) - columns[1].width = value.length; - - var node = new WebInspector.DataGridNode(data, false); - node.selectable = true; - nodes.push(node); - } - - var totalColumnWidths = columns[0].width + columns[1].width; - var width = Math.round((columns[0].width * 100) / totalColumnWidths); - const minimumPrecent = 20; - if (width < minimumPrecent) - width = minimumPrecent; - if (width > 100 - minimumPrecent) - width = 100 - minimumPrecent; - columns[0].width = width; - columns[1].width = 100 - width; - columns[0].width += "%"; - columns[1].width += "%"; - - var dataGrid = new WebInspector.DataGrid(columns); - var length = nodes.length; - for (var i = 0; i < length; ++i) - dataGrid.appendChild(nodes[i]); - if (length > 0) - nodes[0].selected = true; - - return dataGrid; - }, - - _deleteButtonClicked: function(event) - { - if (!this._dataGrid || this._useFallback) - return; - - var cookie = this._dataGrid.selectedNode.cookie; - InspectorController.deleteCookie(cookie.name); - this.update(); - }, - - _refreshButtonClicked: function(event) - { - this.update(); - } -} - -WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype; diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js index 7942f0a..5aacd41 100644 --- a/WebCore/inspector/front-end/DOMAgent.js +++ b/WebCore/inspector/front-end/DOMAgent.js @@ -31,7 +31,7 @@ WebInspector.DOMNode = function(doc, payload) { this.ownerDocument = doc; - this.id = payload.id; + this._id = payload.id; this.nodeType = payload.nodeType; this.nodeName = payload.nodeName; this._nodeValue = payload.nodeValue; @@ -48,22 +48,14 @@ WebInspector.DOMNode = function(doc, payload) { this.nextSibling = null; this.prevSibling = null; this.firstChild = null; - this.lastChild = null; this.parentNode = null; - if (payload.children) - this._setChildrenPayload(payload.children); + if (payload.childNodes) + this._setChildrenPayload(payload.childNodes); this._computedStyle = null; this.style = null; this._matchedCSSRules = []; - - if (this.nodeType == Node.ELEMENT_NODE) { - if (this.nodeName == "HTML") - this.ownerDocument.documentElement = this; - if (this.nodeName == "BODY") - this.ownerDocument.body = this; - } } WebInspector.DOMNode.prototype = { @@ -169,11 +161,9 @@ WebInspector.DOMNode.prototype = { this._childNodeCount = this.children.length; if (this._childNodeCount == 0) { this.firstChild = null; - this.lastChild = null; return; } this.firstChild = this.children[0]; - this.lastChild = this.children[this._childNodeCount - 1]; for (var i = 0; i < this._childNodeCount; ++i) { var child = this.children[i]; child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null; @@ -218,9 +208,17 @@ WebInspector.DOMNode.prototype = { } } -WebInspector.DOMDocument = function(domAgent, defaultView, payload) +WebInspector.DOMDocument = function(domAgent, defaultView) { - WebInspector.DOMNode.call(this, this, payload); + WebInspector.DOMNode.call(this, null, + { + id: 0, + nodeType: Node.DOCUMENT_NODE, + nodeName: "", + nodeValue: "", + attributes: [], + childNodeCount: 0 + }); this._listeners = {}; this._domAgent = domAgent; this.defaultView = defaultView; @@ -228,7 +226,7 @@ WebInspector.DOMDocument = function(domAgent, defaultView, payload) WebInspector.DOMDocument.prototype = { - addEventListener: function(name, callback) + addEventListener: function(name, callback, useCapture) { var listeners = this._listeners[name]; if (!listeners) { @@ -238,7 +236,7 @@ WebInspector.DOMDocument.prototype = { listeners.push(callback); }, - removeEventListener: function(name, callback) + removeEventListener: function(name, callback, useCapture) { var listeners = this._listeners[name]; if (!listeners) @@ -253,12 +251,10 @@ WebInspector.DOMDocument.prototype = { { var listeners = this._listeners[name]; if (!listeners) - return; + return; - for (var i = 0; i < listeners.length; ++i) { - var listener = listeners[i]; - listener.call(this, event); - } + for (var i = 0; i < listeners.length; ++i) + listeners[i](event); } } @@ -306,8 +302,23 @@ WebInspector.DOMAgent = function() { this._idToDOMNode = null; this.document = null; - // TODO: update ElementsPanel to not track embedded iframes - it is already being handled + // Install onpopulate handler. This is a temporary measure. + // TODO: add this code into the original updateChildren once domAgent + // becomes primary source of DOM information. + // TODO2: update ElementsPanel to not track embedded iframes - it is already being handled // in the agent backend. + var domAgent = this; + var originalUpdateChildren = WebInspector.ElementsTreeElement.prototype.updateChildren; + WebInspector.ElementsTreeElement.prototype.updateChildren = function() + { + domAgent.getChildNodesAsync(this.representedObject, originalUpdateChildren.bind(this)); + }; + + // Mute console handle to avoid crash on selection change. + // TODO: Re-implement inspectorConsoleAPI to work in a serialized way and remove this workaround. + WebInspector.Console.prototype.addInspectedNode = function() + { + }; // Whitespace is ignored in InspectorDOMAgent already -> no need to filter. // TODO: Either remove all of its usages or push value into the agent backend. @@ -320,36 +331,38 @@ WebInspector.DOMAgent.prototype = { return this._window; }, - getChildNodesAsync: function(parent, callback) + getChildNodesAsync: function(parent, opt_callback) { var children = parent.children; - if (children) { - callback(children); - return; - } - function mycallback() { - callback(parent.children); + if (children && opt_callback) { + opt_callback(children); + return; } + var mycallback = function() { + if (opt_callback) { + opt_callback(parent.children); + } + }; var callId = WebInspector.Callback.wrap(mycallback); - InspectorController.getChildNodes(callId, parent.id); + InspectorController.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); + InspectorController.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); + InspectorController.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); + InspectorController.setTextNodeValue(WebInspector.Callback.wrap(mycallback), node._id, text); }, _didApplyDomChange: function(node, callback, success) @@ -370,22 +383,26 @@ WebInspector.DOMAgent.prototype = { node._setAttributesPayload(attrsArray); }, - nodeForId: function(nodeId) { + getNodeForId: function(nodeId) { return this._idToDOMNode[nodeId]; }, - _setDocument: function(payload) + _setDocumentElement: function(payload) { - this.document = new WebInspector.DOMDocument(this, this._window, payload); - this._idToDOMNode = {}; - this._idToDOMNode[payload.id] = this.document; - this._bindNodes(this.document.children); + this.document = new WebInspector.DOMDocument(this, this._window); + this._idToDOMNode = { 0 : this.document }; + this._setChildNodes(0, [payload]); + this.document.documentElement = this.document.firstChild; + this.document.documentElement.ownerDocument = this.document; WebInspector.panels.elements.reset(); }, _setChildNodes: function(parentId, payloads) { var parent = this._idToDOMNode[parentId]; + if (parent.children) { + return; + } parent._setChildrenPayload(payloads); this._bindNodes(parent.children); }, @@ -394,7 +411,7 @@ WebInspector.DOMAgent.prototype = { { for (var i = 0; i < children.length; ++i) { var child = children[i]; - this._idToDOMNode[child.id] = child; + this._idToDOMNode[child._id] = child; if (child.children) this._bindNodes(child.children); } @@ -416,7 +433,7 @@ WebInspector.DOMAgent.prototype = { var parent = this._idToDOMNode[parentId]; var prev = this._idToDOMNode[prevId]; var node = parent._insertChild(prev, payload); - this._idToDOMNode[node.id] = node; + this._idToDOMNode[node._id] = node; var event = { target : node, relatedNode : parent }; this.document._fireDomEvent("DOMNodeInserted", event); }, @@ -433,7 +450,7 @@ WebInspector.DOMAgent.prototype = { } WebInspector.CSSStyleDeclaration = function(payload) { - this.id = payload.id; + this._id = payload.id; this.width = payload.width; this.height = payload.height; this.__disabledProperties = payload.__disabledProperties; @@ -475,13 +492,12 @@ WebInspector.CSSStyleDeclaration.parseStyle = function(payload) WebInspector.CSSStyleDeclaration.parseRule = function(payload) { var rule = {}; - rule.id = payload.id; + rule._id = payload.id; rule.selectorText = payload.selectorText; rule.style = new WebInspector.CSSStyleDeclaration(payload.style); rule.style.parentRule = rule; rule.isUserAgent = payload.isUserAgent; rule.isUser = payload.isUser; - rule.isViaInspector = payload.isViaInspector; if (payload.parentStyleSheet) rule.parentStyleSheet = { href: payload.parentStyleSheet.href }; @@ -570,9 +586,9 @@ WebInspector.attributesUpdated = function() this.domAgent._attributesUpdated.apply(this.domAgent, arguments); } -WebInspector.setDocument = function() +WebInspector.setDocumentElement = function() { - this.domAgent._setDocument.apply(this.domAgent, arguments); + this.domAgent._setDocumentElement.apply(this.domAgent, arguments); } WebInspector.setChildNodes = function() @@ -588,11 +604,13 @@ WebInspector.hasChildrenUpdated = function() WebInspector.childNodeInserted = function() { this.domAgent._childNodeInserted.apply(this.domAgent, arguments); + this._childNodeInserted.bind(this); } WebInspector.childNodeRemoved = function() { this.domAgent._childNodeRemoved.apply(this.domAgent, arguments); + this._childNodeRemoved.bind(this); } WebInspector.didGetChildNodes = WebInspector.Callback.processCallback; @@ -601,122 +619,106 @@ WebInspector.didApplyDomChange = WebInspector.Callback.processCallback; WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback; WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback; +// Temporary methods for DOMAgent migration. +WebInspector.wrapNodeWithStyles = function(node, styles) +{ + var windowStub = new WebInspector.DOMWindow(null); + var docStub = new WebInspector.DOMDocument(null, windowStub); + var payload = {}; + payload.nodeType = node.nodeType; + payload.nodeName = node.nodeName; + payload.nodeValue = node.nodeValue; + payload.attributes = []; + payload.childNodeCount = 0; + + for (var i = 0; i < node.attributes.length; ++i) { + var attr = node.attributes[i]; + payload.attributes.push(attr.name); + payload.attributes.push(attr.value); + } + var nodeStub = new WebInspector.DOMNode(docStub, payload); + nodeStub._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules); + return nodeStub; +} + // Temporary methods that will be dispatched via InspectorController into the injected context. InspectorController.getStyles = function(nodeId, authorOnly, callback) { setTimeout(function() { callback(InjectedScript.getStyles(nodeId, authorOnly)); - }, 0); + }, 0) } InspectorController.getComputedStyle = function(nodeId, callback) { setTimeout(function() { callback(InjectedScript.getComputedStyle(nodeId)); - }, 0); + }, 0) } InspectorController.getInlineStyle = function(nodeId, callback) { setTimeout(function() { callback(InjectedScript.getInlineStyle(nodeId)); - }, 0); + }, 0) } InspectorController.applyStyleText = function(styleId, styleText, propertyName, callback) { setTimeout(function() { callback(InjectedScript.applyStyleText(styleId, styleText, propertyName)); - }, 0); + }, 0) } InspectorController.setStyleText = function(style, cssText, callback) { setTimeout(function() { callback(InjectedScript.setStyleText(style, cssText)); - }, 0); + }, 0) } InspectorController.toggleStyleEnabled = function(styleId, propertyName, disabled, callback) { setTimeout(function() { callback(InjectedScript.toggleStyleEnabled(styleId, propertyName, disabled)); - }, 0); + }, 0) } -InspectorController.applyStyleRuleText = function(ruleId, newContent, selectedNodeId, callback) +InspectorController.applyStyleRuleText = function(ruleId, newContent, selectedNode, callback) { setTimeout(function() { - callback(InjectedScript.applyStyleRuleText(ruleId, newContent, selectedNodeId)); - }, 0); + callback(InjectedScript.applyStyleRuleText(ruleId, newContent, selectedNode)); + }, 0) } -InspectorController.addStyleSelector = function(newContent, selectedNodeId, callback) +InspectorController.addStyleSelector = function(newContent, callback) { setTimeout(function() { - callback(InjectedScript.addStyleSelector(newContent, selectedNodeId)); - }, 0); + callback(InjectedScript.addStyleSelector(newContent)); + }, 0) } -InspectorController.setStyleProperty = function(styleId, name, value, callback) -{ +InspectorController.setStyleProperty = function(styleId, name, value, callback) { setTimeout(function() { callback(InjectedScript.setStyleProperty(styleId, name, value)); - }, 0); + }, 0) } -InspectorController.getPrototypes = function(nodeId, callback) -{ +InspectorController.getPrototypes = function(objectProxy, callback) { setTimeout(function() { - callback(InjectedScript.getPrototypes(nodeId)); - }, 0); + callback(InjectedScript.getPrototypes(objectProxy)); + }, 0) } -InspectorController.getProperties = function(objectProxy, ignoreHasOwnProperty, callback) -{ +InspectorController.getProperties = function(objectProxy, ignoreHasOwnProperty, callback) { setTimeout(function() { callback(InjectedScript.getProperties(objectProxy, ignoreHasOwnProperty)); - }, 0); + }, 0) } -InspectorController.setPropertyValue = function(objectProxy, propertyName, expression, callback) -{ +InspectorController.setPropertyValue = function(objectProxy, propertyName, expression, callback) { setTimeout(function() { callback(InjectedScript.setPropertyValue(objectProxy, propertyName, expression)); - }, 0); -} - -InspectorController.evaluate = function(expression, callback) -{ - setTimeout(function() { - callback(InjectedScript.evaluate(expression)); - }, 0); -} - -InspectorController.addInspectedNode = function(nodeId, callback) -{ - setTimeout(function() { - callback(InjectedScript.addInspectedNode(nodeId)); - }, 0); -} - -InspectorController.performSearch = function(whitespaceTrimmedQuery, callback) -{ - setTimeout(function() { - callback(InjectedScript.performSearch(whitespaceTrimmedQuery)); - }, 0); -} - -InspectorController.searchCanceled = function(callback) -{ - setTimeout(function() { - callback(InjectedScript.searchCanceled()); - }, 0); + }, 0) } -InspectorController.getCookies = function(callback) -{ - setTimeout(function() { - callback(InjectedScript.getCookies()); - }, 0); -} diff --git a/WebCore/inspector/front-end/DOMStorageItemsView.js b/WebCore/inspector/front-end/DOMStorageItemsView.js index 514883f..fad6e3c 100644 --- a/WebCore/inspector/front-end/DOMStorageItemsView.js +++ b/WebCore/inspector/front-end/DOMStorageItemsView.js @@ -32,18 +32,21 @@ WebInspector.DOMStorageItemsView = function(domStorage) this.element.addStyleClass("storage-view"); this.element.addStyleClass("table"); - this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); - this.deleteButton.visible = false; + this.deleteButton = document.createElement("button"); + this.deleteButton.title = WebInspector.UIString("Delete"); + this.deleteButton.className = "delete-storage-status-bar-item status-bar-item hidden"; this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); - this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this.refreshButton = document.createElement("button"); + this.refreshButton.title = WebInspector.UIString("Refresh"); + this.refreshButton.className = "refresh-storage-status-bar-item status-bar-item"; this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); } WebInspector.DOMStorageItemsView.prototype = { get statusBarItems() { - return [this.refreshButton.element, this.deleteButton.element]; + return [this.refreshButton, this.deleteButton]; }, show: function(parentElement) @@ -55,7 +58,7 @@ WebInspector.DOMStorageItemsView.prototype = { hide: function() { WebInspector.View.prototype.hide.call(this); - this.deleteButton.visible = false; + this.deleteButton.addStyleClass("hidden"); }, update: function() @@ -73,7 +76,7 @@ WebInspector.DOMStorageItemsView.prototype = { this._dataGrid = dataGrid; this.element.appendChild(dataGrid.element); this._dataGrid.updateWidths(); - this.deleteButton.visible = true; + this.deleteButton.removeStyleClass("hidden"); } } @@ -84,7 +87,7 @@ WebInspector.DOMStorageItemsView.prototype = { emptyMsgElement.textContent = WebInspector.UIString("This storage is empty."); this.element.appendChild(emptyMsgElement); this._dataGrid = null; - this.deleteButton.visible = false; + this.deleteButton.addStyleClass("hidden"); } }, diff --git a/WebCore/inspector/front-end/DataGrid.js b/WebCore/inspector/front-end/DataGrid.js index ce61548..42e001c 100644 --- a/WebCore/inspector/front-end/DataGrid.js +++ b/WebCore/inspector/front-end/DataGrid.js @@ -39,8 +39,6 @@ WebInspector.DataGrid = function(columns) this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true); this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true); - this.aligned = {}; - var scrollContainer = document.createElement("div"); scrollContainer.className = "data-container"; scrollContainer.appendChild(this._dataTable); @@ -80,11 +78,6 @@ WebInspector.DataGrid = function(columns) cell.addStyleClass("sortable"); } - if (column.aligned) { - cell.addStyleClass(column.aligned); - this.aligned[columnIdentifier] = column.aligned; - } - headerRow.appendChild(cell); ++columnCount; @@ -759,10 +752,6 @@ WebInspector.DataGridNode.prototype = { var cell = document.createElement("td"); cell.className = columnIdentifier + "-column"; - var alignment = this.dataGrid.aligned[columnIdentifier]; - if (alignment) - cell.addStyleClass(alignment); - var div = document.createElement("div"); div.textContent = this.data[columnIdentifier]; cell.appendChild(div); diff --git a/WebCore/inspector/front-end/DatabasesPanel.js b/WebCore/inspector/front-end/DatabasesPanel.js index acbbe28..a31e3ff 100644 --- a/WebCore/inspector/front-end/DatabasesPanel.js +++ b/WebCore/inspector/front-end/DatabasesPanel.js @@ -59,10 +59,6 @@ WebInspector.DatabasesPanel = function(database) this.sidebarTree.appendChild(this.sessionStorageListTreeElement); this.sessionStorageListTreeElement.expand(); - this.cookieListTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("COOKIES"), {}, true); - this.sidebarTree.appendChild(this.cookieListTreeElement); - this.cookieListTreeElement.expand(); - this.storageViews = document.createElement("div"); this.storageViews.id = "storage-views"; this.element.appendChild(this.storageViews); @@ -91,12 +87,6 @@ WebInspector.DatabasesPanel.prototype = { WebInspector.Panel.prototype.show.call(this); this._updateSidebarWidth(); this._registerStorageEventListener(); - this.populateInterface(); - }, - - populateInterface: function() - { - this.addCookies(); }, reset: function() @@ -126,15 +116,11 @@ WebInspector.DatabasesPanel.prototype = { this._domStorage = []; - delete this.cookieTreeElement; - delete this._cookieView; - this.databasesListTreeElement.removeChildren(); this.localStorageListTreeElement.removeChildren(); this.sessionStorageListTreeElement.removeChildren(); - this.cookieListTreeElement.removeChildren(); - this.storageViews.removeChildren(); - + this.storageViews.removeChildren(); + this.storageViewStatusBarItemsContainer.removeChildren(); }, @@ -163,14 +149,6 @@ WebInspector.DatabasesPanel.prototype = { this.sessionStorageListTreeElement.appendChild(domStorageTreeElement); }, - addCookies: function() - { - if (!this.cookieTreeElement) { - this.cookieTreeElement = new WebInspector.CookieSidebarTreeElement(); - this.cookieListTreeElement.appendChild(this.cookieTreeElement); - } - }, - selectDatabase: function(db) { var database; @@ -257,27 +235,6 @@ WebInspector.DatabasesPanel.prototype = { this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); }, - showCookies: function() - { - if (this.visibleView) - this.visibleView.hide(); - - var view = this._cookieView; - if (!view) { - view = new WebInspector.CookieItemsView(); - this._cookieView = view; - } - - view.show(this.storageViews); - - this.visibleView = view; - - this.storageViewStatusBarItemsContainer.removeChildren(); - var statusBarItems = view.statusBarItems; - for (var i = 0; i < statusBarItems.length; ++i) - this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); - }, - closeVisibleView: function() { if (this.visibleView) @@ -400,7 +357,7 @@ WebInspector.DatabasesPanel.prototype = { columns[0].title = WebInspector.UIString("Key"); columns[0].width = columns[0].title.length; columns[1].title = WebInspector.UIString("Value"); - columns[1].width = columns[1].title.length; + columns[1].width = columns[0].title.length; var nodes = []; @@ -423,7 +380,7 @@ WebInspector.DatabasesPanel.prototype = { } var totalColumnWidths = columns[0].width + columns[1].width; - var width = Math.round((columns[0].width * 100) / totalColumnWidths); + width = Math.round((columns[0].width * 100) / totalColumnWidths); const minimumPrecent = 10; if (width < minimumPrecent) width = minimumPrecent; @@ -443,7 +400,7 @@ WebInspector.DatabasesPanel.prototype = { nodes[0].selected = true; return dataGrid; }, - + resize: function() { var visibleView = this.visibleView; @@ -649,39 +606,3 @@ WebInspector.DOMStorageSidebarTreeElement.prototype = { } WebInspector.DOMStorageSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; - -WebInspector.CookieSidebarTreeElement = function() -{ - WebInspector.SidebarTreeElement.call(this, "cookie-sidebar-tree-item", null, "", null, false); - - this.refreshTitles(); -} - -WebInspector.CookieSidebarTreeElement.prototype = { - onselect: function() - { - WebInspector.panels.databases.showCookies(); - }, - - get mainTitle() - { - return WebInspector.UIString("Cookies"); - }, - - set mainTitle(x) - { - // Do nothing. - }, - - get subtitle() - { - return ""; - }, - - set subtitle(x) - { - // Do nothing. - } -} - -WebInspector.CookieSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; diff --git a/WebCore/inspector/front-end/Drawer.js b/WebCore/inspector/front-end/Drawer.js index 1b50f91..23dc483 100644 --- a/WebCore/inspector/front-end/Drawer.js +++ b/WebCore/inspector/front-end/Drawer.js @@ -64,12 +64,6 @@ WebInspector.Drawer.prototype = { } }, - showView: function(view) - { - if (!this.visible || this.visibleView !== view) - this.visibleView = view; - }, - show: function() { if (this._animating || this.visible) diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js index 1748159..ffa0000 100644 --- a/WebCore/inspector/front-end/ElementsPanel.js +++ b/WebCore/inspector/front-end/ElementsPanel.js @@ -61,8 +61,7 @@ WebInspector.ElementsPanel = function() InspectorController.toggleNodeSearch(); this.panel.nodeSearchButton.removeStyleClass("toggled-on"); } - if (this._focusedDOMNode) - InspectorController.addInspectedNode(this._focusedDOMNode.id, function() {}); + WebInspector.console.addInspectedNode(this._focusedDOMNode); }; this.contentElement.appendChild(this.treeOutline.element); @@ -98,7 +97,10 @@ WebInspector.ElementsPanel = function() this.sidebarResizeElement.className = "sidebar-resizer-vertical"; this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false); - this.nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item"); + this.nodeSearchButton = this.createStatusBarButton(); + this.nodeSearchButton.title = WebInspector.UIString("Select an element in the page to inspect it."); + this.nodeSearchButton.id = "node-search-status-bar-item"; + this.nodeSearchButton.className = "status-bar-item"; this.nodeSearchButton.addEventListener("click", this._nodeSearchButtonClicked.bind(this), false); this.searchingForNode = false; @@ -107,7 +109,13 @@ WebInspector.ElementsPanel = function() this.element.appendChild(this.sidebarElement); this.element.appendChild(this.sidebarResizeElement); - this._changedStyles = {}; + this._mutationMonitoredWindows = []; + this._nodeInsertedEventListener = InspectorController.wrapCallback(this._nodeInserted.bind(this)); + this._nodeRemovedEventListener = InspectorController.wrapCallback(this._nodeRemoved.bind(this)); + this._contentLoadedEventListener = InspectorController.wrapCallback(this._contentLoaded.bind(this)); + + this.stylesheet = null; + this.styles = {}; this.reset(); } @@ -122,7 +130,7 @@ WebInspector.ElementsPanel.prototype = { get statusBarItems() { - return [this.nodeSearchButton.element, this.crumbsElement]; + return [this.nodeSearchButton, this.crumbsElement]; }, updateStatusBarItems: function() @@ -148,7 +156,7 @@ WebInspector.ElementsPanel.prototype = { if (InspectorController.searchingForNode()) { InspectorController.toggleNodeSearch(); - this.nodeSearchButton.toggled = false; + this.nodeSearchButton.removeStyleClass("toggled-on"); } }, @@ -167,27 +175,40 @@ WebInspector.ElementsPanel.prototype = { if (InspectorController.searchingForNode()) { InspectorController.toggleNodeSearch(); - this.nodeSearchButton.toggled = false; + this.nodeSearchButton.removeStyleClass("toggled-on"); } this.recentlyModifiedNodes = []; + this.unregisterAllMutationEventListeners(); delete this.currentQuery; this.searchCanceled(); - var inspectedWindow = WebInspector.domAgent.inspectedWindow; - if (!inspectedWindow || !inspectedWindow.document || !inspectedWindow.document.firstChild) + var inspectedWindow = Preferences.useDOMAgent ? WebInspector.domAgent.inspectedWindow : InspectorController.inspectedWindow(); + if (!inspectedWindow || !inspectedWindow.document) return; + if (!inspectedWindow.document.firstChild) { + function contentLoaded() + { + inspectedWindow.document.removeEventListener("DOMContentLoaded", contentLoadedCallback, false); + + this.reset(); + } + + var contentLoadedCallback = InspectorController.wrapCallback(contentLoaded.bind(this)); + inspectedWindow.document.addEventListener("DOMContentLoaded", contentLoadedCallback, false); + return; + } + // 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()) return; - var inspectedRootDocument = inspectedWindow.document; - inspectedRootDocument.addEventListener("DOMNodeInserted", this._nodeInserted.bind(this)); - inspectedRootDocument.addEventListener("DOMNodeRemoved", this._nodeRemoved.bind(this)); + this.registerMutationEventListeners(inspectedWindow); + var inspectedRootDocument = inspectedWindow.document; this.rootDOMNode = inspectedRootDocument; var canidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; @@ -201,11 +222,19 @@ WebInspector.ElementsPanel.prototype = { } }, + includedInSearchResultsPropertyName: "__includedInInspectorSearchResults", + searchCanceled: function() { if (this._searchResults) { + const searchResultsProperty = this.includedInSearchResultsPropertyName; for (var i = 0; i < this._searchResults.length; ++i) { - var treeElement = this.treeOutline.findTreeElement(this._searchResults[i]); + var node = this._searchResults[i]; + + // Remove the searchResultsProperty since there might be an unfinished search. + delete node[searchResultsProperty]; + + var treeElement = this.treeOutline.findTreeElement(node); if (treeElement) treeElement.highlighted = false; } @@ -213,9 +242,13 @@ WebInspector.ElementsPanel.prototype = { WebInspector.updateSearchMatchesCount(0, this); + if (this._currentSearchChunkIntervalIdentifier) { + clearInterval(this._currentSearchChunkIntervalIdentifier); + delete this._currentSearchChunkIntervalIdentifier; + } + this._currentSearchResultIndex = 0; this._searchResults = []; - InspectorController.searchCanceled(function() {}); }, performSearch: function(query) @@ -227,56 +260,241 @@ WebInspector.ElementsPanel.prototype = { if (!whitespaceTrimmedQuery.length) return; - this._updatedMatchCountOnce = false; - this._matchesCountUpdateTimeout = null; + var tagNameQuery = whitespaceTrimmedQuery; + var attributeNameQuery = whitespaceTrimmedQuery; + var startTagFound = (tagNameQuery.indexOf("<") === 0); + var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1)); - InspectorController.performSearch(whitespaceTrimmedQuery, function() {}); - }, + if (startTagFound || endTagFound) { + var tagNameQueryLength = tagNameQuery.length; + tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength)); + } - _updateMatchesCount: function() - { - WebInspector.updateSearchMatchesCount(this._searchResults.length, this); - this._matchesCountUpdateTimeout = null; - this._updatedMatchCountOnce = true; - }, + // Check the tagNameQuery is it is a possibly valid tag name. + if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery)) + tagNameQuery = null; - _updateMatchesCountSoon: function() - { - if (!this._updatedMatchCountOnce) - return this._updateMatchesCount(); - if (this._matchesCountUpdateTimeout) - return; - // Update the matches count every half-second so it doesn't feel twitchy. - this._matchesCountUpdateTimeout = setTimeout(this._updateMatchesCount.bind(this), 500); - }, + // Check the attributeNameQuery is it is a possibly valid tag name. + if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery)) + attributeNameQuery = null; - addNodesToSearchResult: function(nodeIds) - { - if (!nodeIds) - return; + const escapedQuery = query.escapeCharacters("'"); + const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null); + const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); + const searchResultsProperty = this.includedInSearchResultsPropertyName; - var nodeIdsArray = nodeIds.split(","); - for (var i = 0; i < nodeIdsArray.length; ++i) { - var nodeId = nodeIdsArray[i]; - var node = WebInspector.domAgent.nodeForId(nodeId); - if (!node) - continue; + var updatedMatchCountOnce = false; + var matchesCountUpdateTimeout = null; - if (!this._searchResults.length) { - this._currentSearchResultIndex = 0; - this.focusedDOMNode = node; + function updateMatchesCount() + { + WebInspector.updateSearchMatchesCount(this._searchResults.length, this); + matchesCountUpdateTimeout = null; + updatedMatchCountOnce = true; + } + + function updateMatchesCountSoon() + { + if (!updatedMatchCountOnce) + return updateMatchesCount.call(this); + if (matchesCountUpdateTimeout) + return; + // Update the matches count every half-second so it doesn't feel twitchy. + matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500); + } + + function addNodesToResults(nodes, length, getItem) + { + if (!length) + return; + + for (var i = 0; i < length; ++i) { + var node = getItem.call(nodes, i); + // Skip this node if it already has the property. + if (searchResultsProperty in node) + continue; + + if (!this._searchResults.length) { + this._currentSearchResultIndex = 0; + this.focusedDOMNode = node; + } + + node[searchResultsProperty] = true; + this._searchResults.push(node); + + // Highlight the tree element to show it matched the search. + // FIXME: highlight the substrings in text nodes and attributes. + var treeElement = this.treeOutline.findTreeElement(node); + if (treeElement) + treeElement.highlighted = true; } - this._searchResults.push(node); + updateMatchesCountSoon.call(this); + } + + function matchExactItems(doc) + { + matchExactId.call(this, doc); + matchExactClassNames.call(this, doc); + matchExactTagNames.call(this, doc); + matchExactAttributeNames.call(this, doc); + } + + function matchExactId(doc) + { + const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this }); + } + + function matchExactClassNames(doc) + { + const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchExactTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchExactAttributeNames(doc) + { + if (!attributeNameQuery) + return; + const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]"); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchPartialTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } - // Highlight the tree element to show it matched the search. - // FIXME: highlight the substrings in text nodes and attributes. - var treeElement = this.treeOutline.findTreeElement(node); - if (treeElement) - treeElement.highlighted = true; + function matchStartOfTagNames(doc) + { + if (!tagNameQuery) + return; + const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); } - this._updateMatchesCountSoon(); + function matchPartialTagNamesAndAttributeValues(doc) + { + if (!tagNameQuery) { + matchPartialAttributeValues.call(this, doc); + return; + } + + const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchPartialAttributeValues(doc) + { + const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchStyleSelector(doc) + { + const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery); + addNodesToResults.call(this, result, result.length, result.item); + } + + function matchPlainText(doc) + { + const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function matchXPathQuery(doc) + { + const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); + } + + function finishedSearching() + { + // Remove the searchResultsProperty now that the search is finished. + for (var i = 0; i < this._searchResults.length; ++i) + delete this._searchResults[i][searchResultsProperty]; + } + + const mainFrameDocument = InspectorController.inspectedWindow().document; + const searchDocuments = [mainFrameDocument]; + + if (tagNameQuery && startTagFound && endTagFound) + const searchFunctions = [matchExactTagNames, matchPlainText]; + else if (tagNameQuery && startTagFound) + const searchFunctions = [matchStartOfTagNames, matchPlainText]; + else if (tagNameQuery && endTagFound) { + // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound. + // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains(). + const searchFunctions = [matchPartialTagNames, matchPlainText]; + } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") { + // These queries will match every node. Matching everything isn't useful and can be slow for large pages, + // so limit the search functions list to plain text and attribute matching. + const searchFunctions = [matchPartialAttributeValues, matchPlainText]; + } else + const searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery]; + + // Find all frames, iframes and object elements to search their documents. + const querySelectorAllFunction = InspectorController.inspectedWindow().Document.prototype.querySelectorAll; + const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object"); + + for (var i = 0; i < subdocumentResult.length; ++i) { + var element = subdocumentResult.item(i); + if (element.contentDocument) + searchDocuments.push(element.contentDocument); + } + + const panel = this; + var documentIndex = 0; + var searchFunctionIndex = 0; + var chunkIntervalIdentifier = null; + + // Split up the work into chunks so we don't block the UI thread while processing. + + function processChunk() + { + var searchDocument = searchDocuments[documentIndex]; + var searchFunction = searchFunctions[searchFunctionIndex]; + + if (++searchFunctionIndex > searchFunctions.length) { + searchFunction = searchFunctions[0]; + searchFunctionIndex = 0; + + if (++documentIndex > searchDocuments.length) { + if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) + delete panel._currentSearchChunkIntervalIdentifier; + clearInterval(chunkIntervalIdentifier); + finishedSearching.call(panel); + return; + } + + searchDocument = searchDocuments[documentIndex]; + } + + if (!searchDocument || !searchFunction) + return; + + try { + searchFunction.call(panel, searchDocument); + } catch(err) { + // ignore any exceptions. the query might be malformed, but we allow that. + } + } + + processChunk(); + + chunkIntervalIdentifier = setInterval(processChunk, 25); + this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; }, jumpToNextSearchResult: function() @@ -297,6 +515,12 @@ WebInspector.ElementsPanel.prototype = { this.focusedDOMNode = this._searchResults[this._currentSearchResultIndex]; }, + inspectedWindowCleared: function(window) + { + if (InspectorController.isWindowVisible()) + this.updateMutationEventListeners(window); + }, + renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector) { // TODO: Implement Shifting the oldSelector, and its contents to a newSelector @@ -308,16 +532,16 @@ WebInspector.ElementsPanel.prototype = { return; var selector = style.parentRule.selectorText; - if (!this._changedStyles[identifier]) - this._changedStyles[identifier] = {}; + if (!this.styles[identifier]) + this.styles[identifier] = {}; - if (!this._changedStyles[identifier][selector]) - this._changedStyles[identifier][selector] = {}; + if (!this.styles[identifier][selector]) + this.styles[identifier][selector] = {}; - if (!this._changedStyles[identifier][selector][property]) + if (!this.styles[identifier][selector][property]) WebInspector.styleChanges += 1; - this._changedStyles[identifier][selector][property] = style.getPropertyValue(property); + this.styles[identifier][selector][property] = style.getPropertyValue(property); }, removeStyleChange: function(identifier, style, property) @@ -326,11 +550,11 @@ WebInspector.ElementsPanel.prototype = { return; var selector = style.parentRule.selectorText; - if (!this._changedStyles[identifier] || !this._changedStyles[identifier][selector]) + if (!this.styles[identifier] || !this.styles[identifier][selector]) return; - if (this._changedStyles[identifier][selector][property]) { - delete this._changedStyles[identifier][selector][property]; + if (this.styles[identifier][selector][property]) { + delete this.styles[identifier][selector][property]; WebInspector.styleChanges -= 1; } }, @@ -342,20 +566,20 @@ WebInspector.ElementsPanel.prototype = { // Merge Down to Just Selectors var mergedSelectors = {}; - for (var identifier in this._changedStyles) { - for (var selector in this._changedStyles[identifier]) { + for (var identifier in this.styles) { + for (var selector in this.styles[identifier]) { if (!mergedSelectors[selector]) - mergedSelectors[selector] = this._changedStyles[identifier][selector]; + mergedSelectors[selector] = this.styles[identifier][selector]; else { // merge on selector var merge = {}; for (var property in mergedSelectors[selector]) merge[property] = mergedSelectors[selector][property]; - for (var property in this._changedStyles[identifier][selector]) { + for (var property in this.styles[identifier][selector]) { if (!merge[property]) - merge[property] = this._changedStyles[identifier][selector][property]; + merge[property] = this.styles[identifier][selector][property]; else { // merge on property within a selector, include comment to notify user var value1 = merge[property]; - var value2 = this._changedStyles[identifier][selector][property]; + var value2 = this.styles[identifier][selector][property]; if (value1 === value2) merge[property] = [value1]; @@ -412,6 +636,53 @@ WebInspector.ElementsPanel.prototype = { InspectorController.inspectedWindow().console.log(result); }, + _addMutationEventListeners: function(monitoredWindow) + { + monitoredWindow.document.addEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true); + monitoredWindow.document.addEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true); + if (monitoredWindow.frameElement) + monitoredWindow.addEventListener("DOMContentLoaded", this._contentLoadedEventListener, true); + }, + + _removeMutationEventListeners: function(monitoredWindow) + { + if (monitoredWindow.frameElement) + monitoredWindow.removeEventListener("DOMContentLoaded", this._contentLoadedEventListener, true); + if (!monitoredWindow.document) + return; + monitoredWindow.document.removeEventListener("DOMNodeInserted", this._nodeInsertedEventListener, true); + monitoredWindow.document.removeEventListener("DOMNodeRemoved", this._nodeRemovedEventListener, true); + }, + + updateMutationEventListeners: function(monitoredWindow) + { + this._addMutationEventListeners(monitoredWindow); + }, + + registerMutationEventListeners: function(monitoredWindow) + { + if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) !== -1) + return; + this._mutationMonitoredWindows.push(monitoredWindow); + if (InspectorController.isWindowVisible()) + this._addMutationEventListeners(monitoredWindow); + }, + + unregisterMutationEventListeners: function(monitoredWindow) + { + if (!monitoredWindow || this._mutationMonitoredWindows.indexOf(monitoredWindow) === -1) + return; + this._mutationMonitoredWindows.remove(monitoredWindow); + this._removeMutationEventListeners(monitoredWindow); + }, + + unregisterAllMutationEventListeners: function() + { + for (var i = 0; i < this._mutationMonitoredWindows.length; ++i) + this._removeMutationEventListeners(this._mutationMonitoredWindows[i]); + this._mutationMonitoredWindows = []; + }, + get rootDOMNode() { return this.treeOutline.rootDOMNode; @@ -432,6 +703,13 @@ WebInspector.ElementsPanel.prototype = { this.treeOutline.focusedDOMNode = x; }, + _contentLoaded: function(event) + { + this.recentlyModifiedNodes.push({node: event.target, parent: event.target.defaultView.frameElement, replaced: true}); + if (this.visible) + this._updateModifiedNodesSoon(); + }, + _nodeInserted: function(event) { this.recentlyModifiedNodes.push({node: event.target, parent: event.relatedNode, inserted: true}); @@ -469,14 +747,14 @@ WebInspector.ElementsPanel.prototype = { if (!parent) continue; - var parentNodeItem = this.treeOutline.findTreeElement(parent); + var parentNodeItem = this.treeOutline.findTreeElement(parent, null, null, objectsAreSame); if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) { parentNodeItem.updateChildren(replaced); parentNodeItem.alreadyUpdatedChildren = true; updatedParentTreeElements.push(parentNodeItem); } - if (!updateBreadcrumbs && (this.focusedDOMNode === parent || isAncestorIncludingParentFrames(this.focusedDOMNode, parent))) + if (!updateBreadcrumbs && (objectsAreSame(this.focusedDOMNode, parent) || isAncestorIncludingParentFrames(this.focusedDOMNode, parent))) updateBreadcrumbs = true; } @@ -536,7 +814,7 @@ WebInspector.ElementsPanel.prototype = { var foundRoot = false; var crumb = crumbs.firstChild; while (crumb) { - if (crumb.representedObject === this.rootDOMNode) + if (objectsAreSame(crumb.representedObject, this.rootDOMNode)) foundRoot = true; if (foundRoot) @@ -544,7 +822,7 @@ WebInspector.ElementsPanel.prototype = { else crumb.removeStyleClass("dimmed"); - if (crumb.representedObject === this.focusedDOMNode) { + if (objectsAreSame(crumb.representedObject, this.focusedDOMNode)) { crumb.addStyleClass("selected"); handled = true; } else { @@ -601,7 +879,7 @@ WebInspector.ElementsPanel.prototype = { if (current.nodeType === Node.DOCUMENT_NODE) continue; - if (current === this.rootDOMNode) + if (objectsAreSame(current, this.rootDOMNode)) foundRoot = true; var crumb = document.createElement("span"); @@ -684,7 +962,7 @@ WebInspector.ElementsPanel.prototype = { if (foundRoot) crumb.addStyleClass("dimmed"); - if (current === this.focusedDOMNode) + if (objectsAreSame(current, this.focusedDOMNode)) crumb.addStyleClass("selected"); if (!crumbs.childNodes.length) crumb.addStyleClass("end"); @@ -991,8 +1269,7 @@ WebInspector.ElementsPanel.prototype = { switch (this.focusedDOMNode.nodeType) { case Node.ELEMENT_NODE: - // TODO: Introduce InspectorController.copyEvent that pushes appropriate markup into the clipboard. - var data = null; + var data = this.focusedDOMNode.outerHTML; break; case Node.COMMENT_NODE: @@ -1039,7 +1316,10 @@ WebInspector.ElementsPanel.prototype = { { InspectorController.toggleNodeSearch(); - this.nodeSearchButton.toggled = InspectorController.searchingForNode(); + if (InspectorController.searchingForNode()) + this.nodeSearchButton.addStyleClass("toggled-on"); + else + this.nodeSearchButton.removeStyleClass("toggled-on"); } } diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js index 345a084..ef53209 100644 --- a/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -51,7 +51,7 @@ WebInspector.ElementsTreeOutline.prototype = { set rootDOMNode(x) { - if (this._rootDOMNode === x) + if (objectsAreSame(this._rootDOMNode, x)) return; this._rootDOMNode = x; @@ -66,7 +66,7 @@ WebInspector.ElementsTreeOutline.prototype = { set focusedDOMNode(x) { - if (this._focusedDOMNode === x) { + if (objectsAreSame(this._focusedDOMNode, x)) { this.revealAndSelectNode(x); return; } @@ -79,11 +79,11 @@ WebInspector.ElementsTreeOutline.prototype = { // and the select() call would change the focusedDOMNode and reenter this setter. So to // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same // node as the one passed in. - if (this._focusedDOMNode === x) { + if (objectsAreSame(this._focusedDOMNode, x)) { this.focusedNodeChanged(); if (x && !this.suppressSelectHighlight) { - InspectorController.highlightDOMNode(x.id); + InspectorController.highlightDOMNode(x); if ("_restorePreviousHighlightNodeTimeout" in this) clearTimeout(this._restorePreviousHighlightNodeTimeout); @@ -92,7 +92,7 @@ WebInspector.ElementsTreeOutline.prototype = { { var hoveredNode = WebInspector.hoveredDOMNode; if (hoveredNode) - InspectorController.highlightDOMNode(hoveredNode.id); + InspectorController.highlightDOMNode(hoveredNode); else InspectorController.hideDOMNodeHighlight(); } @@ -138,17 +138,19 @@ WebInspector.ElementsTreeOutline.prototype = { focusedNodeChanged: function(forceUpdate) {}, - findTreeElement: function(node, isAncestor, getParent) + findTreeElement: function(node, isAncestor, getParent, equal) { if (typeof isAncestor === "undefined") isAncestor = isAncestorIncludingParentFrames; if (typeof getParent === "undefined") getParent = parentNodeOrFrameElement; + if (typeof equal === "undefined") + equal = objectsAreSame; - var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent); + var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestor, getParent, equal); if (!treeElement && node.nodeType === Node.TEXT_NODE) { // The text node might have been inlined if it was short, so try to find the parent element. - treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent); + treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestor, getParent, equal); } return treeElement; @@ -246,7 +248,7 @@ WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype; WebInspector.ElementsTreeElement = function(node) { - var hasChildren = Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes(); + var hasChildren = node.contentDocument || (Preferences.ignoreWhitespace ? (firstChildSkippingWhitespace.call(node) ? true : false) : node.hasChildNodes()); var titleInfo = nodeTitleInfo.call(node, hasChildren, WebInspector.linkifyURL); if (titleInfo.hasChildren) @@ -385,13 +387,8 @@ WebInspector.ElementsTreeElement.prototype = { this.updateChildren(); }, - - updateChildren: function(fullRefresh) - { - WebInspector.domAgent.getChildNodesAsync(this.representedObject, this._updateChildren.bind(this, fullRefresh)); - }, - _updateChildren: function(fullRefresh) + updateChildren: function(fullRefresh) { if (fullRefresh) { var selectedTreeElement = this.treeOutline.selectedTreeElement; @@ -409,11 +406,11 @@ WebInspector.ElementsTreeElement.prototype = { var child = (Preferences.ignoreWhitespace ? firstChildSkippingWhitespace.call(node) : node.firstChild); while (child) { var currentTreeElement = treeElement.children[treeChildIndex]; - if (!currentTreeElement || currentTreeElement.representedObject !== child) { + if (!currentTreeElement || !objectsAreSame(currentTreeElement.representedObject, child)) { // Find any existing element that is later in the children list. var existingTreeElement = null; for (var i = (treeChildIndex + 1); i < treeElement.children.length; ++i) { - if (treeElement.children[i].representedObject === child) { + if (objectsAreSame(treeElement.children[i].representedObject, child)) { existingTreeElement = treeElement.children[i]; break; } @@ -448,7 +445,9 @@ WebInspector.ElementsTreeElement.prototype = { var currentNode = currentChild.representedObject; var currentParentNode = currentNode.parentNode; - if (currentParentNode === this.representedObject) + if (objectsAreSame(currentParentNode, this.representedObject)) + continue; + if (this.representedObject.contentDocument && objectsAreSame(currentParentNode, this.representedObject.contentDocument)) continue; var selectedTreeElement = this.treeOutline.selectedTreeElement; @@ -456,8 +455,13 @@ WebInspector.ElementsTreeElement.prototype = { this.select(); this.removeChildAtIndex(i); + + if (this.treeOutline.panel && currentNode.contentDocument) + this.treeOutline.panel.unregisterMutationEventListeners(currentNode.contentDocument.defaultView); } + if (this.representedObject.contentDocument) + updateChildrenOfNode(this.representedObject.contentDocument); updateChildrenOfNode(this.representedObject); var lastChild = this.children[this.children.length - 1]; @@ -473,6 +477,9 @@ WebInspector.ElementsTreeElement.prototype = { onexpand: function() { this.treeOutline.updateSelection(); + + if (this.treeOutline.panel && this.representedObject.contentDocument) + this.treeOutline.panel.registerMutationEventListeners(this.representedObject.contentDocument.defaultView); }, oncollapse: function() @@ -686,7 +693,7 @@ WebInspector.ElementsTreeElement.prototype = { } if (!parseElement.hasAttributes()) { - this.representedObject.removeAttribute(attributeName); + InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName); this._updateTitle(); moveToNextAttributeIfNeeded.call(this); return; @@ -697,12 +704,12 @@ WebInspector.ElementsTreeElement.prototype = { var attr = parseElement.attributes[i]; foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName; try { - this.representedObject.setAttribute(attr.name, attr.value); + InspectorController.inspectedWindow().Element.prototype.setAttribute.call(this.representedObject, attr.name, attr.value); } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can) } if (!foundOriginalAttribute) - this.representedObject.removeAttribute(attributeName); + InspectorController.inspectedWindow().Element.prototype.removeAttribute.call(this.representedObject, attributeName); this._updateTitle(); diff --git a/WebCore/inspector/front-end/Images/cookie.png b/WebCore/inspector/front-end/Images/cookie.png Binary files differdeleted file mode 100644 index 386d52b..0000000 --- a/WebCore/inspector/front-end/Images/cookie.png +++ /dev/null diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index 4144826..4611b48 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -27,20 +27,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var InjectedScript = {}; - -// Called from within InspectorController on the 'inspected page' side. -InjectedScript.reset = function() -{ - InjectedScript._styles = {}; - InjectedScript._styleRules = {}; - InjectedScript._lastStyleId = 0; - InjectedScript._lastStyleRuleId = 0; - InjectedScript._searchResults = []; - InjectedScript._includedInSearchResultsPropertyName = "__includedInInspectorSearchResults"; -} - -InjectedScript.reset(); +var InjectedScript = { + _styles: {}, + _styleRules: {}, + _lastStyleId: 0, + _lastStyleRuleId: 0 +}; InjectedScript.getStyles = function(nodeId, authorOnly) { @@ -182,14 +174,12 @@ InjectedScript.toggleStyleEnabled = function(styleId, propertyName, disabled) return InjectedScript._serializeStyle(style, true); } -InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId) +InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNode) { var rule = InjectedScript._styleRules[ruleId]; if (!rule) return false; - var selectedNode = InjectedScript._nodeForId(selectedNodeId); - try { var stylesheet = rule.parentStyleSheet; stylesheet.addRule(newContent); @@ -204,14 +194,20 @@ InjectedScript.applyStyleRuleText = function(ruleId, newContent, selectedNodeId) } } - return [InjectedScript._serializeRule(newRule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode)]; + var nodes = selectedNode.ownerDocument.querySelectorAll(newContent); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] === selectedNode) { + return [InjectedScript._serializeRule(newRule), true]; + } + } + return [InjectedScript._serializeRule(newRule), false]; } catch(e) { // Report invalid syntax. return false; } } -InjectedScript.addStyleSelector = function(newContent, selectedNodeId) +InjectedScript.addStyleSelector = function(newContent) { var stylesheet = InjectedScript.stylesheet; if (!stylesheet) { @@ -231,28 +227,10 @@ InjectedScript.addStyleSelector = function(newContent, selectedNodeId) return false; } - var selectedNode = InjectedScript._nodeForId(selectedNodeId); - var rule = stylesheet.cssRules[stylesheet.cssRules.length - 1]; - rule.__isViaInspector = true; - - return [ InjectedScript._serializeRule(rule), InjectedScript._doesSelectorAffectNode(newContent, selectedNode) ]; -} - -InjectedScript._doesSelectorAffectNode = function(selectorText, node) -{ - if (!node) - return false; - var nodes = node.ownerDocument.querySelectorAll(selectorText); - for (var i = 0; i < nodes.length; ++i) { - if (nodes[i] === node) { - return true; - } - } - return false; + return InjectedScript._serializeRule(stylesheet.cssRules[stylesheet.cssRules.length - 1]); } -InjectedScript.setStyleProperty = function(styleId, name, value) -{ +InjectedScript.setStyleProperty = function(styleId, name, value) { var style = InjectedScript._styles[styleId]; if (!style) return false; @@ -273,18 +251,17 @@ InjectedScript._serializeRule = function(rule) } ruleValue.isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode && !parentStyleSheet.href; ruleValue.isUser = parentStyleSheet && parentStyleSheet.ownerNode && parentStyleSheet.ownerNode.nodeName == "#document"; - ruleValue.isViaInspector = !!rule.__isViaInspector; // Bind editable scripts only. var doBind = !ruleValue.isUserAgent && !ruleValue.isUser; ruleValue.style = InjectedScript._serializeStyle(rule.style, doBind); if (doBind) { - if (!rule.id) { - rule.id = InjectedScript._lastStyleRuleId++; - InjectedScript._styleRules[rule.id] = rule; + if (!rule._id) { + rule._id = InjectedScript._lastStyleRuleId++; + InjectedScript._styleRules[rule._id] = rule; } - ruleValue.id = rule.id; + ruleValue.id = rule._id; } return ruleValue; } @@ -318,11 +295,11 @@ InjectedScript._serializeStyle = function(style, doBind) result.uniqueStyleProperties = InjectedScript._getUniqueStyleProperties(style); if (doBind) { - if (!style.id) { - style.id = InjectedScript._lastStyleId++; - InjectedScript._styles[style.id] = style; + if (!style._id) { + style._id = InjectedScript._lastStyleId++; + InjectedScript._styles[style._id] = style; } - result.id = style.id; + result.id = style._id; } return result; } @@ -428,7 +405,6 @@ InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty) return false; var properties = []; - // Go over properties, prepare results. for (var propertyName in object) { if (!ignoreHasOwnProperty && "hasOwnProperty" in object && !object.hasOwnProperty(propertyName)) @@ -439,31 +415,29 @@ InjectedScript.getProperties = function(objectProxy, ignoreHasOwnProperty) continue; var property = {}; property.name = propertyName; - property.parentObjectProxy = objectProxy; var isGetter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName); if (!property.isGetter) { var childObject = object[propertyName]; - var childObjectProxy = {}; - childObjectProxy.objectId = objectProxy.objectId; - childObjectProxy.path = objectProxy.path ? objectProxy.path.slice() : []; - childObjectProxy.path.push(propertyName); - - childObjectProxy.protoDepth = objectProxy.protoDepth || 0; - childObjectProxy.description = Object.describe(childObject, true); - property.value = childObjectProxy; - - var type = typeof childObject; - if (type === "object" || type === "function") { + property.type = typeof childObject; + property.textContent = Object.describe(childObject, true); + property.parentObjectProxy = objectProxy; + var parentPath = objectProxy.path.slice(); + property.childObjectProxy = { + objectId : objectProxy.objectId, + path : parentPath.splice(parentPath.length, 0, propertyName), + protoDepth : objectProxy.protoDepth + }; + if (childObject && (property.type === "object" || property.type === "function")) { for (var subPropertyName in childObject) { if (propertyName === "__treeElementIdentifier") continue; - childObjectProxy.hasChildren = true; + property.hasChildren = true; break; } } } else { // FIXME: this should show something like "getter" (bug 16734). - property.value = { description: "\u2014" }; // em dash + property.textContent = "\u2014"; // em dash property.isGetter = true; } properties.push(property); @@ -505,338 +479,6 @@ InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression } } -InjectedScript.evaluate = function(expression) -{ - InjectedScript._ensureCommandLineAPIInstalled(); - // 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._inspectorCommandLineAPI) { with (window) { " + expression + " } }"; - - var result = {}; - try { - var value = InjectedScript._window().eval(expression); - var wrapper = InspectorController.wrapObject(value); - if (typeof wrapper === "object" && wrapper.exception) - result.exception = wrapper.exception; - else - result.value = wrapper; - } catch (e) { - result.exception = e.toString(); - } - return result; -} - -InjectedScript.addInspectedNode = function(nodeId) -{ - var node = InjectedScript._nodeForId(nodeId); - if (!node) - return false; - - InjectedScript._ensureCommandLineAPIInstalled(); - var inspectedNodes = InjectedScript._window()._inspectorCommandLineAPI._inspectedNodes; - inspectedNodes.unshift(node); - if (inspectedNodes.length >= 5) - inspectedNodes.pop(); - return true; -} - -InjectedScript.performSearch = function(whitespaceTrimmedQuery, searchResultsProperty) -{ - var tagNameQuery = whitespaceTrimmedQuery; - var attributeNameQuery = whitespaceTrimmedQuery; - var startTagFound = (tagNameQuery.indexOf("<") === 0); - var endTagFound = (tagNameQuery.lastIndexOf(">") === (tagNameQuery.length - 1)); - - if (startTagFound || endTagFound) { - var tagNameQueryLength = tagNameQuery.length; - tagNameQuery = tagNameQuery.substring((startTagFound ? 1 : 0), (endTagFound ? (tagNameQueryLength - 1) : tagNameQueryLength)); - } - - // Check the tagNameQuery is it is a possibly valid tag name. - if (!/^[a-zA-Z0-9\-_:]+$/.test(tagNameQuery)) - tagNameQuery = null; - - // Check the attributeNameQuery is it is a possibly valid tag name. - if (!/^[a-zA-Z0-9\-_:]+$/.test(attributeNameQuery)) - attributeNameQuery = null; - - const escapedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); - const escapedTagNameQuery = (tagNameQuery ? tagNameQuery.escapeCharacters("'") : null); - const escapedWhitespaceTrimmedQuery = whitespaceTrimmedQuery.escapeCharacters("'"); - const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName; - - function addNodesToResults(nodes, length, getItem) - { - if (!length) - return; - - var nodeIds = []; - for (var i = 0; i < length; ++i) { - var node = getItem.call(nodes, i); - // Skip this node if it already has the property. - if (searchResultsProperty in node) - continue; - - if (!InjectedScript._searchResults.length) { - InjectedScript._currentSearchResultIndex = 0; - } - - node[searchResultsProperty] = true; - InjectedScript._searchResults.push(node); - var nodeId = InspectorController.pushNodePathToFrontend(node, false); - nodeIds.push(nodeId); - } - InspectorController.addNodesToSearchResult(nodeIds.join(",")); - } - - function matchExactItems(doc) - { - matchExactId.call(this, doc); - matchExactClassNames.call(this, doc); - matchExactTagNames.call(this, doc); - matchExactAttributeNames.call(this, doc); - } - - function matchExactId(doc) - { - const result = doc.__proto__.getElementById.call(doc, whitespaceTrimmedQuery); - addNodesToResults.call(this, result, (result ? 1 : 0), function() { return this }); - } - - function matchExactClassNames(doc) - { - const result = doc.__proto__.getElementsByClassName.call(doc, whitespaceTrimmedQuery); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchExactTagNames(doc) - { - if (!tagNameQuery) - return; - const result = doc.__proto__.getElementsByTagName.call(doc, tagNameQuery); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchExactAttributeNames(doc) - { - if (!attributeNameQuery) - return; - const result = doc.__proto__.querySelectorAll.call(doc, "[" + attributeNameQuery + "]"); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchPartialTagNames(doc) - { - if (!tagNameQuery) - return; - const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchStartOfTagNames(doc) - { - if (!tagNameQuery) - return; - const result = doc.__proto__.evaluate.call(doc, "//*[starts-with(name(), '" + escapedTagNameQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchPartialTagNamesAndAttributeValues(doc) - { - if (!tagNameQuery) { - matchPartialAttributeValues.call(this, doc); - return; - } - - const result = doc.__proto__.evaluate.call(doc, "//*[contains(name(), '" + escapedTagNameQuery + "') or contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchPartialAttributeValues(doc) - { - const result = doc.__proto__.evaluate.call(doc, "//*[contains(@*, '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchStyleSelector(doc) - { - const result = doc.__proto__.querySelectorAll.call(doc, whitespaceTrimmedQuery); - addNodesToResults.call(this, result, result.length, result.item); - } - - function matchPlainText(doc) - { - const result = doc.__proto__.evaluate.call(doc, "//text()[contains(., '" + escapedQuery + "')] | //comment()[contains(., '" + escapedQuery + "')]", doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function matchXPathQuery(doc) - { - const result = doc.__proto__.evaluate.call(doc, whitespaceTrimmedQuery, doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); - addNodesToResults.call(this, result, result.snapshotLength, result.snapshotItem); - } - - function finishedSearching() - { - // Remove the searchResultsProperty now that the search is finished. - for (var i = 0; i < InjectedScript._searchResults.length; ++i) - delete InjectedScript._searchResults[i][searchResultsProperty]; - } - - const mainFrameDocument = InjectedScript._window().document; - const searchDocuments = [mainFrameDocument]; - var searchFunctions; - if (tagNameQuery && startTagFound && endTagFound) - searchFunctions = [matchExactTagNames, matchPlainText]; - else if (tagNameQuery && startTagFound) - searchFunctions = [matchStartOfTagNames, matchPlainText]; - else if (tagNameQuery && endTagFound) { - // FIXME: we should have a matchEndOfTagNames search function if endTagFound is true but not startTagFound. - // This requires ends-with() support in XPath, WebKit only supports starts-with() and contains(). - searchFunctions = [matchPartialTagNames, matchPlainText]; - } else if (whitespaceTrimmedQuery === "//*" || whitespaceTrimmedQuery === "*") { - // These queries will match every node. Matching everything isn't useful and can be slow for large pages, - // so limit the search functions list to plain text and attribute matching. - searchFunctions = [matchPartialAttributeValues, matchPlainText]; - } else - searchFunctions = [matchExactItems, matchStyleSelector, matchPartialTagNamesAndAttributeValues, matchPlainText, matchXPathQuery]; - - // Find all frames, iframes and object elements to search their documents. - const querySelectorAllFunction = InjectedScript._window().Document.prototype.querySelectorAll; - const subdocumentResult = querySelectorAllFunction.call(mainFrameDocument, "iframe, frame, object"); - - for (var i = 0; i < subdocumentResult.length; ++i) { - var element = subdocumentResult.item(i); - if (element.contentDocument) - searchDocuments.push(element.contentDocument); - } - - const panel = InjectedScript; - var documentIndex = 0; - var searchFunctionIndex = 0; - var chunkIntervalIdentifier = null; - - // Split up the work into chunks so we don't block the UI thread while processing. - - function processChunk() - { - var searchDocument = searchDocuments[documentIndex]; - var searchFunction = searchFunctions[searchFunctionIndex]; - - if (++searchFunctionIndex > searchFunctions.length) { - searchFunction = searchFunctions[0]; - searchFunctionIndex = 0; - - if (++documentIndex > searchDocuments.length) { - if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) - delete panel._currentSearchChunkIntervalIdentifier; - clearInterval(chunkIntervalIdentifier); - finishedSearching.call(panel); - return; - } - - searchDocument = searchDocuments[documentIndex]; - } - - if (!searchDocument || !searchFunction) - return; - - try { - searchFunction.call(panel, searchDocument); - } catch(err) { - // ignore any exceptions. the query might be malformed, but we allow that. - } - } - - processChunk(); - - chunkIntervalIdentifier = setInterval(processChunk, 25); - InjectedScript._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; - return true; -} - -InjectedScript.searchCanceled = function() -{ - if (InjectedScript._searchResults) { - const searchResultsProperty = InjectedScript._includedInSearchResultsPropertyName; - for (var i = 0; i < this._searchResults.length; ++i) { - var node = this._searchResults[i]; - - // Remove the searchResultsProperty since there might be an unfinished search. - delete node[searchResultsProperty]; - } - } - - if (InjectedScript._currentSearchChunkIntervalIdentifier) { - clearInterval(InjectedScript._currentSearchChunkIntervalIdentifier); - delete InjectedScript._currentSearchChunkIntervalIdentifier; - } - InjectedScript._searchResults = []; - return true; -} - -InjectedScript.getCookies = function() -{ - return InjectedScript._window().document.cookie; -} - -InjectedScript._ensureCommandLineAPIInstalled = function(inspectedWindow) -{ - var inspectedWindow = InjectedScript._window(); - if (inspectedWindow._inspectorCommandLineAPI) - return; - - inspectedWindow.eval("window._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) }, \ - _inspectedNodes: [], \ - get $0() { return _inspectorCommandLineAPI._inspectedNodes[0] }, \ - get $1() { return _inspectorCommandLineAPI._inspectedNodes[1] }, \ - get $2() { return _inspectorCommandLineAPI._inspectedNodes[2] }, \ - get $3() { return _inspectorCommandLineAPI._inspectedNodes[3] }, \ - get $4() { return _inspectorCommandLineAPI._inspectedNodes[4] } \ - };"); - - inspectedWindow._inspectorCommandLineAPI.clear = InspectorController.wrapCallback(InspectorController.clearMessages.bind(InspectorController, true)); - inspectedWindow._inspectorCommandLineAPI.inspect = InspectorController.wrapCallback(inspectObject.bind(this)); - - function inspectObject(o) - { - if (arguments.length === 0) - return; - - inspectedWindow.console.log(o); - if (Object.type(o, inspectedWindow) === "node") { - InspectorController.pushNodePathToFrontend(o, true); - } else { - switch (Object.describe(o)) { - case "Database": - InspectorController.selectDatabase(o); - break; - case "Storage": - InspectorController.selectDOMStorage(o); - break; - } - } - } -} - InjectedScript._resolveObject = function(objectProxy) { var object = InjectedScript._objectForId(objectProxy.objectId); @@ -844,11 +486,11 @@ InjectedScript._resolveObject = function(objectProxy) var protoDepth = objectProxy.protoDepth; // Follow the property path. - for (var i = 0; object && path && i < path.length; ++i) + for (var i = 0; object && i < path.length; ++i) object = object[path[i]]; // Get to the necessary proto layer. - for (var i = 0; object && protoDepth && i < protoDepth; ++i) + for (var i = 0; object && i < protoDepth; ++i) object = object.__proto__; return object; @@ -863,34 +505,12 @@ InjectedScript._window = function() InjectedScript._nodeForId = function(nodeId) { - if (!nodeId) - return null; - return InspectorController.nodeForId(nodeId); + // TODO: replace with node lookup in the InspectorDOMAgent once DOMAgent nodes are used. + return nodeId; } InjectedScript._objectForId = function(objectId) { - if (typeof objectId === "number") - return InjectedScript._nodeForId(objectId); - else if (typeof objectId === "string") - return InspectorController.unwrapObject(objectId); - - // TODO: move scope chain objects to proxy-based schema. + // TODO: replace with node lookups for node ids and evaluation result lookups for the rest of ids. return objectId; } - -// Called from within InspectorController on the 'inspected page' side. -InjectedScript.createProxyObject = function(object, objectId) -{ - var result = {}; - result.objectId = objectId; - result.type = Object.type(object, InjectedScript._window()); - if (result.type === "node") - result.nodeId = InspectorController.pushNodePathToFrontend(object, false); - try { - result.description = Object.describe(object, true, InjectedScript._window()); - } catch (e) { - result.exception = e.toString(); - } - return result; -} diff --git a/WebCore/inspector/front-end/ObjectPropertiesSection.js b/WebCore/inspector/front-end/ObjectPropertiesSection.js index f0b877d..9b03940 100644 --- a/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -124,6 +124,13 @@ WebInspector.ObjectPropertyTreeElement = function(property) } WebInspector.ObjectPropertyTreeElement.prototype = { + safePropertyValue: function(object, propertyName) + { + if (object["__lookupGetter__"] && object.__lookupGetter__(propertyName)) + return; + return object[propertyName]; + }, + onpopulate: function() { if (this.children.length && !this.shouldRefreshChildren) @@ -140,7 +147,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { self.appendChild(new self.treeOutline.section.treeElementConstructor(properties[i])); } }; - InspectorController.getProperties(this.property.value, false, callback); + InspectorController.getProperties(this.property.childObjectProxy, false, callback); }, ondblclick: function(element, event) @@ -161,7 +168,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.valueElement = document.createElement("span"); this.valueElement.className = "value"; - this.valueElement.textContent = this.property.value.description; + this.valueElement.textContent = this.property.textContent; if (this.property.isGetter) this.valueElement.addStyleClass("dimmed"); @@ -170,7 +177,7 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.listItemElement.appendChild(nameElement); this.listItemElement.appendChild(document.createTextNode(": ")); this.listItemElement.appendChild(this.valueElement); - this.hasChildren = this.property.value.hasChildren; + this.hasChildren = this.property.hasChildren; }, updateSiblings: function() diff --git a/WebCore/inspector/front-end/ObjectProxy.js b/WebCore/inspector/front-end/ObjectProxy.js index dbb9e48..fa7816e 100644 --- a/WebCore/inspector/front-end/ObjectProxy.js +++ b/WebCore/inspector/front-end/ObjectProxy.js @@ -28,17 +28,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -WebInspector.ObjectProxy = function(objectId, path, protoDepth, description, hasChildren) +WebInspector.ObjectProxy = function(objectId, path, protoDepth) { this.objectId = objectId; this.path = path || []; this.protoDepth = protoDepth || 0; - this.description = description; - this.hasChildren = hasChildren; } WebInspector.ObjectPropertyProxy = function(name, object) { this.name = name; - this.value = new WebInspector.ObjectProxy(object, [], 0, Object.describe(object, true), true); + this.type = "object"; + this.hasChildren = true; + this.textContent = Object.describe(object, true); + this.childObjectProxy = new WebInspector.ObjectProxy(object); } diff --git a/WebCore/inspector/front-end/Panel.js b/WebCore/inspector/front-end/Panel.js index 5046f6b..3e2212c 100644 --- a/WebCore/inspector/front-end/Panel.js +++ b/WebCore/inspector/front-end/Panel.js @@ -66,6 +66,18 @@ WebInspector.Panel.prototype = { return this._toolbarItem; }, + createStatusBarButton: function() + { + var button = document.createElement("button"); + var glyph = document.createElement("div"); + glyph.className = "glyph"; + button.appendChild(glyph); + var glyphShadow = document.createElement("div"); + glyphShadow.className = "glyph shadow"; + button.appendChild(glyphShadow); + return button; + }, + show: function() { WebInspector.View.prototype.show.call(this); diff --git a/WebCore/inspector/front-end/ProfileView.js b/WebCore/inspector/front-end/ProfileView.js index 5c9fcda..2517bd2 100644 --- a/WebCore/inspector/front-end/ProfileView.js +++ b/WebCore/inspector/front-end/ProfileView.js @@ -56,19 +56,25 @@ WebInspector.ProfileView = function(profile) this.viewSelectElement.appendChild(heavyViewOption); this.viewSelectElement.appendChild(treeViewOption); - this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item"); + this.percentButton = document.createElement("button"); + this.percentButton.className = "percent-time-status-bar-item status-bar-item"; this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); - this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item"); + this.focusButton = document.createElement("button"); + this.focusButton.title = WebInspector.UIString("Focus selected function."); + this.focusButton.className = "focus-profile-node-status-bar-item status-bar-item"; this.focusButton.disabled = true; this.focusButton.addEventListener("click", this._focusClicked.bind(this), false); - this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item"); + this.excludeButton = document.createElement("button"); + this.excludeButton.title = WebInspector.UIString("Exclude selected function."); + this.excludeButton.className = "exclude-profile-node-status-bar-item status-bar-item"; this.excludeButton.disabled = true; this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false); - this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item"); - this.resetButton.visible = false; + this.resetButton = document.createElement("button"); + this.resetButton.title = WebInspector.UIString("Restore all functions."); + this.resetButton.className = "reset-profile-status-bar-item status-bar-item hidden"; this.resetButton.addEventListener("click", this._resetClicked.bind(this), false); this.profile = profile; @@ -84,7 +90,7 @@ WebInspector.ProfileView = function(profile) WebInspector.ProfileView.prototype = { get statusBarItems() { - return [this.viewSelectElement, this.percentButton.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element]; + return [this.viewSelectElement, this.percentButton, this.focusButton, this.excludeButton, this.resetButton]; }, get profile() @@ -433,10 +439,10 @@ WebInspector.ProfileView.prototype = { { if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) { this.percentButton.title = WebInspector.UIString("Show absolute total and self times."); - this.percentButton.toggled = true; + this.percentButton.addStyleClass("toggled-on"); } else { this.percentButton.title = WebInspector.UIString("Show total and self times as percentages."); - this.percentButton.toggled = false; + this.percentButton.removeStyleClass("toggled-on"); } }, @@ -445,7 +451,7 @@ WebInspector.ProfileView.prototype = { if (!this.dataGrid.selectedNode) return; - this.resetButton.visible = true; + this.resetButton.removeStyleClass("hidden"); this.profileDataGridTree.focus(this.dataGrid.selectedNode); this.refresh(); this.refreshVisibleData(); @@ -460,7 +466,7 @@ WebInspector.ProfileView.prototype = { selectedNode.deselect(); - this.resetButton.visible = true; + this.resetButton.removeStyleClass("hidden"); this.profileDataGridTree.exclude(selectedNode); this.refresh(); this.refreshVisibleData(); @@ -468,7 +474,7 @@ WebInspector.ProfileView.prototype = { _resetClicked: function(event) { - this.resetButton.visible = false; + this.resetButton.addStyleClass("hidden"); this.profileDataGridTree.restore(); this.refresh(); this.refreshVisibleData(); diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js index e7ee064..c8b948a 100644 --- a/WebCore/inspector/front-end/ProfilesPanel.js +++ b/WebCore/inspector/front-end/ProfilesPanel.js @@ -59,10 +59,14 @@ WebInspector.ProfilesPanel = function() this.profileViews.id = "profile-views"; this.element.appendChild(this.profileViews); - this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton = this.createStatusBarButton(); + this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false); - this.recordButton = new WebInspector.StatusBarButton(WebInspector.UIString("Start profiling."), "record-profile-status-bar-item"); + this.recordButton = this.createStatusBarButton(); + this.recordButton.title = WebInspector.UIString("Start profiling."); + this.recordButton.id = "record-profile-status-bar-item"; + this.recordButton.className = "status-bar-item"; this.recordButton.addEventListener("click", this._recordClicked.bind(this), false); this.recording = false; @@ -83,7 +87,7 @@ WebInspector.ProfilesPanel.prototype = { get statusBarItems() { - return [this.enableToggleButton.element, this.recordButton.element, this.profileViewStatusBarItemsContainer]; + return [this.enableToggleButton, this.recordButton, this.profileViewStatusBarItemsContainer]; }, show: function() @@ -313,10 +317,10 @@ WebInspector.ProfilesPanel.prototype = { this.recording = isProfiling; if (isProfiling) { - this.recordButton.toggled = true; + this.recordButton.addStyleClass("toggled-on"); this.recordButton.title = WebInspector.UIString("Stop profiling."); } else { - this.recordButton.toggled = false; + this.recordButton.removeStyleClass("toggled-on"); this.recordButton.title = WebInspector.UIString("Start profiling."); } }, @@ -332,14 +336,14 @@ WebInspector.ProfilesPanel.prototype = { { if (InspectorController.profilerEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable."); - this.enableToggleButton.toggled = true; - this.recordButton.visible = true; + this.enableToggleButton.addStyleClass("toggled-on"); + this.recordButton.removeStyleClass("hidden"); this.profileViewStatusBarItemsContainer.removeStyleClass("hidden"); this.panelEnablerView.visible = false; } else { this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable."); - this.enableToggleButton.toggled = false; - this.recordButton.visible = false; + this.enableToggleButton.removeStyleClass("toggled-on"); + this.recordButton.addStyleClass("hidden"); this.profileViewStatusBarItemsContainer.addStyleClass("hidden"); this.panelEnablerView.visible = true; } diff --git a/WebCore/inspector/front-end/PropertiesSidebarPane.js b/WebCore/inspector/front-end/PropertiesSidebarPane.js index 4e55761..2d32137 100644 --- a/WebCore/inspector/front-end/PropertiesSidebarPane.js +++ b/WebCore/inspector/front-end/PropertiesSidebarPane.js @@ -32,7 +32,7 @@ WebInspector.PropertiesSidebarPane = function() } WebInspector.PropertiesSidebarPane.prototype = { - update: function(node) + update: function(object) { var body = this.bodyElement; @@ -40,7 +40,7 @@ WebInspector.PropertiesSidebarPane.prototype = { this.sections = []; - if (!node) + if (!object) return; var self = this; @@ -51,13 +51,13 @@ WebInspector.PropertiesSidebarPane.prototype = { // Get array of prototype user-friendly names. for (var i = 0; i < prototypes.length; ++i) { - var prototype = new WebInspector.ObjectProxy(node.id, [], i); + var prototype = new WebInspector.ObjectProxy(object, [], i); var section = new WebInspector.ObjectPropertiesSection(prototype, prototypes[i], WebInspector.UIString("Prototype")); self.sections.push(section); body.appendChild(section.element); } }; - InspectorController.getPrototypes(node.id, callback); + InspectorController.getPrototypes(object, callback); } } diff --git a/WebCore/inspector/front-end/ResourcesPanel.js b/WebCore/inspector/front-end/ResourcesPanel.js index bb7faa6..fb43551 100644 --- a/WebCore/inspector/front-end/ResourcesPanel.js +++ b/WebCore/inspector/front-end/ResourcesPanel.js @@ -139,11 +139,14 @@ WebInspector.ResourcesPanel = function() this.element.appendChild(this.panelEnablerView.element); - this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton = this.createStatusBarButton(); + this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; this.enableToggleButton.addEventListener("click", this._toggleResourceTracking.bind(this), false); - this.largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "resources-larger-resources-status-bar-item"); - this.largerResourcesButton.toggled = true; + this.largerResourcesButton = this.createStatusBarButton(); + this.largerResourcesButton.id = "resources-larger-resources-status-bar-item"; + this.largerResourcesButton.className = "status-bar-item toggled-on"; + this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); this.largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false); this.sortingSelectElement = document.createElement("select"); @@ -208,7 +211,7 @@ WebInspector.ResourcesPanel.prototype = { get statusBarItems() { - return [this.enableToggleButton.element, this.largerResourcesButton.element, this.sortingSelectElement]; + return [this.enableToggleButton, this.largerResourcesButton, this.sortingSelectElement]; }, show: function() @@ -464,14 +467,14 @@ WebInspector.ResourcesPanel.prototype = { if (InspectorController.resourceTrackingEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Resource tracking enabled. Click to disable."); - this.enableToggleButton.toggled = true; - this.largerResourcesButton.visible = true; + this.enableToggleButton.addStyleClass("toggled-on"); + this.largerResourcesButton.removeStyleClass("hidden"); this.sortingSelectElement.removeStyleClass("hidden"); this.panelEnablerView.visible = false; } else { this.enableToggleButton.title = WebInspector.UIString("Resource tracking disabled. Click to enable."); - this.enableToggleButton.toggled = false; - this.largerResourcesButton.visible = false; + this.enableToggleButton.removeStyleClass("toggled-on"); + this.largerResourcesButton.addStyleClass("hidden"); this.sortingSelectElement.addStyleClass("hidden"); this.panelEnablerView.visible = true; } @@ -1073,12 +1076,12 @@ WebInspector.ResourcesPanel.prototype = { if (this.resourcesTreeElement.smallChildren) { this.resourcesGraphsElement.addStyleClass("small"); this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows."); - this.largerResourcesButton.toggled = false; + this.largerResourcesButton.removeStyleClass("toggled-on"); this._adjustScrollPosition(); } else { this.resourcesGraphsElement.removeStyleClass("small"); this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); - this.largerResourcesButton.toggled = true; + this.largerResourcesButton.addStyleClass("toggled-on"); } }, @@ -1543,11 +1546,6 @@ WebInspector.ResourceSidebarTreeElement.prototype = { // Do nothing. }, - get selectable() - { - return WebInspector.panels.resources._filterCategory == "all" || WebInspector.panels.resources._filterCategory == this.resource.category.name; - }, - createIconElement: function() { var previousIconElement = this.iconElement; diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js index a97d5cf..0058374 100644 --- a/WebCore/inspector/front-end/ScriptsPanel.js +++ b/WebCore/inspector/front-end/ScriptsPanel.js @@ -151,10 +151,13 @@ WebInspector.ScriptsPanel = function() this.element.appendChild(this.sidebarElement); this.element.appendChild(this.sidebarResizeElement); - this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton = this.createStatusBarButton(); + this.enableToggleButton.className = "enable-toggle-status-bar-item status-bar-item"; this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false); - this.pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item"); + this.pauseOnExceptionButton = this.createStatusBarButton(); + this.pauseOnExceptionButton.id = "scripts-pause-on-exceptions-status-bar-item"; + this.pauseOnExceptionButton.className = "status-bar-item"; this.pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false); this._breakpointsURLMap = {}; @@ -205,7 +208,7 @@ WebInspector.ScriptsPanel.prototype = { get statusBarItems() { - return [this.enableToggleButton.element, this.pauseOnExceptionButton.element]; + return [this.enableToggleButton, this.pauseOnExceptionButton]; }, get paused() @@ -374,8 +377,13 @@ WebInspector.ScriptsPanel.prototype = { var panel = this; function delayedEvaluation() { + if (!code) { + // Evaluate into properties in scope of the selected call frame. + callback(panel._variablesInScope(callFrame)); + return; + } try { - callback(InspectorController.wrapObject(callFrame.evaluate(code))); + callback(callFrame.evaluate(code)); } catch (e) { callback(e, true); } @@ -383,14 +391,10 @@ WebInspector.ScriptsPanel.prototype = { setTimeout(delayedEvaluation, 0); }, - variablesInSelectedCallFrame: function() + _variablesInScope: function(callFrame) { - var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame; - if (!this._paused || !selectedCallFrame) - return {}; - var result = {}; - var scopeChain = selectedCallFrame.scopeChain; + var scopeChain = callFrame.scopeChain; for (var i = 0; i < scopeChain.length; ++i) { var scopeObject = scopeChain[i]; for (var property in scopeObject) @@ -760,10 +764,10 @@ WebInspector.ScriptsPanel.prototype = { { if (InspectorController.pauseOnExceptions()) { this.pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions."); - this.pauseOnExceptionButton.toggled = true; + this.pauseOnExceptionButton.addStyleClass("toggled-on"); } else { this.pauseOnExceptionButton.title = WebInspector.UIString("Pause on exceptions."); - this.pauseOnExceptionButton.toggled = false; + this.pauseOnExceptionButton.removeStyleClass("toggled-on"); } }, @@ -771,13 +775,13 @@ WebInspector.ScriptsPanel.prototype = { { if (InspectorController.debuggerEnabled()) { this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable."); - this.enableToggleButton.toggled = true; - this.pauseOnExceptionButton.visible = true; + this.enableToggleButton.addStyleClass("toggled-on"); + this.pauseOnExceptionButton.removeStyleClass("hidden"); this.panelEnablerView.visible = false; } else { this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable."); - this.enableToggleButton.toggled = false; - this.pauseOnExceptionButton.visible = false; + this.enableToggleButton.removeStyleClass("toggled-on"); + this.pauseOnExceptionButton.addStyleClass("hidden"); this.panelEnablerView.visible = true; } diff --git a/WebCore/inspector/front-end/SourceFrame.js b/WebCore/inspector/front-end/SourceFrame.js index 9c0f7e0..930eb16 100644 --- a/WebCore/inspector/front-end/SourceFrame.js +++ b/WebCore/inspector/front-end/SourceFrame.js @@ -289,10 +289,8 @@ WebInspector.SourceFrame.prototype = { return; var sourceRow = event.target.enclosingNodeOrSelfWithNodeName("tr"); - if (sourceRow._breakpointObject && sourceRow._breakpointObject.enabled) - sourceRow._breakpointObject.enabled = false; - else if (sourceRow._breakpointObject) - WebInspector.panels.scripts.removeBreakpoint(sourceRow._breakpointObject); + if (sourceRow._breakpointObject) + sourceRow._breakpointObject.enabled = !sourceRow._breakpointObject.enabled; else if (this.addBreakpointDelegate) this.addBreakpointDelegate(this.lineNumberForSourceRow(sourceRow)); }, diff --git a/WebCore/inspector/front-end/StatusBarButton.js b/WebCore/inspector/front-end/StatusBarButton.js deleted file mode 100644 index 5c69ed5..0000000 --- a/WebCore/inspector/front-end/StatusBarButton.js +++ /dev/null @@ -1,118 +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. - */ - -WebInspector.StatusBarButton = function(title, className) -{ - this.element = document.createElement("button"); - this.element.className = className + " status-bar-item"; - this.element.addEventListener("click", this._clicked.bind(this), false); - - this.glyph = document.createElement("div"); - this.glyph.className = "glyph"; - this.element.appendChild(this.glyph); - - this.glyphShadow = document.createElement("div"); - this.glyphShadow.className = "glyph shadow"; - this.element.appendChild(this.glyphShadow); - - this.title = title; - this.disabled = false; - this._toggled = false; - this._visible = true; -} - -WebInspector.StatusBarButton.prototype = { - _clicked: function() - { - this.dispatchEventToListeners("click"); - }, - - get disabled() - { - return this._disabled; - }, - - set disabled(x) - { - if (this._disabled === x) - return; - this._disabled = x; - this.element.disabled = x; - }, - - get title() - { - return this._title; - }, - - set title(x) - { - if (this._title === x) - return; - this._title = x; - this.element.title = x; - }, - - get toggled() - { - return this._toggled; - }, - - set toggled(x) - { - if (this._toggled === x) - return; - - if (x) - this.element.addStyleClass("toggled-on"); - else - this.element.removeStyleClass("toggled-on"); - this._toggled = x; - }, - - get visible() - { - return this._visible; - }, - - set visible(x) - { - if (this._visible === x) - return; - - if (x) - this.element.removeStyleClass("hidden"); - else - this.element.addStyleClass("hidden"); - this._visible = x; - } -} - -WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js index db585e0..8a3a67f 100644 --- a/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/WebCore/inspector/front-end/StylesSidebarPane.js @@ -67,10 +67,10 @@ WebInspector.StylesSidebarPane.prototype = { var callback = function(styles) { if (!styles) return; - node._setStyles(styles.computedStyle, styles.inlineStyle, styles.styleAttributes, styles.matchedCSSRules); - self._update(refresh, body, node, editedSection, forceUpdate); + var nodeWrapper = WebInspector.wrapNodeWithStyles(node, styles); + self._update(refresh, body, nodeWrapper, editedSection, forceUpdate); }; - InspectorController.getStyles(node.id, !Preferences.showUserAgentStyles, callback); + InspectorController.getStyles(node, !Preferences.showUserAgentStyles, callback); }, _update: function(refresh, body, node, editedSection, forceUpdate) @@ -322,9 +322,8 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl this.editable = (editable && !computedStyle); // Prevent editing the user agent and user rules. - var isUserAgent = this.rule && this.rule.isUserAgent; - var isUser = this.rule && this.rule.isUser; - var isViaInspector = this.rule && this.rule.isViaInspector; + var isUserAgent = this.styleRule.isUserAgent; + var isUser = this.styleRule.isUser; if (isUserAgent || isUser) this.editable = false; @@ -367,7 +366,7 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl subtitle = WebInspector.UIString("user agent stylesheet"); else if (isUser) subtitle = WebInspector.UIString("user stylesheet"); - else if (isViaInspector) + else if (this.styleRule.parentStyleSheet === WebInspector.panels.elements.stylesheet) subtitle = WebInspector.UIString("via inspector"); else subtitle = WebInspector.UIString("inline stylesheet"); @@ -612,12 +611,24 @@ WebInspector.StylePropertiesSection.prototype = { moveToNextIfNeeded.call(self); }; - InspectorController.applyStyleRuleText(this.rule.id, newContent, this.pane.node.id, callback); + InspectorController.applyStyleRuleText(this.rule._id, newContent, this.pane.node, callback); }, editingSelectorCancelled: function(element, context) { element.textContent = context; + }, + + _doesSelectorAffectSelectedNode: function(selector) + { + var selectedNode = this.pane.node; + var nodes = selectedNode.ownerDocument.querySelectorAll(selector); + for (var i = 0; i < nodes.length; ++i) { + if (nodes[i] === selectedNode) + return true; + } + + return false; } } @@ -662,17 +673,15 @@ WebInspector.BlankStylePropertiesSection.prototype = { editingCommitted: function(element, newContent, oldContent, context) { var self = this; - var callback = function(result) { - if (!result) { + var callback = function(styleRule) { + if (!styleRule) { // Invalid Syntax for a Selector self.editingCancelled(); return; } - var styleRule = result[0]; - var doesSelectorAffectSelectedNode = result[1]; self.makeNormal(WebInspector.CSSStyleDeclaration.parseRule(styleRule)); - if (!doesSelectorAffectSelectedNode) { + if (!self._doesSelectorAffectSelectedNode(newContent)) { self.noAffect = true; self.element.addStyleClass("no-affect"); } @@ -683,7 +692,7 @@ WebInspector.BlankStylePropertiesSection.prototype = { self.pane.addBlankSection(); self.addNewBlankProperty().startEditing(); }; - InspectorController.addStyleSelector(newContent, this.pane.node.id, callback); + InspectorController.addStyleSelector(newContent, callback); }, makeNormal: function(styleRule) @@ -887,70 +896,63 @@ WebInspector.StylePropertyTreeElement.prototype = { // Simple: rgb -> hsl -> nickname? -> shorthex? -> hex -> ... // Advanced: rgba -> hsla -> nickname? -> ... if (colors && colors.length === 1) { - try { - var color = new WebInspector.Color(htmlValue); - } catch(e) { - var color = null; - } - - if (color) { - swatch.addEventListener("click", changeColorDisplay, false); - swatch.addEventListener("dblclick", function(event) { - event.stopPropagation(); - }, false); + var color = new WebInspector.Color(htmlValue); + swatch.addEventListener("click", changeColorDisplay, false); + swatch.addEventListener("dblclick", function(event) { + event.stopPropagation(); + }, false); + + var mode = color.mode; + var valueElement = this.valueElement; + function changeColorDisplay(event) { + + function changeTo(newMode, content) { + mode = newMode; + valueElement.textContent = content; + } - var mode = color.mode; - var valueElement = this.valueElement; - function changeColorDisplay(event) { + switch (mode) { + case "rgb": + changeTo("hsl", color.toHsl()); + break; - function changeTo(newMode, content) { - mode = newMode; - valueElement.textContent = content; - } + case "shorthex": + changeTo("hex", color.toHex()); + break; - switch (mode) { - case "rgb": - changeTo("hsl", color.toHsl()); - break; + case "hex": + changeTo("rgb", color.toRgb()); + break; - case "shorthex": - changeTo("hex", color.toHex()); - break; - - case "hex": - changeTo("rgb", color.toRgb()); - break; - - case "nickname": - if (color.simple) { - if (color.hasShortHex()) - changeTo("shorthex", color.toShortHex()); - else - changeTo("hex", color.toHex()); - } else - changeTo("rgba", color.toRgba()); - break; - - case "hsl": - if (color.nickname) - changeTo("nickname", color.toNickname()); - else if (color.hasShortHex()) + case "nickname": + if (color.simple) { + if (color.hasShortHex()) changeTo("shorthex", color.toShortHex()); else changeTo("hex", color.toHex()); - break; - - case "rgba": - changeTo("hsla", color.toHsla()); - break; - - case "hsla": - if (color.nickname) - changeTo("nickname", color.toNickname()); - else - changeTo("rgba", color.toRgba()); - break; - } + } else + changeTo("rgba", color.toRgba()); + break; + + case "hsl": + if (color.nickname) + changeTo("nickname", color.toNickname()); + else if (color.hasShortHex()) + changeTo("shorthex", color.toShortHex()); + else + changeTo("hex", color.toHex()); + break; + + case "rgba": + changeTo("hsla", color.toHsla()); + break; + + case "hsla": + if (color.nickname) + changeTo("nickname", color.toNickname()); + else + changeTo("rgba", color.toRgba()); + break; } } } @@ -990,7 +992,7 @@ WebInspector.StylePropertyTreeElement.prototype = { self.updateAll(true); }; - InspectorController.toggleStyleEnabled(this.style.id, this.name, disabled, callback); + InspectorController.toggleStyleEnabled(this.style._id, this.name, disabled, callback); }, updateState: function() @@ -1153,7 +1155,7 @@ WebInspector.StylePropertyTreeElement.prototype = { } else { // Restore the original CSS text before applying user changes. This is needed to prevent // new properties from sticking around if the user adds one, then removes it. - InspectorController.setStyleText(this.style.id, this.originalCSSText); + InspectorController.setStyleText(this.style, this.originalCSSText); } this.applyStyleText(this.listItemElement.textContent); @@ -1173,7 +1175,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (this._newProperty) this.treeOutline.removeChild(this); else if (this.originalCSSText) { - InspectorController.setStyleText(this.style.id, this.originalCSSText); + InspectorController.setStyleText(this.style, this.originalCSSText); if (this.treeOutline.section && this.treeOutline.section.pane) this.treeOutline.section.pane.dispatchEventToListeners("style edited"); @@ -1292,7 +1294,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (!self.rule) WebInspector.panels.elements.treeOutline.update(); }; - InspectorController.applyStyleText(this.style.id, styleText.trimWhitespace(), this.name, callback); + InspectorController.applyStyleText(this.style._id, styleText.trimWhitespace(), this.name, callback); } } diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc index c82de61..c39c95b 100644 --- a/WebCore/inspector/front-end/WebKit.qrc +++ b/WebCore/inspector/front-end/WebKit.qrc @@ -9,7 +9,6 @@ <file>ChangesView.js</file> <file>Color.js</file> <file>ConsoleView.js</file> - <file>CookieItemsView.js</file> <file>Database.js</file> <file>DatabaseQueryView.js</file> <file>DatabasesPanel.js</file> @@ -51,7 +50,6 @@ <file>SidebarTreeElement.js</file> <file>SourceFrame.js</file> <file>SourceView.js</file> - <file>StatusBarButton.js</file> <file>StylesSidebarPane.js</file> <file>TextPrompt.js</file> <file>TopDownProfileDataGridTree.js</file> @@ -64,7 +62,6 @@ <file>Images/clearConsoleButtonGlyph.png</file> <file>Images/closeButtons.png</file> <file>Images/consoleButtonGlyph.png</file> - <file>Images/cookie.png</file> <file>Images/database.png</file> <file>Images/databasesIcon.png</file> <file>Images/databaseTable.png</file> diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css index 3292d8d..51d626a 100644 --- a/WebCore/inspector/front-end/inspector.css +++ b/WebCore/inspector/front-end/inspector.css @@ -1626,10 +1626,6 @@ body.inactive .sidebar { content: url(Images/domStorage.png); } -.cookie-sidebar-tree-item .icon { - content: url(Images/cookie.png); -} - #storage-views { position: absolute; top: 0; @@ -1789,14 +1785,6 @@ body.inactive .sidebar { overflow: hidden; } -.data-grid .centered div { - text-align: center; -} - -.data-grid .right div { - text-align: right; -} - .data-grid th.sortable div { position: relative; } @@ -2103,7 +2091,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { -webkit-mask-image: url(Images/enableSolidButtonGlyph.png); } -.scripts-pause-on-exceptions-status-bar-item .glyph { +#scripts-pause-on-exceptions-status-bar-item .glyph { -webkit-mask-image: url(Images/pauseOnExceptionButtonGlyph.png); } @@ -2221,7 +2209,7 @@ button.enable-toggle-status-bar-item.toggled-on .glyph { overflow: auto; } -.resources-larger-resources-status-bar-item .glyph { +#resources-larger-resources-status-bar-item .glyph { -webkit-mask-image: url(Images/largerResourcesButtonGlyph.png); } @@ -3105,16 +3093,16 @@ body.inactive .sidebar-tree-item.selected .bubble.search-matches { button.enable-toggle-status-bar-item .glyph { } -.record-profile-status-bar-item .glyph { +#record-profile-status-bar-item .glyph { -webkit-mask-image: url(Images/recordButtonGlyph.png); } -.record-profile-status-bar-item.toggled-on .glyph { +#record-profile-status-bar-item.toggled-on .glyph { -webkit-mask-image: url(Images/recordToggledButtonGlyph.png); - background-color: rgb(216, 0, 0) !important; + background-color: rgb(216, 0, 0); } -.node-search-status-bar-item .glyph { +#node-search-status-bar-item .glyph { -webkit-mask-image: url(Images/nodeSearchButtonGlyph.png); } @@ -3148,8 +3136,12 @@ button.enable-toggle-status-bar-item .glyph { margin-left: -1px; } -.refresh-storage-status-bar-item .glyph { - -webkit-mask-image: url(Images/reloadButtonGlyph.png); +.refresh-storage-status-bar-item { + background-image: url(Images/reloadButtons.png) !important; +} + +.refresh-storage-status-bar-item:active { + background-position: 32px 0; } #storage-view-status-bar-items { diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html index 4857c7a..a3dc407 100644 --- a/WebCore/inspector/front-end/inspector.html +++ b/WebCore/inspector/front-end/inspector.html @@ -49,7 +49,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <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> <script type="text/javascript" src="SidebarPane.js"></script> @@ -67,7 +66,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="StylesSidebarPane.js"></script> <script type="text/javascript" src="Panel.js"></script> <script type="text/javascript" src="PanelEnablerView.js"></script> - <script type="text/javascript" src="StatusBarButton.js"></script> <script type="text/javascript" src="ElementsPanel.js"></script> <script type="text/javascript" src="ResourcesPanel.js"></script> <script type="text/javascript" src="ScriptsPanel.js"></script> diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js index f6377c2..aa21a86 100644 --- a/WebCore/inspector/front-end/inspector.js +++ b/WebCore/inspector/front-end/inspector.js @@ -39,6 +39,7 @@ var Preferences = { showInheritedComputedStyleProperties: false, styleRulesExpandedState: {}, showMissingLocalizedStrings: false, + useDOMAgent: false } var WebInspector = { @@ -306,7 +307,7 @@ var WebInspector = { set hoveredDOMNode(x) { - if (this._hoveredDOMNode === x) + if (objectsAreSame(this._hoveredDOMNode, x)) return; this._hoveredDOMNode = x; @@ -332,7 +333,7 @@ var WebInspector = { } if (this._hoveredDOMNode) { - InspectorController.highlightDOMNode(this._hoveredDOMNode.id); + InspectorController.highlightDOMNode(this._hoveredDOMNode); this.showingDOMNodeHighlight = true; } else { InspectorController.hideDOMNodeHighlight(); @@ -352,7 +353,9 @@ WebInspector.loaded = function() // this.changes = new WebInspector.ChangesView(this.drawer); // TODO: Remove class="hidden" from inspector.html on button#changes-status-bar-item this.drawer.visibleView = this.console; - this.domAgent = new WebInspector.DOMAgent(); + + if (Preferences.useDOMAgent) + this.domAgent = new WebInspector.DOMAgent(); this.resourceCategories = { documents: new WebInspector.ResourceCategory(WebInspector.UIString("Documents"), "documents"), @@ -438,7 +441,7 @@ WebInspector.loaded = function() document.getElementById("toolbar").addEventListener("mousedown", this.toolbarDragStart, true); document.getElementById("close-button").addEventListener("click", this.close, true); - InspectorController.loaded(); + InspectorController.loaded(Preferences.useDOMAgent); } var windowLoaded = function() @@ -850,12 +853,12 @@ WebInspector.elementDragEnd = function(event) WebInspector.showConsole = function() { - this.drawer.showView(this.console); + this.drawer.visibleView = this.console; } WebInspector.showChanges = function() { - this.drawer.showView(this.changes); + this.drawer.visibleView = this.changes; } WebInspector.showElementsPanel = function() @@ -906,23 +909,6 @@ WebInspector.addResource = function(identifier, payload) this.panels.resources.addResource(resource); } -WebInspector.clearConsoleMessages = function() -{ - WebInspector.console.clearMessages(false); -} - -WebInspector.selectDatabase = function(o) -{ - WebInspector.showDatabasesPanel(); - WebInspector.panels.databases.selectDatabase(o); -} - -WebInspector.selectDOMStorage = function(o) -{ - WebInspector.showDatabasesPanel(); - WebInspector.panels.databases.selectDOMStorage(o); -} - WebInspector.updateResource = function(identifier, payload) { var resource = this.resources[identifier]; @@ -1087,6 +1073,11 @@ WebInspector.reset = function() this.console.clearMessages(); } +WebInspector.inspectedWindowCleared = function(inspectedWindow) +{ + this.panels.elements.inspectedWindowCleared(inspectedWindow); +} + WebInspector.resourceURLChanged = function(resource, oldURL) { delete this.resourceURLMap[oldURL]; @@ -1147,9 +1138,8 @@ WebInspector.drawLoadingPieChart = function(canvas, percent) { g.fill(); } -WebInspector.updateFocusedNode = function(nodeId) +WebInspector.updateFocusedNode = function(node) { - var node = WebInspector.domAgent.nodeForId(nodeId); if (!node) // FIXME: Should we deselect if null is passed in? return; @@ -1339,11 +1329,6 @@ WebInspector.performSearch = function(event) this.currentPanel.performSearch(query); } -WebInspector.addNodesToSearchResult = function(nodeIds) -{ - WebInspector.panels.elements.addNodesToSearchResult(nodeIds); -} - WebInspector.updateSearchMatchesCount = function(matches, panel) { if (!panel) diff --git a/WebCore/inspector/front-end/treeoutline.js b/WebCore/inspector/front-end/treeoutline.js index 67f35c2..579e7fb 100644 --- a/WebCore/inspector/front-end/treeoutline.js +++ b/WebCore/inspector/front-end/treeoutline.js @@ -249,18 +249,21 @@ TreeOutline.prototype._forgetChildrenRecursive = function(parentElement) } } -TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) +TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent, equal) { if (!representedObject) return null; + if (!equal) + equal = function(a, b) { return a === b }; + if ("__treeElementIdentifier" in representedObject) { // If this representedObject has a tree element identifier, and it is a known TreeElement // in our tree we can just return that tree element. var elements = this._knownTreeElements[representedObject.__treeElementIdentifier]; if (elements) { for (var i = 0; i < elements.length; ++i) - if (elements[i].representedObject === representedObject) + if (equal(elements[i].representedObject, representedObject)) return elements[i]; } } @@ -274,7 +277,7 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, var found = false; for (var i = 0; i < this.children.length; ++i) { item = this.children[i]; - if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) { + if (equal(item.representedObject, representedObject) || isAncestor(item.representedObject, representedObject)) { found = true; break; } @@ -289,7 +292,7 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, var currentObject = representedObject; while (currentObject) { ancestors.unshift(currentObject); - if (currentObject === item.representedObject) + if (equal(currentObject, item.representedObject)) break; currentObject = getParent(currentObject); } @@ -298,18 +301,18 @@ TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, for (var i = 0; i < ancestors.length; ++i) { // Make sure we don't call findTreeElement with the same representedObject // again, to prevent infinite recursion. - if (ancestors[i] === representedObject) + if (equal(ancestors[i], representedObject)) continue; // FIXME: we could do something faster than findTreeElement since we will know the next // ancestor exists in the tree. - item = this.findTreeElement(ancestors[i], isAncestor, getParent); + item = this.findTreeElement(ancestors[i], isAncestor, getParent, equal); if (item && item.onpopulate) item.onpopulate(item); } // Now that all the ancestors are populated, try to find the representedObject again. This time // without the isAncestor and getParent functions to prevent an infinite recursion if it isn't found. - return this.findTreeElement(representedObject); + return this.findTreeElement(representedObject, null, null, equal); } TreeOutline.prototype.treeElementFromPoint = function(x, y) diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js index e60af42..eec0b87 100644 --- a/WebCore/inspector/front-end/utilities.js +++ b/WebCore/inspector/front-end/utilities.js @@ -56,18 +56,6 @@ Object.type = function(obj, win) return type; } -Object.proxyType = function(objectProxy) -{ - if (objectProxy === null) - return "null"; - - var type = typeof objectProxy; - if (type !== "object" && type !== "function") - return type; - - return objectProxy.type; -} - Object.hasProperties = function(obj) { if (typeof obj === "undefined" || typeof obj === "null") @@ -77,9 +65,9 @@ Object.hasProperties = function(obj) return false; } -Object.describe = function(obj, abbreviated, win) +Object.describe = function(obj, abbreviated) { - var type1 = Object.type(obj, win); + var type1 = Object.type(obj); var type2 = Object.prototype.toString.call(obj).replace(/^\[object (.*)\]$/i, "$1"); switch (type1) { @@ -250,7 +238,7 @@ Element.prototype.hasStyleClass = function(className) Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) { - for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) + for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode) for (var i = 0; i < nameArray.length; ++i) if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) return node; @@ -264,7 +252,7 @@ Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) Node.prototype.enclosingNodeOrSelfWithClass = function(className) { - for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) + for (var node = this; node && !objectsAreSame(node, this.ownerDocument); node = node.parentNode) if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className)) return node; return null; @@ -530,6 +518,21 @@ function nodeContentPreview() return preview.collapseWhitespace(); } +function objectsAreSame(a, b) +{ + // FIXME: Make this more generic so is works with any wrapped object, not just nodes. + // This function is used to compare nodes that might be JSInspectedObjectWrappers, since + // JavaScript equality is not true for JSInspectedObjectWrappers of the same node wrapped + // with different global ExecStates, we use isSameNode to compare them. + if (a === b) + return true; + if (!a || !b) + return false; + if (a.isSameNode && b.isSameNode) + return a.isSameNode(b); + return false; +} + function isAncestorNode(ancestor) { if (!this || !ancestor) @@ -537,7 +540,7 @@ function isAncestorNode(ancestor) var currentNode = ancestor.parentNode; while (currentNode) { - if (this === currentNode) + if (objectsAreSame(this, currentNode)) return true; currentNode = currentNode.parentNode; } @@ -558,13 +561,13 @@ function firstCommonNodeAncestor(node) var node1 = this.parentNode; var node2 = node.parentNode; - if ((!node1 || !node2) || node1 !== node2) + if ((!node1 || !node2) || !objectsAreSame(node1, node2)) return null; while (node1 && node2) { if (!node1.parentNode || !node2.parentNode) break; - if (node1 !== node2) + if (!objectsAreSame(node1, node2)) break; node1 = node1.parentNode; @@ -623,7 +626,7 @@ function traverseNextNode(skipWhitespace, stayWithin) if (node) return node; - if (stayWithin && this === stayWithin) + if (stayWithin && objectsAreSame(this, stayWithin)) return null; node = skipWhitespace ? nextSiblingSkippingWhitespace.call(this) : this.nextSibling; @@ -631,7 +634,7 @@ function traverseNextNode(skipWhitespace, stayWithin) return node; node = this; - while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin)) + while (node && !(skipWhitespace ? nextSiblingSkippingWhitespace.call(node) : node.nextSibling) && (!stayWithin || !node.parentNode || !objectsAreSame(node.parentNode, stayWithin))) node = node.parentNode; if (!node) return null; @@ -643,7 +646,7 @@ function traversePreviousNode(skipWhitespace, stayWithin) { if (!this) return; - if (stayWithin && this === stayWithin) + if (stayWithin && objectsAreSame(this, stayWithin)) return null; var node = skipWhitespace ? previousSiblingSkippingWhitespace.call(this) : this.previousSibling; while (node && (skipWhitespace ? lastChildSkippingWhitespace.call(node) : node.lastChild) ) @@ -753,10 +756,10 @@ function parentNodeOrFrameElement(node) { } function isAncestorIncludingParentFrames(a, b) { - if (a === b) + if (objectsAreSame(a, b)) return false; for (var node = b; node; node = getDocumentForNode(node).defaultView.frameElement) - if (a === node || isAncestorNode.call(a, node)) + if (objectsAreSame(a, node) || isAncestorNode.call(a, node)) return true; return false; } @@ -787,27 +790,20 @@ Number.secondsToString = function(seconds, formatterFunction, higherResolution) return formatterFunction("%.1f days", days); } -Number.bytesToString = function(bytes, formatterFunction, higherResolution) +Number.bytesToString = function(bytes, formatterFunction) { if (!formatterFunction) formatterFunction = String.sprintf; - if (typeof higherResolution === "undefined") - higherResolution = true; if (bytes < 1024) return formatterFunction("%.0fB", bytes); var kilobytes = bytes / 1024; - if (higherResolution && kilobytes < 1024) + if (kilobytes < 1024) return formatterFunction("%.2fKB", kilobytes); - else if (kilobytes < 1024) - return formatterFunction("%.0fKB", kilobytes); var megabytes = kilobytes / 1024; - if (higherResolution) - return formatterFunction("%.3fMB", megabytes); - else - return formatterFunction("%.0fMB", megabytes); + return formatterFunction("%.3fMB", megabytes); } Number.constrain = function(num, min, max) |