Add WebCore::JavaScriptDebugServer and use it from WebKit/win
authoraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Mar 2008 20:51:35 +0000 (20:51 +0000)
committeraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Mar 2008 20:51:35 +0000 (20:51 +0000)
WebCore:

        Add JavaScriptDebugServer

        This class is a singleton which allows one or more
        JavaScriptDebugListeners to receive callbacks during JavaScript
        execution.

        Right now all listeners receive callbacks for all Pages in the
        process. Eventually we will want to support listeners registering for
        callbacks for specific Pages (e.g., the Inspector will want to listen
        for execution in just the Page it's inspecting).

        Pages notify the JavaScriptDebugServer when they are created so that
        it can install itself as the Page's debugger.

        Reviewed by Darin.

        * GNUMakefile.am: Added new files to project.
        * WebCore.pro: Ditto.
        * WebCore.vcproj/WebCore.vcproj: Ditto.
        * WebCore.xcodeproj/project.pbxproj: Ditto.
        * WebCoreSources.bkl: Ditto.
        * page/JavaScriptDebugListener.h: Added.
        * page/JavaScriptDebugServer.cpp: Added.
        (WebCore::toFrame):
        (WebCore::JavaScriptDebugServer::shared):
        (WebCore::JavaScriptDebugServer::JavaScriptDebugServer):
        (WebCore::JavaScriptDebugServer::~JavaScriptDebugServer):
        (WebCore::JavaScriptDebugServer::addListener): Registers as the
        debugger for all Pages if we're adding our first listener.
        (WebCore::JavaScriptDebugServer::removeListener): Deregisters as the
        debugger for all Pages if we're removing our last listner.
        (WebCore::JavaScriptDebugServer::pageCreated): Registers as the
        debugger for the newly created Page if we have any listeners.
        (WebCore::dispatchDidParseSource): Helper function.
        (WebCore::dispatchFailedToParseSource): Ditto.
        (WebCore::JavaScriptDebugServer::sourceParsed): Call
        dispatchDidParseSource or dispatchFailedToParseSource depending on
        whether there was an error or not.
        (WebCore::JavaScriptDebugServer::dispatchFunctionToListeners): Calls
        the passed-in JavaScriptExecutionCallback on each listener, guarding
        against re-entry.
        (WebCore::JavaScriptDebugServer::callEvent): Dispatch didEnterCallFrame.
        (WebCore::JavaScriptDebugServer::atStatement): Dispatch willExecuteStatement.
        (WebCore::JavaScriptDebugServer::returnEvent): Dispatch willLeaveCallFrame.
        (WebCore::JavaScriptDebugServer::exception): Dispatch exceptionWasRaised.
        * page/JavaScriptDebugServer.h: Added.
        * page/Page.cpp:
        (WebCore::Page::Page): Tell the shared JavaScriptDebugServer we were
        created so it can register as our debugger if needed.

WebKit/win:

        Change WebScriptDebugServer to use WebCore::JavaScriptDebugServer

        WebScriptDebugServer is now a JavaScriptDebugListener.

        Reviewed by Darin.

        * WebScriptDebugServer.cpp:
        (WebScriptDebugServer::WebScriptDebugServer): Removed initialization
        of m_callingListeners member.
        (WebScriptDebugServer::addListener): Register as a listener with
        JavaScriptDebugServer if we've just added our first listener.
        (WebScriptDebugServer::removeListener): Deregister as a listener with
        JavaScriptDebugServer if we've just removed our last listener.
        (WebScriptDebugServer::didParseSource): Added. Code came from the old
        sourceParsed method. Removed m_callingListeners code because
        JavaScriptDebugServer guards against re-entry for us.
        (WebScriptDebugServer::failedToParseSource): Ditto.
        (WebScriptDebugServer::didEnterCallFrame): Ditto for callEvent.
        (WebScriptDebugServer::willExecuteStatement): Ditto for atStatement.
        (WebScriptDebugServer::willLeaveCallFrame): Ditto for
        willLeaveCallFrame.
        (WebScriptDebugServer::exceptionWasRaised): Ditto for exception.
        * WebScriptDebugServer.h: Changed to inherit from
        WebCore::JavaScriptDebugListener.
        * WebView.cpp:
        (WebView::initWithFrame): Removed call to
        WebScriptDebugServer::pageCreated. This is now handled by WebCore.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@30874 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/WebCoreSources.bkl
WebCore/page/JavaScriptDebugListener.h [new file with mode: 0644]
WebCore/page/JavaScriptDebugServer.cpp [new file with mode: 0644]
WebCore/page/JavaScriptDebugServer.h [new file with mode: 0644]
WebCore/page/Page.cpp
WebKit/win/ChangeLog
WebKit/win/WebScriptDebugServer.cpp
WebKit/win/WebScriptDebugServer.h
WebKit/win/WebView.cpp

index 42526f0..5962757 100644 (file)
@@ -1,3 +1,55 @@
+2008-03-06  Adam Roben  <aroben@apple.com>
+
+        Add JavaScriptDebugServer
+
+        This class is a singleton which allows one or more
+        JavaScriptDebugListeners to receive callbacks during JavaScript
+        execution.
+
+        Right now all listeners receive callbacks for all Pages in the
+        process. Eventually we will want to support listeners registering for
+        callbacks for specific Pages (e.g., the Inspector will want to listen
+        for execution in just the Page it's inspecting).
+
+        Pages notify the JavaScriptDebugServer when they are created so that
+        it can install itself as the Page's debugger.
+
+        Reviewed by Darin.
+
+        * GNUMakefile.am: Added new files to project.
+        * WebCore.pro: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * WebCoreSources.bkl: Ditto.
+        * page/JavaScriptDebugListener.h: Added.
+        * page/JavaScriptDebugServer.cpp: Added.
+        (WebCore::toFrame):
+        (WebCore::JavaScriptDebugServer::shared):
+        (WebCore::JavaScriptDebugServer::JavaScriptDebugServer):
+        (WebCore::JavaScriptDebugServer::~JavaScriptDebugServer):
+        (WebCore::JavaScriptDebugServer::addListener): Registers as the
+        debugger for all Pages if we're adding our first listener.
+        (WebCore::JavaScriptDebugServer::removeListener): Deregisters as the
+        debugger for all Pages if we're removing our last listner.
+        (WebCore::JavaScriptDebugServer::pageCreated): Registers as the
+        debugger for the newly created Page if we have any listeners.
+        (WebCore::dispatchDidParseSource): Helper function.
+        (WebCore::dispatchFailedToParseSource): Ditto.
+        (WebCore::JavaScriptDebugServer::sourceParsed): Call
+        dispatchDidParseSource or dispatchFailedToParseSource depending on
+        whether there was an error or not.
+        (WebCore::JavaScriptDebugServer::dispatchFunctionToListeners): Calls
+        the passed-in JavaScriptExecutionCallback on each listener, guarding
+        against re-entry.
+        (WebCore::JavaScriptDebugServer::callEvent): Dispatch didEnterCallFrame.
+        (WebCore::JavaScriptDebugServer::atStatement): Dispatch willExecuteStatement.
+        (WebCore::JavaScriptDebugServer::returnEvent): Dispatch willLeaveCallFrame.
+        (WebCore::JavaScriptDebugServer::exception): Dispatch exceptionWasRaised.
+        * page/JavaScriptDebugServer.h: Added.
+        * page/Page.cpp:
+        (WebCore::Page::Page): Tell the shared JavaScriptDebugServer we were
+        created so it can register as our debugger if needed.
+
 2008-03-07  Darin Adler  <darin@apple.com>
 
         Reviewed by Brady.
index 1594d57..16f2e07 100644 (file)
@@ -801,6 +801,7 @@ webcore_sources += \
        WebCore/page/FrameView.cpp \
        WebCore/page/History.cpp \
        WebCore/page/InspectorController.cpp \
+       WebCore/page/JavaScriptDebugServer.cpp \
        WebCore/page/MouseEventWithHitTestResults.cpp \
        WebCore/page/Page.cpp \
        WebCore/page/PageGroup.cpp \
index 37c2729..a88f40b 100644 (file)
@@ -740,6 +740,7 @@ SOURCES += \
     page/FrameView.cpp \
     page/History.cpp \
     page/InspectorController.cpp \
+    page/JavaScriptDebugServer.cpp \
     page/MouseEventWithHitTestResults.cpp \
     page/Page.cpp \
     page/PageGroup.cpp \
index c96fe2a..db41ad4 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="Windows-1252"?>\r
+<?xml version="1.0" encoding="windows-1251"?>\r
 <VisualStudioProject\r
        ProjectType="Visual C++"\r
        Version="8.00"\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\page\JavaScriptDebugListener.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\page\JavaScriptDebugServer.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\page\JavaScriptDebugServer.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\page\MouseEventWithHitTestResults.cpp"\r
                                >\r
                        </File>\r
index 249203f..3c55f35 100644 (file)
                BCFE8E320A02A1D30009E61D /* WebCoreTextRenderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCFE8E310A02A1D30009E61D /* WebCoreTextRenderer.mm */; };
                C0294DF30D5A6FD800CC7D6B /* UserStyleSheetLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0294DF10D5A6FD800CC7D6B /* UserStyleSheetLoader.cpp */; };
                C0294DF40D5A6FD800CC7D6B /* UserStyleSheetLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = C0294DF20D5A6FD800CC7D6B /* UserStyleSheetLoader.h */; };
