Add WebCore::JavaScriptDebugServer and use it from WebKit/win
[WebKit-https.git] / WebCore / page / JavaScriptDebugServer.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "JavaScriptDebugServer.h"
31
32 #include "DOMWindow.h"
33 #include "Frame.h"
34 #include "JSDOMWindow.h"
35 #include "JavaScriptDebugListener.h"
36 #include "Page.h"
37
38 using namespace KJS;
39
40 namespace WebCore {
41
42 typedef JavaScriptDebugServer::ListenerSet ListenerSet;
43
44 JavaScriptDebugServer& JavaScriptDebugServer::shared()
45 {
46     static JavaScriptDebugServer server;
47     return server;
48 }
49
50 JavaScriptDebugServer::JavaScriptDebugServer()
51     : m_callingListeners(false)
52 {
53 }
54
55 JavaScriptDebugServer::~JavaScriptDebugServer()
56 {
57 }
58
59 void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener)
60 {
61     if (m_listeners.isEmpty())
62         Page::setDebuggerForAllPages(this);
63
64     m_listeners.add(listener);
65 }
66
67 void JavaScriptDebugServer::removeListener(JavaScriptDebugListener* listener)
68 {
69     m_listeners.remove(listener);
70     if (m_listeners.isEmpty())
71         Page::setDebuggerForAllPages(0);
72 }
73
74 void JavaScriptDebugServer::pageCreated(Page* page)
75 {
76     if (m_listeners.isEmpty())
77         return;
78
79     page->setDebugger(this);
80 }
81
82 static void dispatchDidParseSource(const ListenerSet& listeners, ExecState* state, const String& source, int startingLineNumber, const String& sourceURL, int sourceID)
83 {
84     Vector<JavaScriptDebugListener*> copy;
85     copyToVector(listeners, copy);
86     for (size_t i = 0; i < copy.size(); ++i)
87         copy[i]->didParseSource(state, source, startingLineNumber, sourceURL, sourceID);
88 }
89
90 static void dispatchFailedToParseSource(const ListenerSet& listeners, ExecState* state, const String& source, int startingLineNumber, const String& sourceURL, int errorLine, const String& errorMessage)
91 {
92     Vector<JavaScriptDebugListener*> copy;
93     copyToVector(listeners, copy);
94     for (size_t i = 0; i < copy.size(); ++i)
95         copy[i]->failedToParseSource(state, source, startingLineNumber, sourceURL, errorLine, errorMessage);
96 }
97
98 bool JavaScriptDebugServer::sourceParsed(ExecState* state, int sourceID, const UString& sourceURL, const UString& source, int startingLineNumber, int errorLine, const UString& errorMessage)
99 {
100     if (m_callingListeners)
101         return true;
102     m_callingListeners = true;
103
104     ASSERT(!m_listeners.isEmpty());
105     if (errorLine == -1)
106         dispatchDidParseSource(m_listeners, state, source, startingLineNumber, sourceURL, sourceID);
107     else
108         dispatchFailedToParseSource(m_listeners, state, source, startingLineNumber, sourceURL, errorLine, errorMessage);
109
110     m_callingListeners = false;
111     return true;
112 }
113
114 void JavaScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, ExecState* state, int sourceID, int lineNumber)
115 {
116     if (m_callingListeners)
117         return;
118     m_callingListeners = true;
119
120     ASSERT(!m_listeners.isEmpty());
121     Vector<JavaScriptDebugListener*> copy;
122     copyToVector(m_listeners, copy);
123     for (size_t i = 0; i < copy.size(); ++i)
124         (copy[i]->*callback)(state, sourceID, lineNumber);
125
126     m_callingListeners = false;
127 }
128
129 bool JavaScriptDebugServer::callEvent(ExecState* state, int sourceID, int lineNumber, JSObject*, const List&)
130 {
131     dispatchFunctionToListeners(&JavaScriptDebugListener::didEnterCallFrame, state, sourceID, lineNumber);
132     return true;
133 }
134
135 bool JavaScriptDebugServer::atStatement(ExecState* state, int sourceID, int firstLine, int)
136 {
137     dispatchFunctionToListeners(&JavaScriptDebugListener::willExecuteStatement, state, sourceID, firstLine);
138     return true;
139 }
140
141 bool JavaScriptDebugServer::returnEvent(ExecState* state, int sourceID, int lineNumber, JSObject*)
142 {
143     dispatchFunctionToListeners(&JavaScriptDebugListener::willLeaveCallFrame, state, sourceID, lineNumber);
144     return true;
145 }
146
147 bool JavaScriptDebugServer::exception(ExecState* state, int sourceID, int lineNumber, JSValue*)
148 {
149     dispatchFunctionToListeners(&JavaScriptDebugListener::exceptionWasRaised, state, sourceID, lineNumber);
150     return true;
151 }
152
153 } // namespace WebCore