diff options
Diffstat (limited to 'WebCore/inspector/front-end')
21 files changed, 607 insertions, 244 deletions
diff --git a/WebCore/inspector/front-end/BreakpointManager.js b/WebCore/inspector/front-end/BreakpointManager.js index 3ccccac..4f6965a 100644 --- a/WebCore/inspector/front-end/BreakpointManager.js +++ b/WebCore/inspector/front-end/BreakpointManager.js @@ -38,6 +38,7 @@ WebInspector.BreakpointManager.prototype = { if (this._oneTimeBreakpoint) this._removeBreakpointFromBackend(this._oneTimeBreakpoint); this._oneTimeBreakpoint = breakpoint; + // FIXME(40669): one time breakpoint will be persisted in inspector settings if not hit. this._saveBreakpointOnBackend(breakpoint); }, @@ -51,15 +52,15 @@ WebInspector.BreakpointManager.prototype = { addBreakpoint: function(sourceID, sourceURL, line, enabled, condition) { - var breakpoint = new WebInspector.Breakpoint(this, sourceID, sourceURL, line, enabled, condition); - if (this._breakpoints[breakpoint.id]) - return; - if (this._oneTimeBreakpoint && (this._oneTimeBreakpoint.id == breakpoint.id)) - delete this._oneTimeBreakpoint; - this._breakpoints[breakpoint.id] = breakpoint; - this._saveBreakpointOnBackend(breakpoint); - this.dispatchEventToListeners("breakpoint-added", breakpoint); - }, + var breakpoint = this._addBreakpoint(sourceID, sourceURL, line, enabled, condition); + if (breakpoint) + this._saveBreakpointOnBackend(breakpoint); + }, + + restoredBreakpoint: function(sourceID, sourceURL, line, enabled, condition) + { + this._addBreakpoint(sourceID, sourceURL, line, enabled, condition); + }, removeBreakpoint: function(breakpoint) { @@ -78,7 +79,7 @@ WebInspector.BreakpointManager.prototype = { breakpoints.push(this._breakpoints[id]); } return breakpoints; - }, + }, breakpointsForURL: function(url) { @@ -87,7 +88,7 @@ WebInspector.BreakpointManager.prototype = { if (this._breakpoints[id].url === url) breakpoints.push(this._breakpoints[id]); } - return breakpoints; + return breakpoints; }, reset: function() @@ -96,6 +97,18 @@ WebInspector.BreakpointManager.prototype = { delete this._oneTimeBreakpoint; }, + _addBreakpoint: function(sourceID, sourceURL, line, enabled, condition) + { + var breakpoint = new WebInspector.Breakpoint(this, sourceID, sourceURL, line, enabled, condition); + if (this._breakpoints[breakpoint.id]) + return; + if (this._oneTimeBreakpoint && (this._oneTimeBreakpoint.id == breakpoint.id)) + delete this._oneTimeBreakpoint; + this._breakpoints[breakpoint.id] = breakpoint; + this.dispatchEventToListeners("breakpoint-added", breakpoint); + return breakpoint; + }, + _saveBreakpointOnBackend: function(breakpoint) { InspectorBackend.setBreakpoint(breakpoint.sourceID, breakpoint.line, breakpoint.enabled, breakpoint.condition); diff --git a/WebCore/inspector/front-end/CSSCompletions.js b/WebCore/inspector/front-end/CSSCompletions.js new file mode 100644 index 0000000..5485464 --- /dev/null +++ b/WebCore/inspector/front-end/CSSCompletions.js @@ -0,0 +1,102 @@ +WebInspector.CSSCompletions = (function() { + var used = {}; + var properties = []; + var style = document.documentElement.style; + var list = document.defaultView.getComputedStyle(document.documentElement, ""); + var length = list.length; + for (var i = 0; i < length; ++i) + used[properties[i] = list[i]] = true; + + for (var i = 0, end = length; i < length; ++i) { + var propertyWords = properties[i].split("-"); + var j = propertyWords.length; + while (--j) { + propertyWords.pop(); + var shorthand = propertyWords.join("-"); + if (!(shorthand in used) && style[shorthand] !== undefined) { + used[shorthand] = true; + properties[end++] = shorthand; + } + } + } + + return properties.sort(); +})(); + +WebInspector.CSSCompletions.startsWith = function(prefix) +{ + var firstIndex = this._firstIndexOfPrefix(prefix); + if (firstIndex === -1) + return []; + + var results = []; + while (this[firstIndex].indexOf(prefix) === 0) + results.push(this[firstIndex++]); + return results; +} + +WebInspector.CSSCompletions.firstStartsWith = function(prefix) +{ + var foundIndex = this._firstIndexOfPrefix(prefix); + return (foundIndex === -1 ? "" : this[foundIndex]); +} + +WebInspector.CSSCompletions._firstIndexOfPrefix = function(prefix) +{ + if (!prefix) + return -1; + + var maxIndex = this.length - 1; + var minIndex = 0; + var foundIndex; + + do { + var middleIndex = (maxIndex + minIndex) >> 1; + if (this[middleIndex].indexOf(prefix) === 0) { + foundIndex = middleIndex; + break; + } + if (this[middleIndex] < prefix) + minIndex = middleIndex + 1; + else + maxIndex = middleIndex - 1; + } while (minIndex <= maxIndex); + + if (!foundIndex) + return -1; + + while (foundIndex && this[foundIndex - 1].indexOf(prefix) === 0) + foundIndex--; + + return foundIndex; +} + +WebInspector.CSSCompletions.next = function(str, prefix) +{ + return WebInspector.CSSCompletions._closest(str, prefix, 1); +} + +WebInspector.CSSCompletions.previous = function(str, prefix) +{ + return WebInspector.CSSCompletions._closest(str, prefix, -1); +} + +WebInspector.CSSCompletions._closest = function(str, prefix, shift) +{ + if (!str) + return ""; + + var index = this.indexOf(str); + if (index === -1) + return ""; + + if (!prefix) { + index = (index + this.length + shift) % this.length; + return this[index]; + } + + var propertiesWithPrefix = this.startsWith(prefix); + var j = propertiesWithPrefix.indexOf(str); + j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length; + return propertiesWithPrefix[j]; +} diff --git a/WebCore/inspector/front-end/ConsoleView.js b/WebCore/inspector/front-end/ConsoleView.js index d1f347b..8bb71e6 100644 --- a/WebCore/inspector/front-end/ConsoleView.js +++ b/WebCore/inspector/front-end/ConsoleView.js @@ -296,7 +296,7 @@ WebInspector.ConsoleView.prototype = { requestClearMessages: function() { - InjectedScriptAccess.getDefault().clearConsoleMessages(function() {}); + InspectorBackend.clearConsoleMessages(); }, clearMessages: function() @@ -399,7 +399,13 @@ WebInspector.ConsoleView.prototype = { return; } - this._contextMenu.show(event); + var contextMenu = new WebInspector.ContextMenu(); + if (!WebInspector.monitoringXHREnabled) + contextMenu.appendItem(WebInspector.UIString("Enable XMLHttpRequest logging"), InspectorBackend.enableMonitoringXHR.bind(InspectorBackend)); + else + contextMenu.appendItem(WebInspector.UIString("Disable XMLHttpRequest logging"), InspectorBackend.disableMonitoringXHR.bind(InspectorBackend)); + contextMenu.appendItem(WebInspector.UIString("Clear Console"), this.requestClearMessages.bind(this)); + contextMenu.show(event); }, _messagesSelectStart: function(event) @@ -444,8 +450,6 @@ WebInspector.ConsoleView.prototype = { var clearConsoleHandler = this.requestClearMessages.bind(this); var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl); this._shortcuts[shortcutL.key] = clearConsoleHandler; - this._contextMenu = new WebInspector.ContextMenu(); - this._contextMenu.appendItem(WebInspector.UIString("Clear Console"), clearConsoleHandler); var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Console")); var keys = WebInspector.isMac() ? [ shortcutK.name, shortcutL.name ] : [ shortcutL.name ]; diff --git a/WebCore/inspector/front-end/DOMAgent.js b/WebCore/inspector/front-end/DOMAgent.js index 5bde12f..ee85d1c 100644 --- a/WebCore/inspector/front-end/DOMAgent.js +++ b/WebCore/inspector/front-end/DOMAgent.js @@ -669,6 +669,9 @@ WebInspector.didRemoveAttribute = WebInspector.Callback.processCallback; WebInspector.didSetTextNodeValue = WebInspector.Callback.processCallback; WebInspector.didRemoveNode = WebInspector.Callback.processCallback; WebInspector.didChangeTagName = WebInspector.Callback.processCallback; +WebInspector.didGetOuterHTML = WebInspector.Callback.processCallback; +WebInspector.didSetOuterHTML = WebInspector.Callback.processCallback; +WebInspector.didPushNodeByPathToFrontend = WebInspector.Callback.processCallback; WebInspector.didGetEventListenersForNode = WebInspector.Callback.processCallback; WebInspector.didGetStyles = WebInspector.Callback.processCallback; diff --git a/WebCore/inspector/front-end/ElementsPanel.js b/WebCore/inspector/front-end/ElementsPanel.js index 55ba82d..c8eb3dd 100644 --- a/WebCore/inspector/front-end/ElementsPanel.js +++ b/WebCore/inspector/front-end/ElementsPanel.js @@ -59,7 +59,7 @@ WebInspector.ElementsPanel = function() this.panel.updateEventListeners(); if (this._focusedDOMNode) - InjectedScriptAccess.get(this._focusedDOMNode.injectedScriptId).addInspectedNode(this._focusedDOMNode.id, function() {}); + InspectorBackend.addInspectedNode(this._focusedDOMNode.id); }; this.contentElement.appendChild(this.treeOutline.element); @@ -224,9 +224,10 @@ WebInspector.ElementsPanel.prototype = { selectNode.call(this, node); } - if (this._selectedPathOnReset) - InjectedScriptAccess.getDefault().nodeByPath(this._selectedPathOnReset, selectLastSelectedNode.bind(this)); - else + if (this._selectedPathOnReset) { + var callId = WebInspector.Callback.wrap(selectLastSelectedNode.bind(this)); + InspectorBackend.pushNodeByPathToFrontend(callId, this._selectedPathOnReset); + } else selectNode.call(this); delete this._selectedPathOnReset; }, diff --git a/WebCore/inspector/front-end/ElementsTreeOutline.js b/WebCore/inspector/front-end/ElementsTreeOutline.js index e8fecb0..1b84b83 100644 --- a/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -1094,7 +1094,7 @@ WebInspector.ElementsTreeElement.prototype = { function changeTagNameCallback(nodeId) { - if (nodeId === -1) { + if (!nodeId) { cancel(); return; } @@ -1111,7 +1111,7 @@ WebInspector.ElementsTreeElement.prototype = { } var callId = WebInspector.Callback.wrap(changeTagNameCallback); - InspectorBackend.changeTagName(callId, this.representedObject.id, newText, wasExpanded); + InspectorBackend.changeTagName(callId, this.representedObject.id, newText); }, _textNodeEditingCommitted: function(element, newText) @@ -1382,10 +1382,12 @@ WebInspector.ElementsTreeElement.prototype = { function commitChange(value) { - InjectedScriptAccess.get(node.injectedScriptId).setOuterHTML(node.id, value, wasExpanded, selectNode.bind(this)); + var setCallId = WebInspector.Callback.wrap(selectNode); + InspectorBackend.setOuterHTML(setCallId, node.id, value); } - InjectedScriptAccess.get(node.injectedScriptId).getNodePropertyValue(node.id, "outerHTML", this._startEditingAsHTML.bind(this, commitChange)); + var getCallId = WebInspector.Callback.wrap(this._startEditingAsHTML.bind(this, commitChange)); + InspectorBackend.getOuterHTML(getCallId, node.id); }, _copyHTML: function() diff --git a/WebCore/inspector/front-end/InjectedScript.js b/WebCore/inspector/front-end/InjectedScript.js index e62a916..26495e8 100644 --- a/WebCore/inspector/front-end/InjectedScript.js +++ b/WebCore/inspector/front-end/InjectedScript.js @@ -80,13 +80,6 @@ InjectedScript.releaseWrapperObjectGroup = function(objectGroupName) { delete InjectedScript.objectGroups[objectGroupName]; }; -// Called from within InspectorController on the 'inspected page' side. -InjectedScript.reset = function() -{ -} - -InjectedScript.reset(); - InjectedScript.dispatch = function(methodName, args, callId) { var argsArray = eval("(" + args + ")"); @@ -218,29 +211,6 @@ InjectedScript.setPropertyValue = function(objectProxy, propertyName, expression } } -InjectedScript.getNodePropertyValue = function(nodeId, propertyName) -{ - var node = InjectedScript._nodeForId(nodeId); - if (!node) - return false; - var result = node[propertyName]; - return result !== undefined ? result : false; -} - -InjectedScript.setOuterHTML = function(nodeId, value, expanded) -{ - var node = InjectedScript._nodeForId(nodeId); - if (!node) - return false; - - var parent = node.parentNode; - var prevSibling = node.previousSibling; - node.outerHTML = value; - var newNode = prevSibling ? prevSibling.nextSibling : parent.firstChild; - - return InjectedScriptHost.pushNodePathToFrontend(newNode, expanded, false); -} - InjectedScript._populatePropertyNames = function(object, resultSet) { for (var o = object; o; o = o.__proto__) { @@ -281,14 +251,15 @@ InjectedScript.getCompletions = function(expression, includeInspectorCommandLine } else { if (!expression) expression = "this"; - expressionResult = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression); + expressionResult = InjectedScript._evaluateOn(inspectedWindow.eval, inspectedWindow, expression, false); } - if (typeof expressionResult == "object") + if (typeof expressionResult === "object") InjectedScript._populatePropertyNames(expressionResult, props); - if (includeInspectorCommandLineAPI) - for (var prop in inspectedWindow.console._inspectorCommandLineAPI) - if (prop.charAt(0) !== '_') - props[prop] = true; + + if (includeInspectorCommandLineAPI) { + for (var prop in InjectedScript._commandLineAPI) + props[prop] = true; + } } catch(e) { } return props; @@ -319,14 +290,21 @@ InjectedScript._evaluateAndWrap = function(evalFunction, object, expression, obj InjectedScript._evaluateOn = function(evalFunction, object, expression, dontUseCommandLineAPI) { - InjectedScript._ensureCommandLineAPIInstalled(evalFunction, object); - // Surround the expression in with statements to inject our command line API so that - // the window object properties still take more precedent than our API functions. - if (!dontUseCommandLineAPI) - expression = "with (window.console._inspectorCommandLineAPI) { with (window) {\n" + expression + "\n} }"; + if (!dontUseCommandLineAPI) { + // Only install command line api object for the time of evaluation. + + // 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. + inspectedWindow.console._commandLineAPI = InjectedScript._commandLineAPI; + + expression = "with (window.console._commandLineAPI) { with (window) {\n" + expression + "\n} }"; + } var value = evalFunction.call(object, expression); + if (!dontUseCommandLineAPI) + delete inspectedWindow.console._commandLineAPI; + // When evaluating on call frame error is not thrown, but returned as a value. if (InjectedScript._type(value) === "error") throw value.toString(); @@ -334,20 +312,6 @@ InjectedScript._evaluateOn = function(evalFunction, object, expression, dontUseC return value; } -InjectedScript.addInspectedNode = function(nodeId) -{ - var node = InjectedScript._nodeForId(nodeId); - if (!node) - return false; - - InjectedScript._ensureCommandLineAPIInstalled(inspectedWindow.eval, inspectedWindow); - var inspectedNodes = inspectedWindow.console._inspectorCommandLineAPI._inspectedNodes; - inspectedNodes.unshift(node); - if (inspectedNodes.length >= 5) - inspectedNodes.pop(); - return true; -} - InjectedScript.getNodeId = function(node) { return InjectedScriptHost.pushNodePathToFrontend(node, false, false); @@ -392,125 +356,10 @@ InjectedScript._callFrameForId = function(id) return callFrame; } -InjectedScript.clearConsoleMessages = function() -{ - InjectedScriptHost.clearConsoleMessages(); - return true; -} - -InjectedScript._inspectObject = function(o) -{ - if (arguments.length === 0) - return; - - inspectedWindow.console.log(o); - if (InjectedScript._type(o) === "node") { - InjectedScriptHost.pushNodePathToFrontend(o, false, true); - } else { - switch (InjectedScript._describe(o)) { - case "Database": - InjectedScriptHost.selectDatabase(o); - break; - case "Storage": - InjectedScriptHost.selectDOMStorage(o); - break; - } - } -} - -InjectedScript._copy = function(o) -{ - if (InjectedScript._type(o) === "node") { - var nodeId = InjectedScriptHost.pushNodePathToFrontend(o, false, false); - InjectedScriptHost.copyNode(nodeId); - } else { - InjectedScriptHost.copyText(o); - } -} - -InjectedScript._ensureCommandLineAPIInstalled = function(evalFunction, evalObject) -{ - if (evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI")) - return; - var inspectorCommandLineAPI = evalFunction.call(evalObject, "window.console._inspectorCommandLineAPI = { \n\ - $: function() { return document.getElementById.apply(document, arguments) }, \n\ - $$: function() { return document.querySelectorAll.apply(document, arguments) }, \n\ - $x: function(xpath, context) \n\ - { \n\ - var nodes = []; \n\ - try { \n\ - var doc = context || document; \n\ - var results = doc.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null); \n\ - var node; \n\ - while (node = results.iterateNext()) nodes.push(node); \n\ - } catch (e) {} \n\ - return nodes; \n\ - }, \n\ - dir: function() { return console.dir.apply(console, arguments) }, \n\ - dirxml: function() { return console.dirxml.apply(console, arguments) }, \n\ - keys: function(o) { var a = []; for (var k in o) a.push(k); return a; }, \n\ - values: function(o) { var a = []; for (var k in o) a.push(o[k]); return a; }, \n\ - profile: function() { return console.profile.apply(console, arguments) }, \n\ - profileEnd: function() { return console.profileEnd.apply(console, arguments) }, \n\ - _logEvent: function _inspectorCommandLineAPI_logEvent(e) { console.log(e.type, e); }, \n\ - _allEventTypes: [\"mouse\", \"key\", \"load\", \"unload\", \"abort\", \"error\", \n\ - \"select\", \"change\", \"submit\", \"reset\", \"focus\", \"blur\", \n\ - \"resize\", \"scroll\"], \n\ - _normalizeEventTypes: function(t) \n\ - { \n\ - if (typeof t === \"undefined\") \n\ - t = console._inspectorCommandLineAPI._allEventTypes; \n\ - else if (typeof t === \"string\") \n\ - t = [t]; \n\ - var i, te = []; \n\ - for (i = 0; i < t.length; i++) { \n\ - if (t[i] === \"mouse\") \n\ - te.splice(0, 0, \"mousedown\", \"mouseup\", \"click\", \"dblclick\", \n\ - \"mousemove\", \"mouseover\", \"mouseout\"); \n\ - else if (t[i] === \"key\") \n\ - te.splice(0, 0, \"keydown\", \"keyup\", \"keypress\"); \n\ - else \n\ - te.push(t[i]); \n\ - } \n\ - return te; \n\ - }, \n\ - monitorEvents: function(o, t) \n\ - { \n\ - if (!o || !o.addEventListener || !o.removeEventListener) \n\ - return; \n\ - t = console._inspectorCommandLineAPI._normalizeEventTypes(t); \n\ - for (i = 0; i < t.length; i++) { \n\ - o.removeEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\ - o.addEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\ - } \n\ - }, \n\ - unmonitorEvents: function(o, t) \n\ - { \n\ - if (!o || !o.removeEventListener) \n\ - return; \n\ - t = console._inspectorCommandLineAPI._normalizeEventTypes(t); \n\ - for (i = 0; i < t.length; i++) { \n\ - o.removeEventListener(t[i], console._inspectorCommandLineAPI._logEvent, false); \n\ - } \n\ - }, \n\ - _inspectedNodes: [], \n\ - get $0() { return console._inspectorCommandLineAPI._inspectedNodes[0] }, \n\ - get $1() { return console._inspectorCommandLineAPI._inspectedNodes[1] }, \n\ - get $2() { return console._inspectorCommandLineAPI._inspectedNodes[2] }, \n\ - get $3() { return console._inspectorCommandLineAPI._inspectedNodes[3] }, \n\ - get $4() { return console._inspectorCommandLineAPI._inspectedNodes[4] }, \n\ - };"); - - inspectorCommandLineAPI.clear = InjectedScript.clearConsoleMessages; - inspectorCommandLineAPI.inspect = InjectedScript._inspectObject; - inspectorCommandLineAPI.copy = InjectedScript._copy; -} - InjectedScript._resolveObject = function(objectProxy) { var object = InjectedScript._objectForId(objectProxy.objectId); var path = objectProxy.path; - var protoDepth = objectProxy.protoDepth; // Follow the property path. for (var i = 0; InjectedScript._isDefined(object) && path && i < path.length; ++i) @@ -532,11 +381,11 @@ InjectedScript._objectForId = function(objectId) // - numbers point to DOM Node via the InspectorDOMAgent mapping // - strings point to console objects cached in InspectorController for lazy evaluation upon them // - objects contain complex ids and are currently used for scoped objects - if (typeof objectId === "number") { + if (typeof objectId === "number") return InjectedScript._nodeForId(objectId); - } else if (typeof objectId === "string") { + else if (typeof objectId === "string") return InjectedScript.unwrapObject(objectId); - } else if (typeof objectId === "object") { + else if (typeof objectId === "object") { var callFrame = InjectedScript._callFrameForId(objectId.callFrame); if (objectId.thisObject) return callFrame.thisObject; @@ -554,13 +403,6 @@ InjectedScript.pushNodeToFrontend = function(objectProxy) return InjectedScriptHost.pushNodePathToFrontend(object, false, false); } -InjectedScript.nodeByPath = function(path) -{ - // We make this call through the injected script only to get a nice - // callback for it. - return InjectedScriptHost.pushNodeByPathToFrontend(path.join(",")); -} - // Called from within InspectorController on the 'inspected page' side. InjectedScript.createProxyObject = function(object, objectId, abbreviate) { @@ -736,14 +578,13 @@ InjectedScript._type = function(obj) InjectedScript._describe = function(obj, abbreviated) { - var type1 = InjectedScript._type(obj); - var type2 = InjectedScript._className(obj); + var type = InjectedScript._type(obj); - switch (type1) { + switch (type) { case "object": case "node": case "array": - return type2; + return InjectedScript._className(obj); case "string": if (!abbreviated) return obj; @@ -752,10 +593,8 @@ InjectedScript._describe = function(obj, abbreviated) return "\"" + obj + "\""; case "function": var objectText = InjectedScript._toString(obj); - if (!/^function /.test(objectText)) - objectText = (type2 == "object") ? type1 : type2; - else if (abbreviated) - objectText = /.*/.exec(obj)[0].replace(/ +$/g, ""); + if (abbreviated) + objectText = /.*/.exec(objectText)[0].replace(/ +$/g, ""); return objectText; default: return InjectedScript._toString(obj); @@ -779,11 +618,185 @@ InjectedScript._className = function(obj) return str.replace(/^\[object (.*)\]$/i, "$1"); } else { // V8 - if (typeof obj !== "object") - return "null"; - return obj.constructor.name || "Object"; + return obj.constructor && obj.constructor.name || "Object"; + } +} + +InjectedScript._logEvent = function(event) +{ + console.log(event.type, event); +} + +InjectedScript._normalizeEventTypes = function(types) +{ + if (typeof types === "undefined") + types = [ "mouse", "key", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll" ]; + else if (typeof types === "string") + types = [ types ]; + + var result = []; + for (var i = 0; i < types.length; i++) { + if (types[i] === "mouse") + result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout"); + else if (types[i] === "key") + result.splice(0, 0, "keydown", "keyup", "keypress"); + else + result.push(types[i]); + } + return result; +} + +InjectedScript._inspectedNode = function(num) +{ + var nodeId = InjectedScriptHost.inspectedNode(num); + return InjectedScript._nodeForId(nodeId); +} + +function CommandLineAPI() +{ +} + +CommandLineAPI.prototype = { + // Only add API functions here, private stuff should go to + // InjectedScript so that it is not suggested by the completion. + $: 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(object) + { + return Object.keys(object); + }, + + values: function(object) + { + var result = []; + for (var key in object) + result.push(object[key]); + return result; + }, + + profile: function() + { + return console.profile.apply(console, arguments) + }, + + profileEnd: function() + { + return console.profileEnd.apply(console, arguments) + }, + + monitorEvents: function(object, types) + { + if (!object || !object.addEventListener || !object.removeEventListener) + return; + types = InjectedScript._normalizeEventTypes(types); + for (var i = 0; i < types.length; ++i) { + object.removeEventListener(types[i], InjectedScript._logEvent, false); + object.addEventListener(types[i], InjectedScript._logEvent, false); + } + }, + + unmonitorEvents: function(object, types) + { + if (!object || !object.addEventListener || !object.removeEventListener) + return; + types = InjectedScript._normalizeEventTypes(types); + for (var i = 0; i < types.length; ++i) + object.removeEventListener(types[i], InjectedScript._logEvent, false); + }, + + inspect: function(object) + { + if (arguments.length === 0) + return; + + inspectedWindow.console.log(object); + if (InjectedScript._type(object) === "node") + InjectedScriptHost.pushNodePathToFrontend(object, false, true); + else { + switch (InjectedScript._describe(object)) { + case "Database": + InjectedScriptHost.selectDatabase(object); + break; + case "Storage": + InjectedScriptHost.selectDOMStorage(object); + break; + } + } + }, + + copy: function(object) + { + if (InjectedScript._type(object) === "node") { + var nodeId = InjectedScriptHost.pushNodePathToFrontend(object, false, false); + InjectedScriptHost.copyNode(nodeId); + } else + InjectedScriptHost.copyText(object); + }, + + clear: function() + { + InjectedScriptHost.clearConsoleMessages(); + }, + + get $0() + { + return InjectedScript._inspectedNode(0); + }, + + get $1() + { + return InjectedScript._inspectedNode(1); + }, + + get $2() + { + return InjectedScript._inspectedNode(2); + }, + + get $3() + { + return InjectedScript._inspectedNode(3); + }, + + get $4() + { + return InjectedScript._inspectedNode(4); } } +InjectedScript._commandLineAPI = new CommandLineAPI(); + return InjectedScript; }); diff --git a/WebCore/inspector/front-end/InjectedScriptAccess.js b/WebCore/inspector/front-end/InjectedScriptAccess.js index c388213..90daab7 100644 --- a/WebCore/inspector/front-end/InjectedScriptAccess.js +++ b/WebCore/inspector/front-end/InjectedScriptAccess.js @@ -70,18 +70,13 @@ InjectedScriptAccess._installHandler = function(methodName, async) // - Make sure corresponding methods in InjectedScript return non-null and non-undefined values, // - Make sure last parameter of all the InjectedSriptAccess.* calls is a callback function. // We keep these sorted. -InjectedScriptAccess._installHandler("addInspectedNode"); -InjectedScriptAccess._installHandler("clearConsoleMessages"); InjectedScriptAccess._installHandler("evaluate"); InjectedScriptAccess._installHandler("evaluateInCallFrame"); InjectedScriptAccess._installHandler("getCompletions"); -InjectedScriptAccess._installHandler("getNodePropertyValue"); InjectedScriptAccess._installHandler("getProperties"); InjectedScriptAccess._installHandler("getPrototypes"); InjectedScriptAccess._installHandler("openInInspectedWindow"); InjectedScriptAccess._installHandler("pushNodeToFrontend"); -InjectedScriptAccess._installHandler("nodeByPath"); -InjectedScriptAccess._installHandler("setOuterHTML"); InjectedScriptAccess._installHandler("setPropertyValue"); InjectedScriptAccess._installHandler("evaluateOnSelf"); diff --git a/WebCore/inspector/front-end/InspectorBackendStub.js b/WebCore/inspector/front-end/InspectorBackendStub.js index 492bf87..1ae32b5 100644 --- a/WebCore/inspector/front-end/InspectorBackendStub.js +++ b/WebCore/inspector/front-end/InspectorBackendStub.js @@ -32,7 +32,6 @@ if (!window.InspectorBackend) { WebInspector.InspectorBackendStub = function() { - this._searchingForNode = false; this._attachedWindowHeight = 0; this._timelineEnabled = false; } @@ -60,25 +59,23 @@ WebInspector.InspectorBackendStub.prototype = { { }, - clearMessages: function() + clearConsoleMessages: function() { }, - searchingForNode: function() + getOuterHTML: function() { - return this._searchingForNode; }, - search: function(sourceRow, query) + setOuterHTML: function() { }, - toggleNodeSearch: function() + addInspectedNode: function() { - this._searchingForNode = !this._searchingForNode; }, - setAttachedWindowHeight: function(height) + search: function(sourceRow, query) { }, @@ -144,6 +141,16 @@ WebInspector.InspectorBackendStub.prototype = { WebInspector.searchingForNodeWasDisabled(); }, + enableMonitoringXHR: function() + { + WebInspector.monitoringXHRWasEnabled(); + }, + + disableMonitoringXHR: function() + { + WebInspector.monitoringXHRWasDisabled(); + }, + reloadPage: function() { }, diff --git a/WebCore/inspector/front-end/InspectorFrontendHostStub.js b/WebCore/inspector/front-end/InspectorFrontendHostStub.js index 5456069..39bbe02 100644 --- a/WebCore/inspector/front-end/InspectorFrontendHostStub.js +++ b/WebCore/inspector/front-end/InspectorFrontendHostStub.js @@ -40,7 +40,13 @@ WebInspector._platformFlavor = WebInspector.PlatformFlavor.MacLeopard; WebInspector.InspectorFrontendHostStub.prototype = { platform: function() { - return "mac"; + var match = navigator.userAgent.match(/Windows NT/); + if (match) + return "windows"; + match = navigator.userAgent.match(/Mac OS X/); + if (match) + return "mac"; + return "linux"; }, port: function() diff --git a/WebCore/inspector/front-end/ProfilesPanel.js b/WebCore/inspector/front-end/ProfilesPanel.js index 1980fa5..b5122af 100644 --- a/WebCore/inspector/front-end/ProfilesPanel.js +++ b/WebCore/inspector/front-end/ProfilesPanel.js @@ -124,7 +124,7 @@ WebInspector.ProfilesPanel = function() this._profiles = []; this._profilerEnabled = Preferences.profilerAlwaysEnabled; - this.reset(); + this._reset(); } WebInspector.ProfilesPanel.prototype = { @@ -167,7 +167,7 @@ WebInspector.ProfilesPanel.prototype = { populateInterface: function() { - this.reset(); + this._reset(); if (this.visible) this._populateProfiles(); else @@ -189,10 +189,15 @@ WebInspector.ProfilesPanel.prototype = { return; this._profilerEnabled = false; - this.reset(); + this._reset(); }, - reset: function() + resetProfiles: function() + { + this._reset(); + }, + + _reset: function() { for (var i = 0; i < this._profiles.length; ++i) delete this._profiles[i]._profileView; @@ -222,7 +227,7 @@ WebInspector.ProfilesPanel.prototype = { _clearProfiles: function() { InspectorBackend.clearProfiles(); - this.reset(); + this._reset(); }, registerProfileType: function(profileType) @@ -618,7 +623,8 @@ WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle) WebInspector.ProfileGroupSidebarTreeElement.prototype = { onselect: function() { - WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile); + if (this.children.length > 0) + WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile); } } diff --git a/WebCore/inspector/front-end/ScriptView.js b/WebCore/inspector/front-end/ScriptView.js index fb0bb4b..1883fb3 100644 --- a/WebCore/inspector/front-end/ScriptView.js +++ b/WebCore/inspector/front-end/ScriptView.js @@ -105,7 +105,12 @@ WebInspector.ScriptView.prototype = { this.sourceFrame.updateContent(this._prependWhitespace(newBody)); }, - // The follow methods are pulled from SourceView, since they are + _sourceIDForLine: function(line) + { + return this.script.sourceID; + }, + + // The following methods are pulled from SourceView, since they are // generic and work with ScriptView just fine. hide: WebInspector.SourceView.prototype.hide, diff --git a/WebCore/inspector/front-end/ScriptsPanel.js b/WebCore/inspector/front-end/ScriptsPanel.js index 4504d57..c23db14 100644 --- a/WebCore/inspector/front-end/ScriptsPanel.js +++ b/WebCore/inspector/front-end/ScriptsPanel.js @@ -169,8 +169,6 @@ WebInspector.ScriptsPanel = function() this._registerShortcuts(); this._debuggerEnabled = Preferences.debuggerAlwaysEnabled; - if (Preferences.debuggerAlwaysEnabled) - this._attachDebuggerWhenShown = true; WebInspector.breakpointManager.addEventListener("breakpoint-added", this._breakpointAdded, this); WebInspector.breakpointManager.addEventListener("breakpoint-removed", this._breakpointRemoved, this); diff --git a/WebCore/inspector/front-end/Section.js b/WebCore/inspector/front-end/Section.js index 7710192..913d495 100644 --- a/WebCore/inspector/front-end/Section.js +++ b/WebCore/inspector/front-end/Section.js @@ -82,7 +82,22 @@ WebInspector.Section.prototype = { if (this._subtitle === x) return; this._subtitle = x; - this.subtitleElement.innerHTML = x; + this.subtitleElement.setAttribute("data-uncopyable", x); + }, + + get subtitleAsText() + { + var result = ""; + var data = this.subtitleElement.getAttribute("data-uncopyable"); + if (data) + result += data; + var child = this.subtitleElement.querySelector("[data-uncopyable]"); + if (child) { + var linkData = child.getAttribute("data-uncopyable"); + if (linkData) + result += linkData; + } + return result; }, get expanded() diff --git a/WebCore/inspector/front-end/StoragePanel.js b/WebCore/inspector/front-end/StoragePanel.js index ca1b276..fef7802 100644 --- a/WebCore/inspector/front-end/StoragePanel.js +++ b/WebCore/inspector/front-end/StoragePanel.js @@ -289,6 +289,7 @@ WebInspector.StoragePanel.prototype = { var column = {}; column.width = columnIdentifier.length; column.title = columnIdentifier; + column.sortable = true; columns[columnIdentifier] = column; ++numColumns; @@ -313,9 +314,45 @@ WebInspector.StoragePanel.prototype = { for (var i = 0; i < length; ++i) dataGrid.appendChild(nodes[i]); + dataGrid.addEventListener("sorting changed", this._sortDataGrid.bind(this, dataGrid), this); return dataGrid; }, + _sortDataGrid: function(dataGrid) + { + var nodes = dataGrid.children.slice(); + var sortColumnIdentifier = dataGrid.sortColumnIdentifier; + var sortDirection = dataGrid.sortOrder === "ascending" ? 1 : -1; + var columnIsNumeric = true; + + for (var i = 0; i < nodes.length; i++) { + if (isNaN(Number(nodes[i].data[sortColumnIdentifier]))) + columnIsNumeric = false; + } + + function comparator(dataGridNode1, dataGridNode2) + { + var item1 = dataGridNode1.data[sortColumnIdentifier]; + var item2 = dataGridNode2.data[sortColumnIdentifier]; + + var comparison; + if (columnIsNumeric) { + // Sort numbers based on comparing their values rather than a lexicographical comparison. + var number1 = parseFloat(item1); + var number2 = parseFloat(item2); + comparison = number1 < number2 ? -1 : (number1 > number2 ? 1 : 0); + } else + comparison = item1 < item2 ? -1 : (item1 > item2 ? 1 : 0); + + return sortDirection * comparison; + } + + nodes.sort(comparator); + dataGrid.removeChildren(); + for (var i = 0; i < nodes.length; i++) + dataGrid.appendChild(nodes[i]); + }, + updateDOMStorage: function(storageId) { var domStorage = this._domStorageForId(storageId); diff --git a/WebCore/inspector/front-end/StylesSidebarPane.js b/WebCore/inspector/front-end/StylesSidebarPane.js index 18b7f0f..649b9d0 100644 --- a/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/WebCore/inspector/front-end/StylesSidebarPane.js @@ -651,7 +651,10 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl if (!subtitle) { if (this.styleRule.parentStyleSheet && this.styleRule.parentStyleSheet.href) { var url = this.styleRule.parentStyleSheet.href; - this.subtitleElement.appendChild(WebInspector.linkifyResourceAsNode(url, "resources", this.rule.sourceLine + 1)); + var link = WebInspector.linkifyResourceAsNode(url, "resources", this.rule.sourceLine + 1); + link.setAttribute("data-uncopyable", link.textContent); + link.textContent = ""; + this.subtitleElement.appendChild(link); } else if (isUserAgent) subtitle = WebInspector.UIString("user agent stylesheet"); else if (isUser) @@ -669,7 +672,7 @@ WebInspector.StylePropertiesSection = function(styleRule, subtitle, computedStyl this.identifier = styleRule.selectorText; if (this.subtitle) - this.identifier += ":" + this.subtitleElement.textContent; + this.identifier += ":" + this.subtitle; } WebInspector.StylePropertiesSection.prototype = { @@ -1315,6 +1318,18 @@ WebInspector.StylePropertyTreeElement.prototype = { event.stopPropagation(); }, + restoreNameElement: function() + { + // Restore <span class="webkit-css-property"> if it doesn't yet exist or was accidentally deleted. + if (this.nameElement === this.listItemElement.querySelector(".webkit-css-property")) + return; + + this.nameElement = document.createElement("span"); + this.nameElement.className = "webkit-css-property"; + this.nameElement.textContent = ""; + this.listItemElement.insertBefore(this.nameElement, this.listItemElement.firstChild); + }, + startEditing: function(selectElement) { // FIXME: we don't allow editing of longhand properties under a shorthand right now. @@ -1324,7 +1339,12 @@ WebInspector.StylePropertyTreeElement.prototype = { if (WebInspector.isBeingEdited(this.listItemElement) || (this.treeOutline.section && !this.treeOutline.section.editable)) return; - var context = { expanded: this.expanded, hasChildren: this.hasChildren, keyDownListener: this.editingKeyDown.bind(this) }; + var context = { + expanded: this.expanded, + hasChildren: this.hasChildren, + keyDownListener: this.editingKeyDown.bind(this), + keyPressListener: this.editingKeyPress.bind(this) + }; // Lie about our children to prevent expanding on double click and to collapse shorthands. this.hasChildren = false; @@ -1333,11 +1353,42 @@ WebInspector.StylePropertyTreeElement.prototype = { selectElement = this.listItemElement; this.listItemElement.addEventListener("keydown", context.keyDownListener, false); + this.listItemElement.addEventListener("keypress", context.keyPressListener, false); WebInspector.startEditing(this.listItemElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1); }, + editingKeyPress: function(event) + { + var selection = window.getSelection(); + var colonIndex = this.listItemElement.textContent.indexOf(":"); + var selectionLeftOffset = event.target.selectionLeftOffset; + + if (colonIndex < 0 || selectionLeftOffset <= colonIndex) { + // Complete property names. + var character = event.data.toLowerCase(); + if (character && /[a-z-]/.test(character)) { + var prefix = selection.anchorNode.textContent.substring(0, selection.anchorOffset); + var property = WebInspector.CSSCompletions.firstStartsWith(prefix + character); + + if (!selection.isCollapsed) + selection.deleteFromDocument(); + + this.restoreNameElement(); + + if (property) { + if (property !== this.nameElement.textContent) + this.nameElement.textContent = property; + this.nameElement.firstChild.select(prefix.length + 1); + event.preventDefault(); + } + } + } else { + // FIXME: This should complete property values. + } + }, + editingKeyDown: function(event) { var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); @@ -1396,9 +1447,24 @@ WebInspector.StylePropertyTreeElement.prototype = { } replacementString = prefix + number + suffix; - } else { - // FIXME: this should cycle through known keywords for the current property name. + } else if (selection.containsNode(this.nameElement, true)) { + var prefix = selectionRange.startContainer.textContent.substring(0, selectionRange.startOffset); + var property; + + if (event.keyIdentifier === "Up") + property = WebInspector.CSSCompletions.previous(wordString, prefix); + else if (event.keyIdentifier === "Down") + property = WebInspector.CSSCompletions.next(wordString, prefix); + + var startOffset = selectionRange.startOffset; + if (property) { + this.nameElement.textContent = property; + this.nameElement.firstChild.select(startOffset); + } + event.preventDefault(); return; + } else { + // FIXME: this should cycle through known keywords for the current property value. } var replacementTextNode = document.createTextNode(replacementString); @@ -1434,6 +1500,7 @@ WebInspector.StylePropertyTreeElement.prototype = { if (context.expanded) this.expand(); this.listItemElement.removeEventListener("keydown", context.keyDownListener, false); + this.listItemElement.removeEventListener("keypress", context.keyPressListener, false); delete this.originalCSSText; }, diff --git a/WebCore/inspector/front-end/WebKit.qrc b/WebCore/inspector/front-end/WebKit.qrc index fd84586..add50e1 100644 --- a/WebCore/inspector/front-end/WebKit.qrc +++ b/WebCore/inspector/front-end/WebKit.qrc @@ -19,6 +19,7 @@ <file>ConsoleView.js</file> <file>ContextMenu.js</file> <file>CookieItemsView.js</file> + <file>CSSCompletions.js</file> <file>CSSStyleModel.js</file> <file>Database.js</file> <file>DatabaseQueryView.js</file> diff --git a/WebCore/inspector/front-end/inspector.css b/WebCore/inspector/front-end/inspector.css index 52b85bc..b92672a 100644 --- a/WebCore/inspector/front-end/inspector.css +++ b/WebCore/inspector/front-end/inspector.css @@ -27,6 +27,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +html { + height: 100%; +} + body { cursor: default; position: absolute; @@ -4038,6 +4042,10 @@ a.worker-item { color: inherit; } +.styles-section .subtitle::before, .styles-section .subtitle a::before { + content: attr(data-uncopyable); +} + .styles-section .properties { display: none; margin: 0; diff --git a/WebCore/inspector/front-end/inspector.html b/WebCore/inspector/front-end/inspector.html index 4c51634..8a8b7d5 100644 --- a/WebCore/inspector/front-end/inspector.html +++ b/WebCore/inspector/front-end/inspector.html @@ -82,6 +82,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="PropertiesSidebarPane.js"></script> <script type="text/javascript" src="EventListenersSidebarPane.js"></script> <script type="text/javascript" src="Color.js"></script> + <script type="text/javascript" src="CSSCompletions.js"></script> <script type="text/javascript" src="StylesSidebarPane.js"></script> <script type="text/javascript" src="PanelEnablerView.js"></script> <script type="text/javascript" src="WelcomeView.js"></script> diff --git a/WebCore/inspector/front-end/inspector.js b/WebCore/inspector/front-end/inspector.js index e8108af..3bb4180 100644 --- a/WebCore/inspector/front-end/inspector.js +++ b/WebCore/inspector/front-end/inspector.js @@ -1297,6 +1297,16 @@ WebInspector.searchingForNodeWasDisabled = function() this.panels.elements.searchingForNodeWasDisabled(); } +WebInspector.monitoringXHRWasEnabled = function() +{ + this.monitoringXHREnabled = true; +} + +WebInspector.monitoringXHRWasDisabled = function() +{ + this.monitoringXHREnabled = false; +} + WebInspector.attachDebuggerWhenShown = function() { this.panels.scripts.attachDebuggerWhenShown(); @@ -1334,7 +1344,7 @@ WebInspector.parsedScriptSource = function(sourceID, sourceURL, source, starting WebInspector.restoredBreakpoint = function(sourceID, sourceURL, line, enabled, condition) { - this.breakpointManager.addBreakpoint(sourceID, sourceURL, line, enabled, condition); + this.breakpointManager.restoredBreakpoint(sourceID, sourceURL, line, enabled, condition); } WebInspector.failedToParseScriptSource = function(sourceURL, source, startingLine, errorLine, errorMessage) @@ -1385,6 +1395,12 @@ WebInspector.reset = function() this.console.clearMessages(); } +WebInspector.resetProfilesPanel = function() +{ + if (WebInspector.panels.profiles) + WebInspector.panels.profiles.resetProfiles(); +} + WebInspector.bringToFront = function() { InspectorFrontendHost.bringToFront(); diff --git a/WebCore/inspector/front-end/utilities.js b/WebCore/inspector/front-end/utilities.js index bb19dbd..1312e5b 100644 --- a/WebCore/inspector/front-end/utilities.js +++ b/WebCore/inspector/front-end/utilities.js @@ -328,6 +328,63 @@ Element.prototype.offsetRelativeToWindow = function(targetWindow) return elementOffset; } +KeyboardEvent.prototype.__defineGetter__("data", function() +{ + // Emulate "data" attribute from DOM 3 TextInput event. + // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data + switch (this.type) { + case "keypress": + if (!this.ctrlKey && !this.metaKey) + return String.fromCharCode(this.charCode); + else + return ""; + case "keydown": + case "keyup": + if (!this.ctrlKey && !this.metaKey && !this.altKey) + return String.fromCharCode(this.which); + else + return ""; + } +}); + +Text.prototype.select = function(start, end) +{ + start = start || 0; + end = end || this.textContent.length; + + if (start < 0) + start = end + start; + + var selection = window.getSelection(); + selection.removeAllRanges(); + var range = document.createRange(); + range.setStart(this, start); + range.setEnd(this, end); + selection.addRange(range); + return this; +} + +Element.prototype.__defineGetter__("selectionLeftOffset", function() { + // Calculate selection offset relative to the current element. + + var selection = window.getSelection(); + if (!selection.containsNode(this, true)) + return null; + + var leftOffset = selection.anchorOffset; + var node = selection.anchorNode; + + while (node !== this) { + while (node.previousSibling) { + node = node.previousSibling; + leftOffset += node.textContent.length; + } + node = node.parentNode; + } + + return leftOffset; +}); + Node.prototype.isWhitespace = isNodeWhitespace; Node.prototype.displayName = nodeDisplayName; Node.prototype.isAncestor = function(node) @@ -672,6 +729,12 @@ Array.prototype.keySet = function() return keys; } +Array.convert = function(list) +{ + // Cast array-like object to an array. + return Array.prototype.slice.call(list); +} + function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction) { // indexOf returns (-lowerBound - 1). Taking (-result - 1) works out to lowerBound. |