+               C02B14C20D81E02A00D8A970 /* JavaScriptDebugListener.h in Headers */ = {isa = PBXBuildFile; fileRef = C02B14BF0D81E02A00D8A970 /* JavaScriptDebugListener.h */; };
+               C02B14C30D81E02A00D8A970 /* JavaScriptDebugServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C02B14C00D81E02A00D8A970 /* JavaScriptDebugServer.cpp */; };
+               C02B14C40D81E02A00D8A970 /* JavaScriptDebugServer.h in Headers */ = {isa = PBXBuildFile; fileRef = C02B14C10D81E02A00D8A970 /* JavaScriptDebugServer.h */; };
                C6D74AD509AA282E000B0A52 /* ModifySelectionListLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = C6D74AD309AA282E000B0A52 /* ModifySelectionListLevel.h */; };
                C6D74AE409AA290A000B0A52 /* ModifySelectionListLevel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.cpp */; };
                D05CED290A40BB2C00C5AF38 /* FormatBlockCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D05CED270A40BB2C00C5AF38 /* FormatBlockCommand.cpp */; };
                BE983D95052A2E0A00892D85 /* WebCoreKeyboardUIMode.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreKeyboardUIMode.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                C0294DF10D5A6FD800CC7D6B /* UserStyleSheetLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserStyleSheetLoader.cpp; sourceTree = "<group>"; };
                C0294DF20D5A6FD800CC7D6B /* UserStyleSheetLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserStyleSheetLoader.h; sourceTree = "<group>"; };
+               C02B14BF0D81E02A00D8A970 /* JavaScriptDebugListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptDebugListener.h; sourceTree = "<group>"; };
+               C02B14C00D81E02A00D8A970 /* JavaScriptDebugServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JavaScriptDebugServer.cpp; sourceTree = "<group>"; };
+               C02B14C10D81E02A00D8A970 /* JavaScriptDebugServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptDebugServer.h; sourceTree = "<group>"; };
                C6D74AD309AA282E000B0A52 /* ModifySelectionListLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModifySelectionListLevel.h; sourceTree = "<group>"; };
                C6D74AE309AA290A000B0A52 /* ModifySelectionListLevel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModifySelectionListLevel.cpp; sourceTree = "<group>"; };
                D05CED270A40BB2C00C5AF38 /* FormatBlockCommand.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FormatBlockCommand.cpp; sourceTree = "<group>"; };
                                06693DB70BFBA2F400216072 /* InspectorClient.h */,
                                06693DB80BFBA2F400216072 /* InspectorController.cpp */,
                                06693DB90BFBA2F400216072 /* InspectorController.h */,
