2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "JavaScriptDebugServer.h"
32 #include "DOMWindow.h"
34 #include "JSDOMWindow.h"
35 #include "JavaScriptDebugListener.h"
42 typedef JavaScriptDebugServer::ListenerSet ListenerSet;
44 JavaScriptDebugServer& JavaScriptDebugServer::shared()
46 static JavaScriptDebugServer server;
50 JavaScriptDebugServer::JavaScriptDebugServer()
51 : m_callingListeners(false)
55 JavaScriptDebugServer::~JavaScriptDebugServer()
57 deleteAllValues(m_pageListenersMap);
60 void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener)
63 Page::setDebuggerForAllPages(this);
65 m_listeners.add(listener);
68 void JavaScriptDebugServer::removeListener(JavaScriptDebugListener* listener)
70 m_listeners.remove(listener);
72 Page::setDebuggerForAllPages(0);
75 void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener, Page* page)
77 ASSERT_ARG(page, page);
80 Page::setDebuggerForAllPages(this);
82 pair<PageListenersMap::iterator, bool> result = m_pageListenersMap.add(page, 0);
84 result.first->second = new ListenerSet;
85 ListenerSet* listeners = result.first->second;
87 listeners->add(listener);
90 void JavaScriptDebugServer::removeListener(JavaScriptDebugListener* listener, Page* page)
92 ASSERT_ARG(page, page);
94 PageListenersMap::iterator it = m_pageListenersMap.find(page);
95 if (it == m_pageListenersMap.end())
98 ListenerSet* listeners = it->second;
100 listeners->remove(listener);
102 if (listeners->isEmpty()) {
103 m_pageListenersMap.remove(it);
108 Page::setDebuggerForAllPages(0);
111 void JavaScriptDebugServer::pageCreated(Page* page)
116 page->setDebugger(this);
119 static void dispatchDidParseSource(const ListenerSet& listeners, ExecState* exec, const UString& source, int startingLineNumber, const UString& sourceURL, int sourceID)
121 Vector<JavaScriptDebugListener*> copy;
122 copyToVector(listeners, copy);
123 for (size_t i = 0; i < copy.size(); ++i)
124 copy[i]->didParseSource(exec, source, startingLineNumber, sourceURL, sourceID);
127 static void dispatchFailedToParseSource(const ListenerSet& listeners, ExecState* exec, const UString& source, int startingLineNumber, const UString& sourceURL, int errorLine, const UString& errorMessage)
129 Vector<JavaScriptDebugListener*> copy;
130 copyToVector(listeners, copy);
131 for (size_t i = 0; i < copy.size(); ++i)
132 copy[i]->failedToParseSource(exec, source, startingLineNumber, sourceURL, errorLine, errorMessage);
135 static Page* toPage(ExecState* exec)
137 ASSERT_ARG(exec, exec);
139 JSDOMWindow* window = toJSDOMWindow(exec->dynamicGlobalObject());
142 return window->impl()->frame()->page();
145 bool JavaScriptDebugServer::sourceParsed(ExecState* exec, int sourceID, const UString& sourceURL, const UString& source, int startingLineNumber, int errorLine, const UString& errorMessage)
147 if (m_callingListeners)
150 Page* page = toPage(exec);
154 m_callingListeners = true;
156 ASSERT(hasListeners());
158 bool isError = errorLine != -1;
160 if (!m_listeners.isEmpty()) {
162 dispatchFailedToParseSource(m_listeners, exec, source, startingLineNumber, sourceURL, errorLine, errorMessage);
164 dispatchDidParseSource(m_listeners, exec, source, startingLineNumber, sourceURL, sourceID);
167 if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) {
168 ASSERT(!pageListeners->isEmpty());
170 dispatchFailedToParseSource(*pageListeners, exec, source, startingLineNumber, sourceURL, errorLine, errorMessage);
172 dispatchDidParseSource(*pageListeners, exec, source, startingLineNumber, sourceURL, sourceID);
175 m_callingListeners = false;
179 static void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptDebugServer::JavaScriptExecutionCallback callback, ExecState* exec, int sourceID, int lineNumber)
181 Vector<JavaScriptDebugListener*> copy;
182 copyToVector(listeners, copy);
183 for (size_t i = 0; i < copy.size(); ++i)
184 (copy[i]->*callback)(exec, sourceID, lineNumber);
187 void JavaScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, ExecState* exec, int sourceID, int lineNumber)
189 if (m_callingListeners)
192 Page* page = toPage(exec);
196 m_callingListeners = true;
198 ASSERT(hasListeners());
200 WebCore::dispatchFunctionToListeners(m_listeners, callback, exec, sourceID, lineNumber);
201 if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) {
202 ASSERT(!pageListeners->isEmpty());
203 WebCore::dispatchFunctionToListeners(*pageListeners, callback, exec, sourceID, lineNumber);
206 m_callingListeners = false;
209 bool JavaScriptDebugServer::callEvent(ExecState* exec, int sourceID, int lineNumber, JSObject*, const List&)
211 dispatchFunctionToListeners(&JavaScriptDebugListener::didEnterCallFrame, exec, sourceID, lineNumber);
215 bool JavaScriptDebugServer::atStatement(ExecState* exec, int sourceID, int firstLine, int)
217 dispatchFunctionToListeners(&JavaScriptDebugListener::willExecuteStatement, exec, sourceID, firstLine);
221 bool JavaScriptDebugServer::returnEvent(ExecState* exec, int sourceID, int lineNumber, JSObject*)
223 dispatchFunctionToListeners(&JavaScriptDebugListener::willLeaveCallFrame, exec, sourceID, lineNumber);
227 bool JavaScriptDebugServer::exception(ExecState* exec, int sourceID, int lineNumber, JSValue*)
229 dispatchFunctionToListeners(&JavaScriptDebugListener::exceptionWasRaised, exec, sourceID, lineNumber);
233 } // namespace WebCore