1/* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2010-2011 Google Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#ifndef ScriptDebugServer_h 31#define ScriptDebugServer_h 32 33#if ENABLE(JAVASCRIPT_DEBUGGER) 34 35#include "ScriptDebugListener.h" 36#include "ScriptBreakpoint.h" 37#include "Timer.h" 38#include <debugger/Debugger.h> 39#include <wtf/HashMap.h> 40#include <wtf/HashSet.h> 41#include <wtf/RefPtr.h> 42#include <wtf/Vector.h> 43#include <wtf/text/TextPosition.h> 44#include <wtf/text/WTFString.h> 45 46namespace JSC { 47class DebuggerCallFrame; 48class JSGlobalObject; 49class ExecState; 50} 51namespace WebCore { 52 53class JavaScriptCallFrame; 54class ScriptDebugListener; 55class ScriptObject; 56class ScriptValue; 57 58class ScriptDebugServer : protected JSC::Debugger { 59 WTF_MAKE_NONCOPYABLE(ScriptDebugServer); WTF_MAKE_FAST_ALLOCATED; 60public: 61 String setBreakpoint(const String& sourceID, const ScriptBreakpoint&, int* actualLineNumber, int* actualColumnNumber); 62 void removeBreakpoint(const String& breakpointId); 63 void clearBreakpoints(); 64 void setBreakpointsActivated(bool activated); 65 void activateBreakpoints() { setBreakpointsActivated(true); } 66 void deactivateBreakpoints() { setBreakpointsActivated(false); } 67 68 enum PauseOnExceptionsState { 69 DontPauseOnExceptions, 70 PauseOnAllExceptions, 71 PauseOnUncaughtExceptions 72 }; 73 PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } 74 void setPauseOnExceptionsState(PauseOnExceptionsState); 75 76 void setPauseOnNextStatement(bool pause); 77 void breakProgram(); 78 void continueProgram(); 79 void stepIntoStatement(); 80 void stepOverStatement(); 81 void stepOutOfFunction(); 82 83 bool canSetScriptSource(); 84 bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, ScriptValue* newCallFrames, ScriptObject* result); 85 void updateCallStack(ScriptValue* callFrame); 86 87 bool causesRecompilation() { return true; } 88 bool supportsSeparateScriptCompilationAndExecution() { return false; } 89 90 void recompileAllJSFunctionsSoon(); 91 virtual void recompileAllJSFunctions(Timer<ScriptDebugServer>* = 0) = 0; 92 93 void setScriptPreprocessor(const String&) 94 { 95 // FIXME(webkit.org/b/82203): Implement preprocessor. 96 } 97 98 bool isPaused() { return m_paused; } 99 bool runningNestedMessageLoop() { return m_runningNestedMessageLoop; } 100 101 void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage); 102 void clearCompiledScripts(); 103 void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage); 104 105 class Task { 106 WTF_MAKE_FAST_ALLOCATED; 107 public: 108 virtual ~Task() { } 109 virtual void run() = 0; 110 }; 111 112protected: 113 typedef HashSet<ScriptDebugListener*> ListenerSet; 114 typedef void (ScriptDebugServer::*JavaScriptExecutionCallback)(ScriptDebugListener*); 115 116 ScriptDebugServer(); 117 ~ScriptDebugServer(); 118 119 virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) = 0; 120 virtual void didPause(JSC::JSGlobalObject*) = 0; 121 virtual void didContinue(JSC::JSGlobalObject*) = 0; 122 123 virtual void runEventLoopWhilePaused() = 0; 124 125 virtual bool isContentScript(JSC::ExecState*); 126 127 bool hasBreakpoint(intptr_t sourceID, const TextPosition&) const; 128 129 void dispatchFunctionToListeners(JavaScriptExecutionCallback, JSC::JSGlobalObject*); 130 void dispatchFunctionToListeners(const ListenerSet& listeners, JavaScriptExecutionCallback callback); 131 void dispatchDidPause(ScriptDebugListener*); 132 void dispatchDidContinue(ScriptDebugListener*); 133 void dispatchDidParseSource(const ListenerSet& listeners, JSC::SourceProvider*, bool isContentScript); 134 void dispatchFailedToParseSource(const ListenerSet& listeners, JSC::SourceProvider*, int errorLine, const String& errorMessage); 135 136 void createCallFrame(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int columnNumber); 137 void updateCallFrameAndPauseIfNeeded(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int columnNumber); 138 void pauseIfNeeded(JSC::JSGlobalObject* dynamicGlobalObject); 139 140 virtual void detach(JSC::JSGlobalObject*); 141 142 virtual void sourceParsed(JSC::ExecState*, JSC::SourceProvider*, int errorLine, const String& errorMsg); 143 virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int columnNumber); 144 virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int firstLine, int columnNumber); 145 virtual void returnEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int columnNumber); 146 virtual void exception(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int columnNumber, bool hasHandler); 147 virtual void willExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno, int columnNumber); 148 virtual void didExecuteProgram(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno, int columnNumber); 149 virtual void didReachBreakpoint(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno, int columnNumber); 150 151 typedef Vector<ScriptBreakpoint> BreakpointsInLine; 152 typedef HashMap<long, BreakpointsInLine> LineToBreakpointMap; 153 typedef HashMap<intptr_t, LineToBreakpointMap> SourceIdToBreakpointsMap; 154 155 bool m_callingListeners; 156 PauseOnExceptionsState m_pauseOnExceptionsState; 157 bool m_pauseOnNextStatement; 158 bool m_paused; 159 bool m_runningNestedMessageLoop; 160 bool m_doneProcessingDebuggerEvents; 161 bool m_breakpointsActivated; 162 JavaScriptCallFrame* m_pauseOnCallFrame; 163 RefPtr<JavaScriptCallFrame> m_currentCallFrame; 164 SourceIdToBreakpointsMap m_sourceIdToBreakpoints; 165 Timer<ScriptDebugServer> m_recompileTimer; 166 167 int m_lastExecutedLine; 168 intptr_t m_lastExecutedSourceId; 169}; 170 171} // namespace WebCore 172 173#endif // ENABLE(JAVASCRIPT_DEBUGGER) 174 175#endif // ScriptDebugServer_h 176