+                               C02B14BF0D81E02A00D8A970 /* JavaScriptDebugListener.h */,
+                               C02B14C00D81E02A00D8A970 /* JavaScriptDebugServer.cpp */,
+                               C02B14C10D81E02A00D8A970 /* JavaScriptDebugServer.h */,
                                93EB355E09E37FD600F43799 /* MouseEventWithHitTestResults.cpp */,
                                935C476209AC4CE600A6AAB4 /* MouseEventWithHitTestResults.h */,
                                65FEA86809833ADE00BED4AB /* Page.cpp */,
                                1A569D230D7E2B82007C3983 /* runtime_object.h in Headers */,
                                1A569D250D7E2B82007C3983 /* runtime_root.h in Headers */,
                                BC6932740D7E293900AE44D1 /* JSDOMWindowBase.h in Headers */,
+                               C02B14C20D81E02A00D8A970 /* JavaScriptDebugListener.h in Headers */,
+                               C02B14C40D81E02A00D8A970 /* JavaScriptDebugServer.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                1A569D220D7E2B82007C3983 /* runtime_object.cpp in Sources */,
                                1A569D240D7E2B82007C3983 /* runtime_root.cpp in Sources */,
                                BC6932730D7E293900AE44D1 /* JSDOMWindowBase.cpp in Sources */,
