summaryrefslogtreecommitdiffstats
path: root/WebCore/inspector/JavaScriptDebugServer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/inspector/JavaScriptDebugServer.cpp')
-rw-r--r--WebCore/inspector/JavaScriptDebugServer.cpp617
1 files changed, 0 insertions, 617 deletions
diff --git a/WebCore/inspector/JavaScriptDebugServer.cpp b/WebCore/inspector/JavaScriptDebugServer.cpp
deleted file mode 100644
index ed9ae85..0000000
--- a/WebCore/inspector/JavaScriptDebugServer.cpp
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * 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 "EventLoop.h"
-#include "Frame.h"
-#include "FrameTree.h"
-#include "FrameView.h"
-#include "JSDOMWindowCustom.h"
-#include "JavaScriptCallFrame.h"
-#include "JavaScriptDebugListener.h"
-#include "Page.h"
-#include "PageGroup.h"
-#include "PausedTimeouts.h"
-#include "PluginView.h"
-#include "ScrollView.h"
-#include "Widget.h"
-#include "ScriptController.h"
-#include <runtime/CollectorHeapIterator.h>
-#include <debugger/DebuggerCallFrame.h>
-#include <runtime/JSLock.h>
-#include <kjs/Parser.h>
-#include <wtf/MainThread.h>
-#include <wtf/UnusedParam.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-typedef JavaScriptDebugServer::ListenerSet ListenerSet;
-
-JavaScriptDebugServer& JavaScriptDebugServer::shared()
-{
- static JavaScriptDebugServer server;
- return server;
-}
-
-JavaScriptDebugServer::JavaScriptDebugServer()
- : m_callingListeners(false)
- , m_pauseOnExceptions(false)
- , m_pauseOnNextStatement(false)
- , m_paused(false)
- , m_doneProcessingDebuggerEvents(true)
- , m_pauseOnCallFrame(0)
- , m_recompileTimer(this, &JavaScriptDebugServer::recompileAllJSFunctions)
-{
-}
-
-JavaScriptDebugServer::~JavaScriptDebugServer()
-{
- deleteAllValues(m_pageListenersMap);
- deleteAllValues(m_breakpoints);
- deleteAllValues(m_pausedTimeouts);
-}
-
-void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener)
-{
- ASSERT_ARG(listener, listener);
-
- m_listeners.add(listener);
-
- didAddListener(0);
-}
-
-void JavaScriptDebugServer::removeListener(JavaScriptDebugListener* listener)
-{
- ASSERT_ARG(listener, listener);
-
- m_listeners.remove(listener);
-
- didRemoveListener(0);
- if (!hasListeners())
- didRemoveLastListener();
-}
-
-void JavaScriptDebugServer::addListener(JavaScriptDebugListener* listener, Page* page)
-{
- ASSERT_ARG(listener, listener);
- ASSERT_ARG(page, page);
-
- pair<PageListenersMap::iterator, bool> result = m_pageListenersMap.add(page, 0);
- if (result.second)
- result.first->second = new ListenerSet;
-
- ListenerSet* listeners = result.first->second;
- listeners->add(listener);
-
- didAddListener(page);
-}
-
-void JavaScriptDebugServer::removeListener(JavaScriptDebugListener* listener, Page* page)
-{
- ASSERT_ARG(listener, listener);
- ASSERT_ARG(page, page);
-
- PageListenersMap::iterator it = m_pageListenersMap.find(page);
- if (it == m_pageListenersMap.end())
- return;
-
- ListenerSet* listeners = it->second;
- listeners->remove(listener);
- if (listeners->isEmpty()) {
- m_pageListenersMap.remove(it);
- delete listeners;
- }
-
- didRemoveListener(page);
- if (!hasListeners())
- didRemoveLastListener();
-}
-
-void JavaScriptDebugServer::pageCreated(Page* page)
-{
- ASSERT_ARG(page, page);
-
- if (!hasListenersInterestedInPage(page))
- return;
- page->setDebugger(this);
-}
-
-bool JavaScriptDebugServer::hasListenersInterestedInPage(Page* page)
-{
- ASSERT_ARG(page, page);
-
- if (hasGlobalListeners())
- return true;
-
- return m_pageListenersMap.contains(page);
-}
-
-void JavaScriptDebugServer::addBreakpoint(intptr_t sourceID, unsigned lineNumber)
-{
- HashSet<unsigned>* lines = m_breakpoints.get(sourceID);
- if (!lines) {
- lines = new HashSet<unsigned>;
- m_breakpoints.set(sourceID, lines);
- }
-
- lines->add(lineNumber);
-}
-
-void JavaScriptDebugServer::removeBreakpoint(intptr_t sourceID, unsigned lineNumber)
-{
- HashSet<unsigned>* lines = m_breakpoints.get(sourceID);
- if (!lines)
- return;
-
- lines->remove(lineNumber);
-
- if (!lines->isEmpty())
- return;
-
- m_breakpoints.remove(sourceID);
- delete lines;
-}
-
-bool JavaScriptDebugServer::hasBreakpoint(intptr_t sourceID, unsigned lineNumber) const
-{
- HashSet<unsigned>* lines = m_breakpoints.get(sourceID);
- if (!lines)
- return false;
- return lines->contains(lineNumber);
-}
-
-void JavaScriptDebugServer::clearBreakpoints()
-{
- deleteAllValues(m_breakpoints);
- m_breakpoints.clear();
-}
-
-void JavaScriptDebugServer::setPauseOnExceptions(bool pause)
-{
- m_pauseOnExceptions = pause;
-}
-
-void JavaScriptDebugServer::pauseProgram()
-{
- m_pauseOnNextStatement = true;
-}
-
-void JavaScriptDebugServer::continueProgram()
-{
- if (!m_paused)
- return;
-
- m_pauseOnNextStatement = false;
- m_doneProcessingDebuggerEvents = true;
-}
-
-void JavaScriptDebugServer::stepIntoStatement()
-{
- if (!m_paused)
- return;
-
- m_pauseOnNextStatement = true;
- m_doneProcessingDebuggerEvents = true;
-}
-
-void JavaScriptDebugServer::stepOverStatement()
-{
- if (!m_paused)
- return;
-
- m_pauseOnCallFrame = m_currentCallFrame.get();
- m_doneProcessingDebuggerEvents = true;
-}
-
-void JavaScriptDebugServer::stepOutOfFunction()
-{
- if (!m_paused)
- return;
-
- m_pauseOnCallFrame = m_currentCallFrame ? m_currentCallFrame->caller() : 0;
- m_doneProcessingDebuggerEvents = true;
-}
-
-JavaScriptCallFrame* JavaScriptDebugServer::currentCallFrame()
-{
- if (!m_paused)
- return 0;
- return m_currentCallFrame.get();
-}
-
-static void dispatchDidParseSource(const ListenerSet& listeners, ExecState* exec, const JSC::SourceCode& source)
-{
- Vector<JavaScriptDebugListener*> copy;
- copyToVector(listeners, copy);
- for (size_t i = 0; i < copy.size(); ++i)
- copy[i]->didParseSource(exec, source);
-}
-
-static void dispatchFailedToParseSource(const ListenerSet& listeners, ExecState* exec, const SourceCode& source, int errorLine, const String& errorMessage)
-{
- Vector<JavaScriptDebugListener*> copy;
- copyToVector(listeners, copy);
- for (size_t i = 0; i < copy.size(); ++i)
- copy[i]->failedToParseSource(exec, source, errorLine, errorMessage);
-}
-
-static Page* toPage(JSGlobalObject* globalObject)
-{
- ASSERT_ARG(globalObject, globalObject);
-
- JSDOMWindow* window = asJSDOMWindow(globalObject);
- Frame* frame = window->impl()->frame();
- return frame ? frame->page() : 0;
-}
-
-void JavaScriptDebugServer::sourceParsed(ExecState* exec, const SourceCode& source, int errorLine, const UString& errorMessage)
-{
- if (m_callingListeners)
- return;
-
- Page* page = toPage(exec->dynamicGlobalObject());
- if (!page)
- return;
-
- m_callingListeners = true;
-
- ASSERT(hasListeners());
-
- bool isError = errorLine != -1;
-
- if (hasGlobalListeners()) {
- if (isError)
- dispatchFailedToParseSource(m_listeners, exec, source, errorLine, errorMessage);
- else
- dispatchDidParseSource(m_listeners, exec, source);
- }
-
- if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) {
- ASSERT(!pageListeners->isEmpty());
- if (isError)
- dispatchFailedToParseSource(*pageListeners, exec, source, errorLine, errorMessage);
- else
- dispatchDidParseSource(*pageListeners, exec, source);
- }
-
- m_callingListeners = false;
-}
-
-static void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptDebugServer::JavaScriptExecutionCallback callback)
-{
- Vector<JavaScriptDebugListener*> copy;
- copyToVector(listeners, copy);
- for (size_t i = 0; i < copy.size(); ++i)
- (copy[i]->*callback)();
-}
-
-void JavaScriptDebugServer::dispatchFunctionToListeners(JavaScriptExecutionCallback callback, Page* page)
-{
- if (m_callingListeners)
- return;
-
- m_callingListeners = true;
-
- ASSERT(hasListeners());
-
- WebCore::dispatchFunctionToListeners(m_listeners, callback);
-
- if (ListenerSet* pageListeners = m_pageListenersMap.get(page)) {
- ASSERT(!pageListeners->isEmpty());
- WebCore::dispatchFunctionToListeners(*pageListeners, callback);
- }
-
- m_callingListeners = false;
-}
-
-void JavaScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused)
-{
- setMainThreadCallbacksPaused(paused);
-
- const HashSet<Page*>& pages = pageGroup.pages();
-
- HashSet<Page*>::const_iterator end = pages.end();
- for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it)
- setJavaScriptPaused(*it, paused);
-}
-
-void JavaScriptDebugServer::setJavaScriptPaused(Page* page, bool paused)
-{
- ASSERT_ARG(page, page);
-
- page->setDefersLoading(paused);
-
- for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
- setJavaScriptPaused(frame, paused);
-}
-
-void JavaScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused)
-{
- ASSERT_ARG(frame, frame);
-
- if (!frame->script()->isEnabled())
- return;
-
- frame->script()->setPaused(paused);
-
- if (JSDOMWindow* window = toJSDOMWindow(frame)) {
- if (paused) {
- OwnPtr<PausedTimeouts> timeouts;
- window->pauseTimeouts(timeouts);
- m_pausedTimeouts.set(frame, timeouts.release());
- } else {
- OwnPtr<PausedTimeouts> timeouts(m_pausedTimeouts.take(frame));
- window->resumeTimeouts(timeouts);
- }
- }
-
- setJavaScriptPaused(frame->view(), paused);
-}
-
-void JavaScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused)
-{
-#if !PLATFORM(MAC)
- if (!view)
- return;
-
- const HashSet<Widget*>* children = view->children();
- ASSERT(children);
-
- HashSet<Widget*>::const_iterator end = children->end();
- for (HashSet<Widget*>::const_iterator it = children->begin(); it != end; ++it) {
- Widget* widget = *it;
- if (!widget->isPluginView())
- continue;
- static_cast<PluginView*>(widget)->setJavaScriptPaused(paused);
- }
-#endif
-}
-
-void JavaScriptDebugServer::pauseIfNeeded(Page* page)
-{
- if (m_paused)
- return;
-
- if (!page || !hasListenersInterestedInPage(page))
- return;
-
- bool pauseNow = m_pauseOnNextStatement;
- pauseNow |= (m_pauseOnCallFrame == m_currentCallFrame);
- pauseNow |= (m_currentCallFrame->line() > 0 && hasBreakpoint(m_currentCallFrame->sourceID(), m_currentCallFrame->line()));
- if (!pauseNow)
- return;
-
- m_pauseOnCallFrame = 0;
- m_pauseOnNextStatement = false;
- m_paused = true;
-
- dispatchFunctionToListeners(&JavaScriptDebugListener::didPause, page);
-
- setJavaScriptPaused(page->group(), true);
-
- TimerBase::fireTimersInNestedEventLoop();
-
- EventLoop loop;
- m_doneProcessingDebuggerEvents = false;
- while (!m_doneProcessingDebuggerEvents && !loop.ended())
- loop.cycle();
-
- setJavaScriptPaused(page->group(), false);
-
- m_paused = false;
-}
-
-void JavaScriptDebugServer::callEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- m_currentCallFrame = JavaScriptCallFrame::create(debuggerCallFrame, m_currentCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-}
-
-void JavaScriptDebugServer::atStatement(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- ASSERT(m_currentCallFrame);
- if (!m_currentCallFrame)
- return;
-
- m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-}
-
-void JavaScriptDebugServer::returnEvent(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- ASSERT(m_currentCallFrame);
- if (!m_currentCallFrame)
- return;
-
- m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-
- // Treat stepping over a return statement like stepping out.
- if (m_currentCallFrame == m_pauseOnCallFrame)
- m_pauseOnCallFrame = m_currentCallFrame->caller();
- m_currentCallFrame = m_currentCallFrame->caller();
-}
-
-void JavaScriptDebugServer::exception(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- ASSERT(m_currentCallFrame);
- if (!m_currentCallFrame)
- return;
-
- if (m_pauseOnExceptions)
- m_pauseOnNextStatement = true;
-
- m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-}
-
-void JavaScriptDebugServer::willExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- m_currentCallFrame = JavaScriptCallFrame::create(debuggerCallFrame, m_currentCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-}
-
-void JavaScriptDebugServer::didExecuteProgram(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- ASSERT(m_currentCallFrame);
- if (!m_currentCallFrame)
- return;
-
- m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-
- // Treat stepping over the end of a program like stepping out.
- if (m_currentCallFrame == m_pauseOnCallFrame)
- m_pauseOnCallFrame = m_currentCallFrame->caller();
- m_currentCallFrame = m_currentCallFrame->caller();
-}
-
-void JavaScriptDebugServer::didReachBreakpoint(const DebuggerCallFrame& debuggerCallFrame, intptr_t sourceID, int lineNumber)
-{
- if (m_paused)
- return;
-
- ASSERT(m_currentCallFrame);
- if (!m_currentCallFrame)
- return;
-
- m_pauseOnNextStatement = true;
- m_currentCallFrame->update(debuggerCallFrame, sourceID, lineNumber);
- pauseIfNeeded(toPage(debuggerCallFrame.dynamicGlobalObject()));
-}
-
-void JavaScriptDebugServer::recompileAllJSFunctionsSoon()
-{
- m_recompileTimer.startOneShot(0);
-}
-
-void JavaScriptDebugServer::recompileAllJSFunctions(Timer<JavaScriptDebugServer>*)
-{
- JSLock lock(false);
- 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))
- functions.append(static_cast<JSFunction*>(*it));
- }
-
- typedef HashMap<RefPtr<FunctionBodyNode>, RefPtr<FunctionBodyNode> > FunctionBodyMap;
- typedef HashSet<SourceProvider*> SourceProviderSet;
-
- FunctionBodyMap functionBodies;
- SourceProviderSet sourceProviders;
-
- size_t size = functions.size();
- for (size_t i = 0; i < size; ++i) {
- JSFunction* function = functions[i];
-
- FunctionBodyNode* oldBody = function->m_body.get();
- pair<FunctionBodyMap::iterator, bool> result = functionBodies.add(oldBody, 0);
- if (!result.second) {
- function->m_body = result.first->second;
- 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->m_body = newBody.release();
-
- if (hasListeners()) {
- SourceProvider* provider = sourceCode.provider();
- if (sourceProviders.add(provider).second)
- sourceParsed(exec, SourceCode(provider), -1, 0);
- }
- }
-}
-
-void JavaScriptDebugServer::didAddListener(Page* page)
-{
- recompileAllJSFunctionsSoon();
-
- if (page)
- page->setDebugger(this);
- else
- Page::setDebuggerForAllPages(this);
-}
-
-void JavaScriptDebugServer::didRemoveListener(Page* page)
-{
- if (hasGlobalListeners() || (page && hasListenersInterestedInPage(page)))
- return;
-
- recompileAllJSFunctionsSoon();
-
- if (page)
- page->setDebugger(0);
- else
- Page::setDebuggerForAllPages(0);
-}
-
-void JavaScriptDebugServer::didRemoveLastListener()
-{
- m_doneProcessingDebuggerEvents = true;
-}
-
-} // namespace WebCore