diff options
Diffstat (limited to 'WebCore/inspector')
39 files changed, 1090 insertions, 1824 deletions
diff --git a/WebCore/inspector/InspectorBackend.cpp b/WebCore/inspector/InspectorBackend.cpp index ae2596a..1eb10e8 100644 --- a/WebCore/inspector/InspectorBackend.cpp +++ b/WebCore/inspector/InspectorBackend.cpp @@ -30,10 +30,6 @@ #include "config.h" #include "InspectorBackend.h" -#if ENABLE(DATABASE) -#include "Database.h" -#endif - #include "Element.h" #include "Frame.h" #include "FrameLoader.h" @@ -41,13 +37,8 @@ #include "InspectorClient.h" #include "InspectorController.h" #include "InspectorDOMAgent.h" -#include "InspectorFrontend.h" #include "InspectorResource.h" -#if ENABLE(DOM_STORAGE) -#include "Storage.h" -#endif - #if ENABLE(JAVASCRIPT_DEBUGGER) #include "JavaScriptCallFrame.h" #include "JavaScriptDebugServer.h" @@ -148,10 +139,10 @@ bool InspectorBackend::addSourceToFrame(const String& mimeType, const String& so return true; } -void InspectorBackend::clearMessages(bool clearUI) +void InspectorBackend::clearMessages() { if (m_inspectorController) - m_inspectorController->clearConsoleMessages(clearUI); + m_inspectorController->clearConsoleMessages(); } void InspectorBackend::toggleNodeSearch() @@ -191,10 +182,10 @@ bool InspectorBackend::searchingForNode() return false; } -void InspectorBackend::loaded() +void InspectorBackend::loaded(bool enableDOMAgent) { if (m_inspectorController) - m_inspectorController->scriptObjectReady(); + m_inspectorController->scriptObjectReady(enableDOMAgent); } void InspectorBackend::enableResourceTracking(bool always) @@ -364,10 +355,10 @@ void InspectorBackend::stepOutOfFunctionInDebugger() #endif -void InspectorBackend::getChildNodes(long callId, long nodeId) +void InspectorBackend::getChildNodes(long callId, long elementId) { if (m_inspectorController) - m_inspectorController->domAgent()->getChildNodes(callId, nodeId); + m_inspectorController->domAgent()->getChildNodes(callId, elementId); } void InspectorBackend::setAttribute(long callId, long elementId, const String& name, const String& value) @@ -382,87 +373,16 @@ void InspectorBackend::removeAttribute(long callId, long elementId, const String m_inspectorController->domAgent()->removeAttribute(callId, elementId, name); } -void InspectorBackend::setTextNodeValue(long callId, long nodeId, const String& value) +void InspectorBackend::setTextNodeValue(long callId, long elementId, const String& value) { if (m_inspectorController) - m_inspectorController->domAgent()->setTextNodeValue(callId, nodeId, value); + m_inspectorController->domAgent()->setTextNodeValue(callId, elementId, value); } -void InspectorBackend::highlight(long nodeId) -{ - if (m_inspectorController) { - Node* node = m_inspectorController->domAgent()->nodeForId(nodeId); - if (node) - m_inspectorController->highlight(node); - } -} - -Node* InspectorBackend::nodeForId(long nodeId) +void InspectorBackend::highlight(Node* node) { if (m_inspectorController) - return m_inspectorController->domAgent()->nodeForId(nodeId); - return 0; + m_inspectorController->highlight(node); } -long InspectorBackend::idForNode(Node* node) -{ - if (m_inspectorController) - return m_inspectorController->domAgent()->idForNode(node); - return -1; -} - -ScriptValue InspectorBackend::wrapObject(const ScriptValue& object) -{ - if (m_inspectorController) - return m_inspectorController->wrapObject(object); - return ScriptValue(); -} - -ScriptValue InspectorBackend::unwrapObject(const String& objectId) -{ - if (m_inspectorController) - return m_inspectorController->unwrapObject(objectId); - return ScriptValue(); -} - -long InspectorBackend::pushNodePathToFrontend(Node* node, bool selectInUI) -{ - if (!m_inspectorController) - return 0; - if (!m_inspectorController->m_domAgent || !m_inspectorController->m_frontend) - return 0; - long id = m_inspectorController->m_domAgent->pushNodePathToFrontend(node); - if (selectInUI) - m_inspectorController->m_frontend->updateFocusedNode(id); - return id; -} - -void InspectorBackend::addNodesToSearchResult(const String& nodeIds) -{ - if (m_inspectorController && m_inspectorController->m_frontend) - m_inspectorController->m_frontend->addNodesToSearchResult(nodeIds); -} - -#if ENABLE(DATABASE) -void InspectorBackend::selectDatabase(Database* database) -{ - if (!m_inspectorController) - return; - if (!m_inspectorController->m_frontend) - return; - m_inspectorController->m_frontend->selectDatabase(database); -} -#endif - -#if ENABLE(DOM_STORAGE) -void InspectorBackend::selectDOMStorage(Storage* storage) -{ - if (!m_inspectorController) - return; - if (!m_inspectorController->m_frontend) - return; - m_inspectorController->m_frontend->selectDOMStorage(storage); -} -#endif - } // namespace WebCore diff --git a/WebCore/inspector/InspectorBackend.h b/WebCore/inspector/InspectorBackend.h index c40e1b9..daa16b4 100644 --- a/WebCore/inspector/InspectorBackend.h +++ b/WebCore/inspector/InspectorBackend.h @@ -38,12 +38,10 @@ namespace WebCore { class CachedResource; -class Database; class InspectorClient; class InspectorDOMAgent; class JavaScriptCallFrame; class Node; -class Storage; class InspectorBackend : public RefCounted<InspectorBackend> { @@ -71,7 +69,7 @@ public: void addResourceSourceToFrame(long identifier, Node* frame); bool addSourceToFrame(const String& mimeType, const String& source, Node* frame); - void clearMessages(bool clearUI); + void clearMessages(); void toggleNodeSearch(); @@ -84,7 +82,7 @@ public: bool searchingForNode(); - void loaded(); + void loaded(bool enableDOMAgent); void enableResourceTracking(bool always); void disableResourceTracking(bool always); @@ -125,25 +123,13 @@ public: void stepOutOfFunctionInDebugger(); #endif - void getChildNodes(long callId, long nodeId); + void getChildNodes(long callId, long elementId); void setAttribute(long callId, long elementId, const String& name, const String& value); void removeAttribute(long callId, long elementId, const String& name); - void setTextNodeValue(long callId, long nodeId, const String& value); + void setTextNodeValue(long callId, long elementId, const String& value); // Generic code called from custom implementations. - void highlight(long nodeId); - Node* nodeForId(long nodeId); - long idForNode(Node* node); - ScriptValue wrapObject(const ScriptValue& object); - ScriptValue unwrapObject(const String& objectId); - long pushNodePathToFrontend(Node* node, bool selectInUI); - void addNodesToSearchResult(const String& nodeIds); -#if ENABLE(DATABASE) - void selectDatabase(Database* database); -#endif -#if ENABLE(DOM_STORAGE) - void selectDOMStorage(Storage* storage); -#endif + void highlight(Node* node); private: InspectorBackend(InspectorController* inspectorController, InspectorClient* client); diff --git a/WebCore/inspector/InspectorBackend.idl b/WebCore/inspector/InspectorBackend.idl index 942819e..bae1f26 100644 --- a/WebCore/inspector/InspectorBackend.idl +++ b/WebCore/inspector/InspectorBackend.idl @@ -35,14 +35,14 @@ module core { GenerateConstructor ] InspectorBackend { void hideDOMNodeHighlight(); - [Custom] void highlightDOMNode(in long nodeId); - void loaded(); + [Custom] void highlightDOMNode(in Node node); + void loaded(in boolean enableDOMAgent); void windowUnloading(); void attach(); void detach(); void closeWindow(); - void clearMessages(in boolean clearUI); + void clearMessages(); void toggleNodeSearch(); boolean isWindowVisible(); @@ -68,9 +68,6 @@ module core { void disableResourceTracking(in boolean always); void storeLastActivePanel(in DOMString panelName); - [Custom] Array cookies(); - [Custom] void deleteCookie(in DOMString cookieName); - #if defined(ENABLE_JAVASCRIPT_DEBUGGER) && ENABLE_JAVASCRIPT_DEBUGGER boolean debuggerEnabled(); void enableDebugger(in boolean always); @@ -100,23 +97,9 @@ module core { [Custom] Array profiles(); #endif - void getChildNodes(in long callId, in long nodeId); + void getChildNodes(in long callId, in long elementId); void setAttribute(in long callId, in long elementId, in DOMString name, in DOMString value); void removeAttribute(in long callId, in long elementId, in DOMString name); - void setTextNodeValue(in long callId, in long nodeId, in DOMString value); - - // Called from InjectedScript. - [Custom] DOMObject nodeForId(in long nodeId); - [Custom] long idForNode(in DOMObject node); - [Custom] long wrapObject(in DOMObject object); - [Custom] DOMObject unwrapObject(in long objectId); - [Custom] int pushNodePathToFrontend(in DOMObject node, in boolean selectInUI); - void addNodesToSearchResult(in DOMString nodeIds); -#if defined(ENABLE_DATABASE) && ENABLE_DATABASE - [Custom] void selectDatabase(in DOMObject database); -#endif -#if defined(ENABLE_DOM_STORAGE) && ENABLE_DOM_STORAGE - [Custom] void selectDOMStorage(in DOMObject storage); -#endif + void setTextNodeValue(in long callId, in long elementId, in DOMString value); }; -} + } diff --git a/WebCore/inspector/InspectorController.cpp b/WebCore/inspector/InspectorController.cpp index 3035d4e..c3351e5 100644 --- a/WebCore/inspector/InspectorController.cpp +++ b/WebCore/inspector/InspectorController.cpp @@ -61,9 +61,7 @@ #include "ResourceRequest.h" #include "ResourceResponse.h" #include "ScriptCallStack.h" -#include "ScriptFunctionCall.h" #include "ScriptObject.h" -#include "ScriptObjectQuarantine.h" #include "ScriptString.h" #include "SecurityOrigin.h" #include "Settings.h" @@ -127,7 +125,6 @@ InspectorController::InspectorController(Page* page, InspectorClient* client) , m_resourceTrackingEnabled(false) , m_resourceTrackingSettingsLoaded(false) , m_inspectorBackend(InspectorBackend::create(this, client)) - , m_lastBoundObjectId(1) #if ENABLE(JAVASCRIPT_DEBUGGER) , m_debuggerEnabled(false) , m_attachDebuggerWhenShown(false) @@ -273,8 +270,7 @@ void InspectorController::focusNode() ASSERT(m_frontend); ASSERT(m_nodeToFocus); - long id = m_domAgent->pushNodePathToFrontend(m_nodeToFocus.get()); - m_frontend->updateFocusedNode(id); + m_frontend->updateFocusedNode(m_nodeToFocus.get()); m_nodeToFocus = 0; } @@ -382,15 +378,12 @@ void InspectorController::addConsoleMessage(ScriptState* scriptState, ConsoleMes m_previousMessage->addToConsole(m_frontend.get()); } -void InspectorController::clearConsoleMessages(bool clearUI) +void InspectorController::clearConsoleMessages() { deleteAllValues(m_consoleMessages); m_consoleMessages.clear(); m_previousMessage = 0; m_groupLevel = 0; - m_idToConsoleObject.clear(); - if (clearUI && m_frontend) - m_frontend->clearConsoleMessages(); } void InspectorController::startGroup(MessageSource source, ScriptCallStack* callStack) @@ -499,6 +492,14 @@ void InspectorController::handleMousePressOnNode(Node* node) inspect(node); } +void InspectorController::inspectedWindowScriptObjectCleared(Frame* frame) +{ + if (!enabled() || !m_frontend) + return; + + m_frontend->inspectedWindowScriptObjectCleared(frame); +} + void InspectorController::windowScriptObjectAvailable() { if (!m_page || !enabled()) @@ -510,7 +511,7 @@ void InspectorController::windowScriptObjectAvailable() ScriptGlobalObject::set(m_scriptState, "InspectorController", m_inspectorBackend.get()); } -void InspectorController::scriptObjectReady() +void InspectorController::scriptObjectReady(bool enableDOMAgent) { ASSERT(m_scriptState); if (!m_scriptState) @@ -519,10 +520,9 @@ void InspectorController::scriptObjectReady() ScriptObject webInspectorObj; if (!ScriptGlobalObject::get(m_scriptState, "WebInspector", webInspectorObj)) return; - ScriptObject injectedScriptObj; - if (!ScriptGlobalObject::get(m_scriptState, "InjectedScript", injectedScriptObj)) - return; - setFrontendProxyObject(m_scriptState, webInspectorObj, injectedScriptObj); + setFrontendProxyObject(m_scriptState, webInspectorObj); + if (enableDOMAgent) + m_domAgent = new InspectorDOMAgent(m_frontend.get()); #if ENABLE(JAVASCRIPT_DEBUGGER) Setting debuggerEnabled = setting(debuggerEnabledSettingName); @@ -539,12 +539,9 @@ void InspectorController::scriptObjectReady() m_client->inspectorWindowObjectCleared(); } -void InspectorController::setFrontendProxyObject(ScriptState* scriptState, ScriptObject webInspectorObj, ScriptObject injectedScriptObj) +void InspectorController::setFrontendProxyObject(ScriptState* scriptState, ScriptObject webInspectorObj) { - m_scriptState = scriptState; - m_injectedScriptObj = injectedScriptObj; - m_frontend.set(new InspectorFrontend(this, scriptState, webInspectorObj)); - m_domAgent = new InspectorDOMAgent(m_frontend.get()); + m_frontend.set(new InspectorFrontend(scriptState, webInspectorObj)); } void InspectorController::show() @@ -598,8 +595,10 @@ void InspectorController::close() closeWindow(); m_frontend.set(0); - m_injectedScriptObj = ScriptObject(); - m_domAgent = 0; + if (m_domAgent) { + m_domAgent->setDocument(0); + m_domAgent = 0; + } m_scriptState = 0; } @@ -650,8 +649,8 @@ void InspectorController::populateScriptObjects() (*it)->bind(m_frontend.get()); #endif - if (m_domAgent->setDocument(m_inspectedPage->mainFrame()->document())) - resetInjectedScript(); + if (m_domAgent) + m_domAgent->setDocument(m_inspectedPage->mainFrame()->document()); m_frontend->populateInterface(); } @@ -707,7 +706,7 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) if (loader->frame() == m_inspectedPage->mainFrame()) { m_client->inspectedURLChanged(loader->url().string()); - clearConsoleMessages(false); + clearConsoleMessages(); m_times.clear(); m_counts.clear(); @@ -726,7 +725,7 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) if (windowVisible()) { resetScriptObjects(); - if (!loader->frameLoader()->isLoadingFromCachedPage()) { + if (!loader->isLoadingFromCachedPage()) { ASSERT(m_mainResource && m_mainResource->isSameLoader(loader)); // We don't add the main resource until its load is committed. This is // needed to keep the load for a user-entered URL from showing up in the @@ -741,8 +740,8 @@ void InspectorController::didCommitLoad(DocumentLoader* loader) } } - if (m_domAgent && m_domAgent->setDocument(m_inspectedPage->mainFrame()->document())) - resetInjectedScript(); + if (m_domAgent) + m_domAgent->setDocument(m_inspectedPage->mainFrame()->document()); } for (Frame* frame = loader->frame(); frame; frame = frame->tree()->traverseNext(loader->frame())) @@ -860,7 +859,7 @@ void InspectorController::identifierForInitialRequest(unsigned long identifier, addResource(resource.get()); - if (windowVisible() && loader->frameLoader()->isLoadingFromCachedPage() && resource == m_mainResource) + if (windowVisible() && loader->isLoadingFromCachedPage() && resource == m_mainResource) resource->createScriptObject(m_frontend.get()); } @@ -1479,34 +1478,4 @@ InspectorController::SpecialPanels InspectorController::specialPanelForJSName(co return ElementsPanel; } -ScriptValue InspectorController::wrapObject(const ScriptValue& quarantinedObject) -{ - if (quarantinedObject.isObject()) { - long id = m_lastBoundObjectId++; - String objectId = String::format("object#%ld", id); - m_idToConsoleObject.set(objectId, quarantinedObject); - - ScriptFunctionCall function(m_scriptState, m_injectedScriptObj, "createProxyObject"); - function.appendArgument(quarantinedObject); - function.appendArgument(objectId); - ScriptValue wrapper = function.call(); - return wrapper; - } - return quarantinedObject; -} - -ScriptValue InspectorController::unwrapObject(const String& objectId) -{ - HashMap<String, ScriptValue>::iterator it = m_idToConsoleObject.find(objectId); - if (it != m_idToConsoleObject.end()) - return it->second; - return ScriptValue(); -} - -void InspectorController::resetInjectedScript() -{ - ScriptFunctionCall function(m_scriptState, m_injectedScriptObj, "reset"); - function.call(); -} - } // namespace WebCore diff --git a/WebCore/inspector/InspectorController.h b/WebCore/inspector/InspectorController.h index 6a31deb..632b0ce 100644 --- a/WebCore/inspector/InspectorController.h +++ b/WebCore/inspector/InspectorController.h @@ -31,9 +31,7 @@ #include "Console.h" #include "PlatformString.h" -#include "ScriptObject.h" #include "ScriptState.h" -#include "ScriptValue.h" #include "StringHash.h" #include "Timer.h" @@ -62,6 +60,7 @@ class HitTestResult; class InspectorClient; class InspectorDOMAgent; class JavaScriptCallFrame; +class StorageArea; class KURL; class Node; class Page; @@ -69,9 +68,9 @@ struct ResourceRequest; class ResourceResponse; class ResourceError; class ScriptCallStack; +class ScriptObject; class ScriptString; class SharedBuffer; -class StorageArea; class ConsoleMessage; class InspectorDatabaseResource; @@ -188,7 +187,7 @@ public: void addMessageToConsole(MessageSource, MessageType, MessageLevel, ScriptCallStack*); void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned lineNumber, const String& sourceID); - void clearConsoleMessages(bool clearUI); + void clearConsoleMessages(); const Vector<ConsoleMessage*>& consoleMessages() const { return m_consoleMessages; } void attachWindow(); @@ -199,9 +198,10 @@ public: void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); void handleMousePressOnNode(Node*); + void inspectedWindowScriptObjectCleared(Frame*); void windowScriptObjectAvailable(); - void setFrontendProxyObject(ScriptState* state, ScriptObject webInspectorObj, ScriptObject injectedScriptObj = ScriptObject()); + void setFrontendProxyObject(ScriptState* state, ScriptObject object); void populateScriptObjects(); void resetScriptObjects(); @@ -279,7 +279,7 @@ private: #endif // Following are used from InspectorBackend and internally. - void scriptObjectReady(); + void scriptObjectReady(bool enableDOMAgent); void moveWindowBy(float x, float y) const; void setAttachedWindow(bool); void setAttachedWindowHeight(unsigned height); @@ -287,15 +287,6 @@ private: void closeWindow(); InspectorDOMAgent* domAgent() { return m_domAgent.get(); } - friend class InspectorFrontend; - // Following are used from InspectorFrontend only. We don't want to expose them to the - // rest of the InspectorController clients. - // TODO: extract these into a separate interface. - ScriptValue wrapObject(const ScriptValue& object); - ScriptValue unwrapObject(const String& objectId); - - void resetInjectedScript(); - #if ENABLE(JAVASCRIPT_DEBUGGER) void startUserInitiatedProfilingSoon(); void toggleRecordButton(bool); @@ -323,7 +314,6 @@ private: InspectorClient* m_client; RefPtr<InspectorDOMAgent> m_domAgent; - ScriptObject m_injectedScriptObj; Page* m_page; RefPtr<Node> m_nodeToFocus; RefPtr<InspectorResource> m_mainResource; @@ -353,8 +343,6 @@ private: OwnPtr<InspectorFrontend> m_frontend; RefPtr<InspectorBackend> m_inspectorBackend; #endif - HashMap<String, ScriptValue> m_idToConsoleObject; - long m_lastBoundObjectId; #if ENABLE(JAVASCRIPT_DEBUGGER) bool m_debuggerEnabled; bool m_attachDebuggerWhenShown; diff --git a/WebCore/inspector/InspectorDOMAgent.cpp b/WebCore/inspector/InspectorDOMAgent.cpp index 8a081f7..f222239 100644 --- a/WebCore/inspector/InspectorDOMAgent.cpp +++ b/WebCore/inspector/InspectorDOMAgent.cpp @@ -31,7 +31,6 @@ #include "InspectorDOMAgent.h" #include "AtomicString.h" -#include "ContainerNode.h" #include "DOMWindow.h" #include "Document.h" #include "Event.h" @@ -64,11 +63,10 @@ InspectorDOMAgent::~InspectorDOMAgent() setDocument(0); } -bool InspectorDOMAgent::setDocument(Document* doc) +void InspectorDOMAgent::setDocument(Document* doc) { if (doc == mainFrameDocument()) - return false; - discardBindings(); + return; ListHashSet<RefPtr<Document> > copy = m_documents; for (ListHashSet<RefPtr<Document> >::iterator it = copy.begin(); it != copy.end(); ++it) @@ -79,10 +77,11 @@ bool InspectorDOMAgent::setDocument(Document* doc) if (doc) { startListening(doc); if (doc->documentElement()) { - pushDocumentToFrontend(); + pushDocumentElementToFrontend(); } + } else { + discardBindings(); } - return true; } void InspectorDOMAgent::startListening(Document* doc) @@ -95,7 +94,6 @@ void InspectorDOMAgent::startListening(Document* doc) doc->addEventListener(eventNames().DOMNodeRemovedEvent, this, false); doc->addEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, true); doc->addEventListener(eventNames().DOMAttrModifiedEvent, this, false); - doc->addEventListener(eventNames().loadEvent, this, true); m_documents.add(doc); } @@ -109,7 +107,6 @@ void InspectorDOMAgent::stopListening(Document* doc) doc->removeEventListener(eventNames().DOMNodeRemovedEvent, this, false); doc->removeEventListener(eventNames().DOMNodeRemovedFromDocumentEvent, this, true); doc->removeEventListener(eventNames().DOMAttrModifiedEvent, this, false); - doc->removeEventListener(eventNames().loadEvent, this, true); m_documents.remove(doc); } @@ -172,25 +169,7 @@ void InspectorDOMAgent::handleEvent(Event* event, bool) } else if (type == eventNames().DOMContentLoadedEvent) { // Re-push document once it is loaded. discardBindings(); - pushDocumentToFrontend(); - } else if (type == eventNames().loadEvent) { - long frameOwnerId = idForNode(node); - if (!frameOwnerId) - return; - - if (!m_childrenRequested.contains(frameOwnerId)) { - // No children are mapped yet -> only notify on changes of hasChildren. - m_frontend->hasChildrenUpdated(frameOwnerId, true); - } else { - // Re-add frame owner element together with its new children. - long parentId = idForNode(innerParentNode(node)); - m_frontend->childNodeRemoved(parentId, frameOwnerId); - long prevId = idForNode(innerPreviousSibling(node)); - ScriptObject value = buildObjectForNode(node, 0); - m_frontend->childNodeInserted(parentId, prevId, value); - // Invalidate children requested flag for the element. - m_childrenRequested.remove(m_childrenRequested.find(frameOwnerId)); - } + pushDocumentElementToFrontend(); } } @@ -220,24 +199,25 @@ void InspectorDOMAgent::unbind(Node* node) } } -void InspectorDOMAgent::pushDocumentToFrontend() +void InspectorDOMAgent::pushDocumentElementToFrontend() { - Document* document = mainFrameDocument(); - if (!m_nodeToId.contains(document)) - m_frontend->setDocument(buildObjectForNode(document, 2)); + Element* docElem = mainFrameDocument()->documentElement(); + if (!m_nodeToId.contains(docElem)) + m_frontend->setDocumentElement(buildObjectForNode(docElem, 0)); } -void InspectorDOMAgent::pushChildNodesToFrontend(long nodeId) +void InspectorDOMAgent::pushChildNodesToFrontend(long elementId) { - Node* node = nodeForId(nodeId); - if (!node || (node->nodeType() != Node::ELEMENT_NODE && node->nodeType() != Node::DOCUMENT_NODE)) + Node* node = nodeForId(elementId); + if (!node || (node->nodeType() != Node::ELEMENT_NODE)) return; - if (m_childrenRequested.contains(nodeId)) + if (m_childrenRequested.contains(elementId)) return; - ScriptArray children = buildArrayForContainerChildren(node, 1); - m_childrenRequested.add(nodeId); - m_frontend->setChildNodes(nodeId, children); + Element* element = static_cast<Element*>(node); + ScriptArray children = buildArrayForElementChildren(element, 1); + m_childrenRequested.add(elementId); + m_frontend->setChildNodes(elementId, children); } void InspectorDOMAgent::discardBindings() @@ -249,9 +229,6 @@ void InspectorDOMAgent::discardBindings() Node* InspectorDOMAgent::nodeForId(long id) { - if (!id) - return 0; - HashMap<long, Node*>::iterator it = m_idToNode.find(id); if (it != m_idToNode.end()) return it->second; @@ -268,9 +245,9 @@ long InspectorDOMAgent::idForNode(Node* node) return 0; } -void InspectorDOMAgent::getChildNodes(long callId, long nodeId) +void InspectorDOMAgent::getChildNodes(long callId, long elementId) { - pushChildNodesToFrontend(nodeId); + pushChildNodesToFrontend(elementId); m_frontend->didGetChildNodes(callId); } @@ -279,25 +256,25 @@ long InspectorDOMAgent::pushNodePathToFrontend(Node* nodeToPush) ASSERT(nodeToPush); // Invalid input // If we are sending information to the client that is currently being created. Send root node first. - pushDocumentToFrontend(); + pushDocumentElementToFrontend(); // Return id in case the node is known. long result = idForNode(nodeToPush); if (result) return result; - Node* node = innerParentNode(nodeToPush); - ASSERT(node); // Node is detached or is a document itself + Element* element = innerParentElement(nodeToPush); + ASSERT(element); // Node is detached or is a document itself - Vector<Node*> path; - while (node && !idForNode(node)) { - path.append(node); - node = innerParentNode(node); + Vector<Element*> path; + while (element && !idForNode(element)) { + path.append(element); + element = innerParentElement(element); } // element is known to the client - ASSERT(node); - path.append(node); + ASSERT(element); + path.append(element); for (int i = path.size() - 1; i >= 0; --i) { long nodeId = idForNode(path.at(i)); ASSERT(nodeId); @@ -332,9 +309,9 @@ void InspectorDOMAgent::removeAttribute(long callId, long elementId, const Strin } } -void InspectorDOMAgent::setTextNodeValue(long callId, long nodeId, const String& value) +void InspectorDOMAgent::setTextNodeValue(long callId, long elementId, const String& value) { - Node* node = nodeForId(nodeId); + Node* node = nodeForId(elementId); if (node && (node->nodeType() == Node::TEXT_NODE)) { Text* text_node = static_cast<Text*>(node); ExceptionCode ec = 0; @@ -359,9 +336,9 @@ ScriptObject InspectorDOMAgent::buildObjectForNode(Node* node, int depth) nodeValue = node->nodeValue(); break; case Node::ATTRIBUTE_NODE: + case Node::DOCUMENT_NODE: case Node::DOCUMENT_FRAGMENT_NODE: break; - case Node::DOCUMENT_NODE: case Node::ELEMENT_NODE: default: nodeName = node->nodeName(); @@ -376,11 +353,10 @@ ScriptObject InspectorDOMAgent::buildObjectForNode(Node* node, int depth) if (node->nodeType() == Node::ELEMENT_NODE) { Element* element = static_cast<Element*>(node); value.set("attributes", buildArrayForElementAttributes(element)); - } - if (node->nodeType() == Node::ELEMENT_NODE || node->nodeType() == Node::DOCUMENT_NODE) { - int nodeCount = innerChildNodeCount(node); + int nodeCount = innerChildNodeCount(element); value.set("childNodeCount", nodeCount); - ScriptArray children = buildArrayForContainerChildren(node, depth); + + ScriptArray children = buildArrayForElementChildren(element, depth); if (children.length() > 0) value.set("children", children); } @@ -405,14 +381,14 @@ ScriptArray InspectorDOMAgent::buildArrayForElementAttributes(Element* element) return attributesValue; } -ScriptArray InspectorDOMAgent::buildArrayForContainerChildren(Node* container, int depth) +ScriptArray InspectorDOMAgent::buildArrayForElementChildren(Element* element, int depth) { ScriptArray children = m_frontend->newScriptArray(); if (depth == 0) { int index = 0; // Special case the_only text child. - if (innerChildNodeCount(container) == 1) { - Node *child = innerFirstChild(container); + if (innerChildNodeCount(element) == 1) { + Node *child = innerFirstChild(element); if (child->nodeType() == Node::TEXT_NODE) children.set(index++, buildObjectForNode(child, 0)); } @@ -422,7 +398,7 @@ ScriptArray InspectorDOMAgent::buildArrayForContainerChildren(Node* container, i } int index = 0; - for (Node *child = innerFirstChild(container); child; child = innerNextSibling(child)) + for (Node *child = innerFirstChild(element); child; child = innerNextSibling(child)) children.set(index++, buildObjectForNode(child, depth)); return children; } @@ -470,12 +446,12 @@ int InspectorDOMAgent::innerChildNodeCount(Node* node) return count; } -Node* InspectorDOMAgent::innerParentNode(Node* node) +Element* InspectorDOMAgent::innerParentElement(Node* node) { - Node* parent = node->parentNode(); - if (parent && parent->nodeType() == Node::DOCUMENT_NODE) - return static_cast<Document*>(parent)->ownerElement(); - return parent; + Element* element = node->parentElement(); + if (!element) + return node->ownerDocument()->ownerElement(); + return element; } bool InspectorDOMAgent::isWhitespace(Node* node) diff --git a/WebCore/inspector/InspectorDOMAgent.h b/WebCore/inspector/InspectorDOMAgent.h index 67b2be8..28c3a22 100644 --- a/WebCore/inspector/InspectorDOMAgent.h +++ b/WebCore/inspector/InspectorDOMAgent.h @@ -42,7 +42,6 @@ #include <wtf/RefPtr.h> namespace WebCore { - class ContainerNode; class Element; class Event; class Document; @@ -57,13 +56,13 @@ namespace WebCore { ~InspectorDOMAgent(); // Methods called from the frontend. - void getChildNodes(long callId, long nodeId); + void getChildNodes(long callId, long elementId); void setAttribute(long callId, long elementId, const String& name, const String& value); void removeAttribute(long callId, long elementId, const String& name); - void setTextNodeValue(long callId, long nodeId, const String& value); + void setTextNodeValue(long callId, long elementId, const String& value); // Methods called from the InspectorController. - bool setDocument(Document* document); + void setDocument(Document* document); Node* nodeForId(long nodeId); long idForNode(Node* node); @@ -78,12 +77,12 @@ namespace WebCore { long bind(Node* node); void unbind(Node* node); - void pushDocumentToFrontend(); - void pushChildNodesToFrontend(long nodeId); + void pushDocumentElementToFrontend(); + void pushChildNodesToFrontend(long elementId); ScriptObject buildObjectForNode(Node* node, int depth); - ScriptArray buildArrayForElementAttributes(Element* element); - ScriptArray buildArrayForContainerChildren(Node* container, int depth); + ScriptArray buildArrayForElementAttributes(Element* elemen); + ScriptArray buildArrayForElementChildren(Element* element, int depth); // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. @@ -91,7 +90,7 @@ namespace WebCore { Node* innerNextSibling(Node* node); Node* innerPreviousSibling(Node* node); int innerChildNodeCount(Node* node); - Node* innerParentNode(Node* node); + Element* innerParentElement(Node* node); bool isWhitespace(Node* node); Document* mainFrameDocument(); diff --git a/WebCore/inspector/InspectorDOMStorageResource.cpp b/WebCore/inspector/InspectorDOMStorageResource.cpp index 1e56742..03db649 100644 --- a/WebCore/inspector/InspectorDOMStorageResource.cpp +++ b/WebCore/inspector/InspectorDOMStorageResource.cpp @@ -64,7 +64,7 @@ void InspectorDOMStorageResource::bind(InspectorFrontend* frontend) ScriptObject jsonObject = frontend->newScriptObject(); ScriptObject domStorage; - if (!getQuarantinedScriptObject(m_domStorage.get(), domStorage)) + if (!getQuarantinedScriptObject(m_frame.get(), m_domStorage.get(), domStorage)) return; jsonObject.set("domStorage", domStorage); jsonObject.set("host", m_frame->document()->securityOrigin()->host()); diff --git a/WebCore/inspector/InspectorFrontend.cpp b/WebCore/inspector/InspectorFrontend.cpp index f745ae3..af65fb4 100644 --- a/WebCore/inspector/InspectorFrontend.cpp +++ b/WebCore/inspector/InspectorFrontend.cpp @@ -32,7 +32,7 @@ #include "ConsoleMessage.h" #include "Frame.h" -#include "InspectorController.h" +#include "InspectorController.h" // TODO(pfeldman): Extract SpecialPanels to remove include. #include "Node.h" #include "ScriptFunctionCall.h" #include "ScriptObject.h" @@ -49,9 +49,8 @@ namespace WebCore { -InspectorFrontend::InspectorFrontend(InspectorController* inspectorController, ScriptState* scriptState, ScriptObject webInspector) - : m_inspectorController(inspectorController) - , m_scriptState(scriptState) +InspectorFrontend::InspectorFrontend(ScriptState* scriptState, ScriptObject webInspector) + : m_scriptState(scriptState) , m_webInspector(webInspector) { } @@ -80,17 +79,12 @@ void InspectorFrontend::addMessageToConsole(const ScriptObject& messageObj, cons function->appendArgument(frames[i]); } else if (!wrappedArguments.isEmpty()) { for (unsigned i = 0; i < wrappedArguments.size(); ++i) - function->appendArgument(m_inspectorController->wrapObject(wrappedArguments[i])); + function->appendArgument(wrappedArguments[i]); } else function->appendArgument(message); function->call(); } -void InspectorFrontend::clearConsoleMessages() -{ - callSimpleFunction("clearConsoleMessages"); -} - bool InspectorFrontend::addResource(long long identifier, const ScriptObject& resourceObj) { OwnPtr<ScriptFunctionCall> function(newFunctionCall("addResource")); @@ -118,10 +112,14 @@ void InspectorFrontend::removeResource(long long identifier) function->call(); } -void InspectorFrontend::updateFocusedNode(long long nodeId) +void InspectorFrontend::updateFocusedNode(Node* node) { + ScriptObject quarantinedNode; + if (!getQuarantinedScriptObject(node, quarantinedNode)) + return; + OwnPtr<ScriptFunctionCall> function(newFunctionCall("updateFocusedNode")); - function->appendArgument(nodeId); + function->appendArgument(quarantinedNode); function->call(); } @@ -132,6 +130,17 @@ void InspectorFrontend::setAttachedWindow(bool attached) function->call(); } +void InspectorFrontend::inspectedWindowScriptObjectCleared(Frame* frame) +{ + ScriptObject domWindow; + if (!getQuarantinedScriptObject(frame->domWindow(), domWindow)) + return; + + OwnPtr<ScriptFunctionCall> function(newFunctionCall("inspectedWindowCleared")); + function->appendArgument(domWindow); + function->call(); +} + void InspectorFrontend::showPanel(int panel) { const char* showFunctionName; @@ -277,9 +286,9 @@ bool InspectorFrontend::addDOMStorage(const ScriptObject& domStorageObj) } #endif -void InspectorFrontend::setDocument(const ScriptObject& root) +void InspectorFrontend::setDocumentElement(const ScriptObject& root) { - OwnPtr<ScriptFunctionCall> function(newFunctionCall("setDocument")); + OwnPtr<ScriptFunctionCall> function(newFunctionCall("setDocumentElement")); function->appendArgument(root); function->call(); } @@ -340,37 +349,6 @@ void InspectorFrontend::didApplyDomChange(int callId, bool success) function->call(); } -#if ENABLE(DATABASE) -void InspectorFrontend::selectDatabase(Database* database) -{ - OwnPtr<ScriptFunctionCall> function(newFunctionCall("selectDatabase")); - ScriptObject quarantinedObject; - if (!getQuarantinedScriptObject(database, quarantinedObject)) - return; - function->appendArgument(quarantinedObject); - function->call(); -} -#endif - -#if ENABLE(DOM_STORAGE) -void InspectorFrontend::selectDOMStorage(Storage* storage) -{ - OwnPtr<ScriptFunctionCall> function(newFunctionCall("selectDOMStorage")); - ScriptObject quarantinedObject; - if (!getQuarantinedScriptObject(storage, quarantinedObject)) - return; - function->appendArgument(quarantinedObject); - function->call(); -} -#endif - -void InspectorFrontend::addNodesToSearchResult(const String& nodeIds) -{ - OwnPtr<ScriptFunctionCall> function(newFunctionCall("addNodesToSearchResult")); - function->appendArgument(nodeIds); - function->call(); -} - PassOwnPtr<ScriptFunctionCall> InspectorFrontend::newFunctionCall(const String& functionName) { ScriptFunctionCall* function = new ScriptFunctionCall(m_scriptState, m_webInspector, "dispatch"); diff --git a/WebCore/inspector/InspectorFrontend.h b/WebCore/inspector/InspectorFrontend.h index 600f50a..7a48b62 100644 --- a/WebCore/inspector/InspectorFrontend.h +++ b/WebCore/inspector/InspectorFrontend.h @@ -45,32 +45,28 @@ namespace JSC { namespace WebCore { class ConsoleMessage; - class Database; - class Frame; - class InspectorController; class InspectorResource; class Node; class ScriptFunctionCall; class ScriptString; - class Storage; class InspectorFrontend { public: - InspectorFrontend(InspectorController* inspectorController, ScriptState*, ScriptObject webInspector); + InspectorFrontend(ScriptState*, ScriptObject webInspector); ~InspectorFrontend(); ScriptArray newScriptArray(); ScriptObject newScriptObject(); void addMessageToConsole(const ScriptObject& messageObj, const Vector<ScriptString>& frames, const Vector<ScriptValue> wrappedArguments, const String& message); - void clearConsoleMessages(); - + bool addResource(long long identifier, const ScriptObject& resourceObj); bool updateResource(long long identifier, const ScriptObject& resourceObj); void removeResource(long long identifier); - void updateFocusedNode(long long nodeId); + void updateFocusedNode(Node* node); void setAttachedWindow(bool attached); + void inspectedWindowScriptObjectCleared(Frame* frame); void showPanel(int panel); void populateInterface(); void reset(); @@ -94,15 +90,13 @@ namespace WebCore { #if ENABLE(DATABASE) bool addDatabase(const ScriptObject& dbObj); - void selectDatabase(Database* database); #endif #if ENABLE(DOM_STORAGE) bool addDOMStorage(const ScriptObject& domStorageObj); - void selectDOMStorage(Storage* storage); #endif - void setDocument(const ScriptObject& root); + void setDocumentElement(const ScriptObject& root); void setChildNodes(int parentId, const ScriptArray& nodes); void hasChildrenUpdated(int id, bool newValue); void childNodeInserted(int parentId, int prevId, const ScriptObject& node); @@ -111,12 +105,9 @@ namespace WebCore { void didGetChildNodes(int callId); void didApplyDomChange(int callId, bool success); - void addNodesToSearchResult(const String& nodeIds); - private: PassOwnPtr<ScriptFunctionCall> newFunctionCall(const String& functionName); void callSimpleFunction(const String& functionName); - InspectorController* m_inspectorController; ScriptState* m_scriptState; ScriptObject m_webInspector; }; diff --git a/WebCore/inspector/JavaScriptDebugServer.cpp b/WebCore/inspector/JavaScriptDebugServer.cpp index 008ddd3..10eff26 100644 --- a/WebCore/inspector/JavaScriptDebugServer.cpp +++ b/WebCore/inspector/JavaScriptDebugServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,8 +45,10 @@ #include "ScrollView.h" #include "Widget.h" #include "ScriptController.h" +#include <runtime/CollectorHeapIterator.h> #include <debugger/DebuggerCallFrame.h> #include <runtime/JSLock.h> +#include <parser/Parser.h> #include <wtf/MainThread.h> #include <wtf/StdLibExtras.h> #include <wtf/UnusedParam.h> @@ -297,6 +299,8 @@ void JavaScriptDebugServer::sourceParsed(ExecState* exec, const SourceCode& sour m_callingListeners = true; + ASSERT(hasListeners()); + bool isError = errorLine != -1; if (hasGlobalListeners()) { @@ -551,7 +555,60 @@ void JavaScriptDebugServer::recompileAllJSFunctionsSoon() void JavaScriptDebugServer::recompileAllJSFunctions(Timer<JavaScriptDebugServer>*) { JSLock lock(SilenceAssertionsOnly); - Debugger::recompileAllJSFunctions(JSDOMWindow::commonJSGlobalData()); + JSGlobalData* globalData = JSDOMWindow::commonJSGlobalData(); + + // If JavaScript is running, it's not safe to recompile, since we'll end + // up throwing away code that is live on the stack. + ASSERT(!globalData->dynamicGlobalObject); + if (globalData->dynamicGlobalObject) + return; + + Vector<ProtectedPtr<JSFunction> > functions; + Heap::iterator heapEnd = globalData->heap.primaryHeapEnd(); + for (Heap::iterator it = globalData->heap.primaryHeapBegin(); it != heapEnd; ++it) { + if ((*it)->isObject(&JSFunction::info)) { + JSFunction* function = static_cast<JSFunction*>(*it); + if (!function->isHostFunction()) + functions.append(function); + } + } + + typedef HashMap<RefPtr<FunctionBodyNode>, RefPtr<FunctionBodyNode> > FunctionBodyMap; + typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap; + + FunctionBodyMap functionBodies; + SourceProviderMap sourceProviders; + + size_t size = functions.size(); + for (size_t i = 0; i < size; ++i) { + JSFunction* function = functions[i]; + + FunctionBodyNode* oldBody = function->body(); + pair<FunctionBodyMap::iterator, bool> result = functionBodies.add(oldBody, 0); + if (!result.second) { + function->setBody(result.first->second.get()); + continue; + } + + ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec(); + const SourceCode& sourceCode = oldBody->source(); + + RefPtr<FunctionBodyNode> newBody = globalData->parser->parse<FunctionBodyNode>(exec, 0, sourceCode); + ASSERT(newBody); + newBody->finishParsing(oldBody->copyParameters(), oldBody->parameterCount()); + + result.first->second = newBody; + function->setBody(newBody.release()); + + if (hasListeners() && function->scope().globalObject()->debugger() == this) + sourceProviders.add(sourceCode.provider(), exec); + } + + // Call sourceParsed() after reparsing all functions because it will execute + // JavaScript in the inspector. + SourceProviderMap::const_iterator end = sourceProviders.end(); + for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter) + sourceParsed((*iter).second, SourceCode((*iter).first), -1, 0); } void JavaScriptDebugServer::didAddListener(Page* page) 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) |