+                               C02B14C30D81E02A00D8A970 /* JavaScriptDebugServer.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 7bad662..fecacae 100644 (file)
@@ -569,6 +569,7 @@ This file contains the list of files needed to build WebCore.
         page/FrameView.cpp
         page/History.cpp
         page/InspectorController.cpp
+        page/JavaScriptDebugServer.cpp
         page/MouseEventWithHitTestResults.cpp
         page/Page.cpp
         page/PageGroup.cpp
diff --git a/WebCore/page/JavaScriptDebugListener.h b/WebCore/page/JavaScriptDebugListener.h
new file mode 100644 (file)
index 0000000..4d7cbb6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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
+ * 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.
+ */
+
+#ifndef JavaScriptDebugListener_h
+#define JavaScriptDebugListener_h
+
+namespace KJS {
+    class ExecState;
+}
+
+namespace WebCore {
+
+    class Frame;
+    class Page;
+    class String;
+
+    class JavaScriptDebugListener {
+    public:
+        virtual ~JavaScriptDebugListener() { }
+
+        virtual void didParseSource(KJS::ExecState*, const String& source, int startingLineNumber, const String& sourceURL, int sourceID) = 0;
+        virtual void failedToParseSource(KJS::ExecState*, const String& source, int startingLineNumber, const String& sourceURL, int errorLine, const String& errorMessage) = 0;
+        virtual void didEnterCallFrame(KJS::ExecState*, int sourceID, int lineNumber) = 0;
+        virtual void willExecuteStatement(KJS::ExecState*, int sourceID, int lineNumber) = 0;
+        virtual void willLeaveCallFrame(KJS::ExecState*, int sourceID, int lineNumber) = 0;
+        virtual void exceptionWasRaised(KJS::ExecState*, int sourceID, int lineNumber) = 0;
+    };
+
+} // namespace WebCore
+
+#endif // JavaScriptDebugListener_h
diff --git a/WebCore/page/JavaScriptDebugServer.cpp b/WebCore/page/JavaScriptDebugServer.cpp
new file mode 100644 (file)
index 0000000..bd324aa
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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
+ * 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.
+ */
+
+#include "config.h"
+#include "JavaScriptDebugServer.h"
+
+#include "DOMWindow.h"
+#include "Frame.h"
+#include "JSDOMWindow.h"
+#include "JavaScriptDebugListener.h"
+#include "Page.h"
+
+using namespace KJS;
+
+namespace WebCore {
+
+typedef JavaScriptDebugServer::ListenerSet ListenerSet;
+
+JavaScriptDebugServer& JavaScriptDebugServer::shared()
+{
+    static JavaScriptDebugServer server;
+    return server;
+}
+
+JavaScriptDebugServer::JavaScriptDebugServer()
+    : m_callingListeners(false)
+{
+}
+
+JavaScriptDebugServer::~JavaScriptDebugServer()
+{
+}
+
+void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener)
+{
+    if (m_listeners.isEmpty())
+        Page::setDebuggerForAllPages(this);
+
+    m_listeners.add(listener);
+}
+
+void JavaScriptDebugServer::removeListener(JavaScriptDebugListener* listener)
+{
+    m_listeners.remove(listener);
+    if (m_listeners.isEmpty())
+        Page::setDebuggerForAllPages(0);
+}
+
+void JavaScriptDebugServer::pageCreated(Page* page)
+{
+    if (m_listeners.isEmpty())
+        return;
+
+    page->setDebugger(this);
+}
+
+static void dispatchDidParseSource(const ListenerSet& listeners, ExecState* state, const String& source, int startingLineNumber, const String& sourceURL, int sourceID)
+{
+    Vector<JavaScriptDebugListener*> copy;
+    copyToVector(listeners, copy);
+    for (size_t i = 0; i < copy.size(); ++i)
+        copy[i]->didParseSource(state, source, startingLineNumber, sourceURL, sourceID);
+}
+
+static void dispatchFailedToParseSource(const ListenerSet& listeners, ExecState* state, const String& source, int startingLineNumber, const String& sourceURL, int errorLine, const String& errorMessage)
+{
+    Vector<JavaScriptDebugListener*> copy;
+    copyToVector(listeners, copy);
+    for (size_t i = 0; i < copy.size(); ++i)
+        copy[i]->failedToParseSource(state, source, startingLineNumber, sourceURL, errorLine, errorMessage);
+}
+
+bool JavaScriptDebugServer::sourceParsed(ExecState* state, int sourceID, const UString& sourceURL, const UString& source, int startingLineNumber, int errorLine, const UString& errorMessage)
+{
+    if (m_callingListeners)
+        return true;
+    m_callingListeners = true;
+
+    ASSERT(!m_listeners.isEmpty());
+    if (errorLine == -1)
+        dispatchDidParseSource(m_listeners, state, source, startingLineNumber, sourceURL, sourceID);
+    else
+        dispatchFailedToParseSource(m_listeners, state, source, startingLineNumber, sourceURL, errorLine, errorMessage);
+
+    m_callingListeners = false;
+    return true;
+}
+
+void JavaScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, ExecState* state, int sourceID, int lineNumber)
+{
+    if (m_callingListeners)
+        return;
+    m_callingListeners = true;
+
+    ASSERT(!m_listeners.isEmpty());
+    Vector<JavaScriptDebugListener*> copy;
+    copyToVector(m_listeners, copy);
+    for (size_t i = 0; i < copy.size(); ++i)
+        (copy[i]->*callback)(state, sourceID, lineNumber);
+
+    m_callingListeners = false;
+}
+
+bool JavaScriptDebugServer::callEvent(ExecState* state, int sourceID, int lineNumber, JSObject*, const List&)
+{
+    dispatchFunctionToListeners(&JavaScriptDebugListener::didEnterCallFrame, state, sourceID, lineNumber);
+    return true;
+}
+
+bool JavaScriptDebugServer::atStatement(ExecState* state, int sourceID, int firstLine, int)
+{
+    dispatchFunctionToListeners(&JavaScriptDebugListener::willExecuteStatement, state, sourceID, firstLine);
+    return true;
+}
+
+bool JavaScriptDebugServer::returnEvent(ExecState* state, int sourceID, int lineNumber, JSObject*)
+{
+    dispatchFunctionToListeners(&JavaScriptDebugListener::willLeaveCallFrame, state, sourceID, lineNumber);
+    return true;
+}
+
+bool JavaScriptDebugServer::exception(ExecState* state, int sourceID, int lineNumber, JSValue*)
+{
+    dispatchFunctionToListeners(&JavaScriptDebugListener::exceptionWasRaised, state, sourceID, lineNumber);
+    return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/page/JavaScriptDebugServer.h b/WebCore/page/JavaScriptDebugServer.h
new file mode 100644 (file)
index 0000000..3301fd8
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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
+ * 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.
+ */
+
+#ifndef JavaScriptDebugServer_h
+#define JavaScriptDebugServer_h
+
+#include <kjs/debugger.h>
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+    class Frame;
+    class Page;
+    class JavaScriptDebugListener;
+
+    class JavaScriptDebugServer : KJS::Debugger {
+    public:
+        static JavaScriptDebugServer& shared();
+
+        void addListener(JavaScriptDebugListener*);
+        void removeListener(JavaScriptDebugListener*);
+
+        void pageCreated(Page*);
+
+        typedef HashSet<JavaScriptDebugListener*> ListenerSet;
+
+    private:
+        JavaScriptDebugServer();
+        ~JavaScriptDebugServer();
+
+        typedef void (JavaScriptDebugListener::*JavaScriptExecutionCallback)(KJS::ExecState*, int sourceID, int lineNumber);
+        void dispatchFunctionToListeners(JavaScriptExecutionCallback, KJS::ExecState*, int sourceID, int lineNumber);
+
+        virtual bool sourceParsed(KJS::ExecState*, int sourceID, const KJS::UString& sourceURL, const KJS::UString& source, int startingLineNumber, int errorLine, const KJS::UString& errorMsg);
+        virtual bool callEvent(KJS::ExecState*, int sourceID, int lineNumber, KJS::JSObject* function, const KJS::List& args);
+        virtual bool atStatement(KJS::ExecState*, int sourceID, int firstLine, int lastLine);
+        virtual bool returnEvent(KJS::ExecState*, int sourceID, int lineNumber, KJS::JSObject* function);
+        virtual bool exception(KJS::ExecState*, int sourceID, int lineNumber, KJS::JSValue* exception);
+
+        ListenerSet m_listeners;
+        bool m_callingListeners;
+    };
+
+} // namespace WebCore
+
+#endif // JavaScriptDebugServer_h
index 294e349..0eefc07 100644 (file)
@@ -34,6 +34,7 @@
 #include "FrameView.h"
 #include "HistoryItem.h"
 #include "InspectorController.h"
+#include "JavaScriptDebugServer.h"
 #include "Logging.h"
 #include "PageGroup.h"
 #include "ProgressTracker.h"
@@ -99,6 +100,8 @@ Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, Edi
     ASSERT(!allPages->contains(this));
     allPages->add(this);
 
+    JavaScriptDebugServer::shared().pageCreated(this);
+
 #ifndef NDEBUG
     ++PageCounter::count;
 #endif
index 123e0fb..fe2b92e 100644 (file)
@@ -1,3 +1,33 @@
+2008-03-06  Adam Roben  <aroben@apple.com>
+
+        Change WebScriptDebugServer to use WebCore::JavaScriptDebugServer
+
+        WebScriptDebugServer is now a JavaScriptDebugListener.
+
+        Reviewed by Darin.
+
+        * WebScriptDebugServer.cpp:
+        (WebScriptDebugServer::WebScriptDebugServer): Removed initialization
+        of m_callingListeners member.
+        (WebScriptDebugServer::addListener): Register as a listener with
+        JavaScriptDebugServer if we've just added our first listener.
+        (WebScriptDebugServer::removeListener): Deregister as a listener with
+        JavaScriptDebugServer if we've just removed our last listener.
+        (WebScriptDebugServer::didParseSource): Added. Code came from the old
+        sourceParsed method. Removed m_callingListeners code because
+        JavaScriptDebugServer guards against re-entry for us.
+        (WebScriptDebugServer::failedToParseSource): Ditto.
+        (WebScriptDebugServer::didEnterCallFrame): Ditto for callEvent.
+        (WebScriptDebugServer::willExecuteStatement): Ditto for atStatement.
+        (WebScriptDebugServer::willLeaveCallFrame): Ditto for
+        willLeaveCallFrame.
+        (WebScriptDebugServer::exceptionWasRaised): Ditto for exception.
+        * WebScriptDebugServer.h: Changed to inherit from
+        WebCore::JavaScriptDebugListener.
+        * WebView.cpp:
+        (WebView::initWithFrame): Removed call to
+        WebScriptDebugServer::pageCreated. This is now handled by WebCore.
+
 2008-03-06  Darin Adler  <darin@apple.com>
 
         Reviewed by Mitz.
index 0a4038a..ceb82e2 100644 (file)
@@ -33,7 +33,7 @@
 #pragma warning(push, 0)
 #include <WebCore/DOMWindow.h>
 #include <WebCore/JSDOMWindow.h>
-#include <WebCore/Page.h>
+#include <WebCore/JavaScriptDebugServer.h>
 #pragma warning(pop)
 #include <kjs/ExecState.h>
 #include <wtf/Assertions.h>
@@ -72,7 +72,6 @@ WebScriptDebugServer::WebScriptDebugServer()
     : m_refCount(0)
     , m_paused(false)
     , m_step(false)
-    , m_callingListeners(false)
 {
     gClassCount++;
 }
@@ -101,14 +100,6 @@ WebScriptDebugServer* WebScriptDebugServer::sharedWebScriptDebugServer()
     return server;
 }
 
-void WebScriptDebugServer::pageCreated(Page* page)
-{
-    ASSERT_ARG(page, page);
-
-    if (s_ListenerCount > 0)
-        page->setDebugger(sharedWebScriptDebugServer());
-}
-
 // IUnknown -------------------------------------------------------------------
 
 HRESULT STDMETHODCALLTYPE WebScriptDebugServer::QueryInterface(REFIID riid, void** ppvObject)
@@ -163,7 +154,7 @@ HRESULT STDMETHODCALLTYPE WebScriptDebugServer::addListener(
         return E_POINTER;
 
     if (!s_ListenerCount)
-        Page::setDebuggerForAllPages(sharedWebScriptDebugServer());
+        JavaScriptDebugServer::shared().addListener(this);
 
     ++s_ListenerCount;
     s_Listeners.add(listener);
@@ -187,7 +178,7 @@ HRESULT STDMETHODCALLTYPE WebScriptDebugServer::removeListener(
 
     ASSERT(s_ListenerCount >= 1);
     if (--s_ListenerCount == 0) {
-        Page::setDebuggerForAllPages(0);
+        JavaScriptDebugServer::shared().removeListener(this);
         resume();
     }
 
@@ -290,44 +281,34 @@ void WebScriptDebugServer::didLoadMainResourceForDataSource(IWebView* webView, I
         (**it).didLoadMainResourceForDataSource(webView, dataSource);
 }
 
-bool WebScriptDebugServer::sourceParsed(ExecState* exec, int sourceID, const UString& sourceURL,
-                  const UString& source, int startingLineNumber, int errorLine, const UString& /*errorMsg*/)
+void WebScriptDebugServer::didParseSource(ExecState* exec, const String& source, int startingLineNumber, const String& sourceURL, int sourceID)
 {
-    if (m_callingListeners)
-        return true;
+    BString bSource = source;
+    BString bSourceURL = sourceURL;
 
-    m_callingListeners = true;
-
-    if (listenerCount() <= 0)
-        return true;
-
-    BString bSource = String(source);
-    BString bSourceURL = String(sourceURL);
-    
     ListenerSet listenersCopy = s_Listeners;
     ListenerSet::iterator end = listenersCopy.end();
-    if (errorLine == -1) {
-        for (ListenerSet::iterator it = listenersCopy.begin(); it != end; ++it)
-            (**it).didParseSource(webView(exec), bSource, startingLineNumber, bSourceURL, sourceID, webFrame(exec));
-    } else {
-        // FIXME: the error var should be made with the information in the errorMsg.  It is not a simple
-        // UString to BSTR conversion there is some logic involved that I don't fully understand yet.
-        BString error(L"An Error Occurred.");
-        for (ListenerSet::iterator it = listenersCopy.begin(); it != end; ++it)
-            (**it).failedToParseSource(webView(exec), bSource, startingLineNumber, bSourceURL, error, webFrame(exec));
-    }
-
-    m_callingListeners = false;
-    return true;
+    for (ListenerSet::iterator it = listenersCopy.begin(); it != end; ++it)
+        (**it).didParseSource(webView(exec), bSource, startingLineNumber, bSourceURL, sourceID, webFrame(exec));
 }
 
-bool WebScriptDebugServer::callEvent(ExecState* exec, int sourceID, int lineNumber, JSObject* /*function*/, const List &/*args*/)
+void WebScriptDebugServer::failedToParseSource(ExecState* exec, const String& source, int startingLineNumber, const String& sourceURL, int errorLine, const String& errorMessage)
 {
-    if (m_callingListeners)
-        return true;
+    BString bSource = source;
+    BString bSourceURL = sourceURL;
 
-    m_callingListeners = true;
+    // FIXME: the error var should be made with the information in the errorMsg.  It is not a simple
+    // UString to BSTR conversion there is some logic involved that I don't fully understand yet.
+    BString error(L"An Error Occurred.");
 
+    ListenerSet listenersCopy = s_Listeners;
+    ListenerSet::iterator end = listenersCopy.end();
+    for (ListenerSet::iterator it = listenersCopy.begin(); it != end; ++it)
+        (**it).failedToParseSource(webView(exec), bSource, startingLineNumber, bSourceURL, error, webFrame(exec));
+}
+
+void WebScriptDebugServer::didEnterCallFrame(ExecState* exec, int sourceID, int lineNumber)
+{
     COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec));
     ListenerSet listenersCopy = s_Listeners;
     ListenerSet::iterator end = listenersCopy.end();
@@ -335,39 +316,21 @@ bool WebScriptDebugServer::callEvent(ExecState* exec, int sourceID, int lineNumb
         (**it).didEnterCallFrame(webView(exec), callFrame.get(), sourceID, lineNumber, webFrame(exec));
 
     suspendProcessIfPaused();
-
-    m_callingListeners = false;
-
-    return true;
 }
 
-bool WebScriptDebugServer::atStatement(ExecState* exec, int sourceID, int firstLine, int /*lastLine*/)
+void WebScriptDebugServer::willExecuteStatement(ExecState* exec, int sourceID, int lineNumber)
 {
-    if (m_callingListeners)
-        return true;
-
-    m_callingListeners = true;
-
     COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec));
     ListenerSet listenersCopy = s_Listeners;
     ListenerSet::iterator end = listenersCopy.end();
     for (ListenerSet::iterator it = listenersCopy.begin(); it != end; ++it)
-        (**it).willExecuteStatement(webView(exec), callFrame.get(), sourceID, firstLine, webFrame(exec));
+        (**it).willExecuteStatement(webView(exec), callFrame.get(), sourceID, lineNumber, webFrame(exec));
 
     suspendProcessIfPaused();
-
-    m_callingListeners = false;
-
-    return true;
 }
 
-bool WebScriptDebugServer::returnEvent(ExecState* exec, int sourceID, int lineNumber, JSObject* /*function*/)
+void WebScriptDebugServer::willLeaveCallFrame(ExecState* exec, int sourceID, int lineNumber)
 {
-    if (m_callingListeners)
-        return true;
-
-    m_callingListeners = true;
-
     COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec->callingExecState()));
     ListenerSet listenersCopy = s_Listeners;
     ListenerSet::iterator end = listenersCopy.end();
@@ -375,19 +338,10 @@ bool WebScriptDebugServer::returnEvent(ExecState* exec, int sourceID, int lineNu
         (**it).willLeaveCallFrame(webView(exec), callFrame.get(), sourceID, lineNumber, webFrame(exec));
 
     suspendProcessIfPaused();
-
-    m_callingListeners = false;
-
-    return true;
 }
 
-bool WebScriptDebugServer::exception(ExecState* exec, int sourceID, int lineNumber, JSValue* /*exception */)
+void WebScriptDebugServer::exceptionWasRaised(ExecState* exec, int sourceID, int lineNumber)
 {
-    if (m_callingListeners)
-        return true;
-
-    m_callingListeners = true;
-
     COMPtr<WebScriptCallFrame> callFrame(AdoptCOM, WebScriptCallFrame::createInstance(exec));
     ListenerSet listenersCopy = s_Listeners;
     ListenerSet::iterator end = listenersCopy.end();
@@ -395,10 +349,6 @@ bool WebScriptDebugServer::exception(ExecState* exec, int sourceID, int lineNumb
         (**it).exceptionWasRaised(webView(exec), callFrame.get(), sourceID, lineNumber, webFrame(exec));
 
     suspendProcessIfPaused();
-
-    m_callingListeners = false;
-
-    return true;
 }
 
 void WebScriptDebugServer::serverDidDie()
index 00f09b5..4c98501 100644 (file)
@@ -27,7 +27,9 @@
 #define WebScriptDebugServer_H
 
 #include "WebKit.h"
-#include <kjs/debugger.h>
+#pragma warning(push, 0)
+#include <WebCore/JavaScriptDebugListener.h>
+#pragma warning(pop)
 
 namespace WebCore {
     class Page;
@@ -35,13 +37,11 @@ namespace WebCore {
 
 interface IWebView;
 
-class WebScriptDebugServer : public IWebScriptDebugServer, KJS::Debugger {
+class WebScriptDebugServer : public IWebScriptDebugServer, WebCore::JavaScriptDebugListener {
 public:
     static WebScriptDebugServer* createInstance();
     static WebScriptDebugServer* sharedWebScriptDebugServer();
 
-    static void pageCreated(WebCore::Page*);
-
     // IUnknown
     virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
         /* [in] */ REFIID riid,
@@ -81,13 +81,13 @@ private:
 
     void suspendProcessIfPaused();
 
-    // KJS::Debugger
-    virtual bool sourceParsed(KJS::ExecState*, int sourceID, const KJS::UString& sourceURL,
-        const KJS::UString& source, int startingLineNumber, int errorLine, const KJS::UString& errorMsg);
-    virtual bool callEvent(KJS::ExecState*, int sourceID, int lineNumber, KJS::JSObject* function, const KJS::List& args);
-    virtual bool atStatement(KJS::ExecState*, int sourceID, int firstLine, int lastLine);
-    virtual bool returnEvent(KJS::ExecState*, int sourceID, int lineNumber, KJS::JSObject* function);
-    virtual bool exception(KJS::ExecState*, int sourceID, int lineNumber, KJS::JSValue* exception);
+    // JavaScriptDebugListener
+    virtual void didParseSource(KJS::ExecState*, const WebCore::String& source, int startingLineNumber, const WebCore::String& sourceURL, int sourceID);
+    virtual void failedToParseSource(KJS::ExecState*, const WebCore::String& source, int startingLineNumber, const WebCore::String& sourceURL, int errorLine, const WebCore::String& errorMessage);
+    virtual void didEnterCallFrame(KJS::ExecState*, int sourceID, int lineNumber);
+    virtual void willExecuteStatement(KJS::ExecState*, int sourceID, int lineNumber);
+    virtual void willLeaveCallFrame(KJS::ExecState*, int sourceID, int lineNumber);
+    virtual void exceptionWasRaised(KJS::ExecState*, int sourceID, int lineNumber);
 
     bool m_paused;
     bool m_step;
index 4702ef2..8c743ec 100644 (file)
@@ -47,7 +47,6 @@
 #include "WebMutableURLRequest.h"
 #include "WebNotificationCenter.h"
 #include "WebPreferences.h"
-#include "WebScriptDebugServer.h"
 #pragma warning( push, 0 )
 #include <CoreGraphics/CGContext.h>
 #include <WebCore/BString.h>
@@ -2059,8 +2058,6 @@ HRESULT STDMETHODCALLTYPE WebView::initWithFrame(
 
     m_page = new Page(new WebChromeClient(this), new WebContextMenuClient(this), new WebEditorClient(this), new WebDragClient(this), new WebInspectorClient(this));
 
-    WebScriptDebugServer::pageCreated(m_page);
-
     if (m_uiDelegate) {
         COMPtr<IWebUIDelegate2> uiDelegate2;
         if (SUCCEEDED(m_uiDelegate->QueryInterface(IID_IWebUIDelegate2, (void**)&uiDelegate2))) {