finally blocks should not set the exception stack trace when re-throwing the exception.
[WebKit-https.git] / Source / JavaScriptCore / debugger / Debugger.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifndef Debugger_h
23 #define Debugger_h
24
25 #include "Breakpoint.h"
26 #include "DebuggerCallFrame.h"
27 #include "DebuggerPrimitives.h"
28 #include "JSCJSValue.h"
29 #include <wtf/HashMap.h>
30 #include <wtf/HashSet.h>
31 #include <wtf/RefPtr.h>
32 #include <wtf/text/TextPosition.h>
33
34 namespace JSC {
35
36 class CodeBlock;
37 class ExecState;
38 class JSGlobalObject;
39 class SourceProvider;
40 class VM;
41
42 typedef ExecState CallFrame;
43
44 class JS_EXPORT_PRIVATE Debugger {
45 public:
46     Debugger(bool isInWorkerThread = false);
47     virtual ~Debugger();
48
49     JSC::DebuggerCallFrame* currentDebuggerCallFrame() const;
50     bool hasHandlerForExceptionCallback() const
51     {
52         ASSERT(m_reasonForPause == PausedForException);
53         return m_hasHandlerForExceptionCallback;
54     }
55     JSValue currentException()
56     {
57         ASSERT(m_reasonForPause == PausedForException);
58         return m_currentException;
59     }
60
61     bool needsExceptionCallbacks() const { return m_pauseOnExceptionsState != DontPauseOnExceptions; }
62
63     enum ReasonForDetach {
64         TerminatingDebuggingSession,
65         GlobalObjectIsDestructing
66     };
67     void attach(JSGlobalObject*);
68     void detach(JSGlobalObject*, ReasonForDetach);
69     bool isAttached(JSGlobalObject*);
70
71     BreakpointID setBreakpoint(Breakpoint, unsigned& actualLine, unsigned& actualColumn);
72     void removeBreakpoint(BreakpointID);
73     void clearBreakpoints();
74     void setBreakpointsActivated(bool);
75     void activateBreakpoints() { setBreakpointsActivated(true); }
76     void deactivateBreakpoints() { setBreakpointsActivated(false); }
77
78     enum PauseOnExceptionsState {
79         DontPauseOnExceptions,
80         PauseOnAllExceptions,
81         PauseOnUncaughtExceptions
82     };
83     PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; }
84     void setPauseOnExceptionsState(PauseOnExceptionsState);
85
86     enum ReasonForPause {
87         NotPaused,
88         PausedForException,
89         PausedAtStatement,
90         PausedAfterCall,
91         PausedBeforeReturn,
92         PausedAtStartOfProgram,
93         PausedAtEndOfProgram,
94         PausedForBreakpoint,
95         PausedForDebuggerStatement,
96     };
97     ReasonForPause reasonForPause() const { return m_reasonForPause; }
98     BreakpointID pausingBreakpointID() const { return m_pausingBreakpointID; }
99
100     void setPauseOnNextStatement(bool);
101     void breakProgram();
102     void continueProgram();
103     void stepIntoStatement();
104     void stepOverStatement();
105     void stepOutOfFunction();
106
107     bool isPaused() const { return m_isPaused; }
108     bool isStepping() const { return m_steppingMode == SteppingModeEnabled; }
109
110     virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const WTF::String& errorMessage) = 0;
111
112     void exception(CallFrame*, JSValue exceptionValue, bool hasCatchHandler);
113     void atStatement(CallFrame*);
114     void callEvent(CallFrame*);
115     void returnEvent(CallFrame*);
116     void willExecuteProgram(CallFrame*);
117     void didExecuteProgram(CallFrame*);
118     void didReachBreakpoint(CallFrame*);
119
120     void recompileAllJSFunctions(VM*);
121
122     void registerCodeBlock(CodeBlock*);
123
124 protected:
125     virtual bool needPauseHandling(JSGlobalObject*) { return false; }
126     virtual void handleBreakpointHit(JSGlobalObject*, const Breakpoint&) { }
127     virtual void handleExceptionInBreakpointCondition(ExecState*, Exception*) const { }
128     virtual void handlePause(JSGlobalObject*, ReasonForPause) { }
129     virtual void notifyDoneProcessingDebuggerEvents() { }
130
131 private:
132     typedef HashMap<BreakpointID, Breakpoint*> BreakpointIDToBreakpointMap;
133
134     typedef HashMap<unsigned, RefPtr<BreakpointsList>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> LineToBreakpointsMap;
135     typedef HashMap<SourceID, LineToBreakpointsMap, WTF::IntHash<SourceID>, WTF::UnsignedWithZeroKeyHashTraits<SourceID>> SourceIDToBreakpointsMap;
136
137     class ClearCodeBlockDebuggerRequestsFunctor;
138     class ClearDebuggerRequestsFunctor;
139     class SetSteppingModeFunctor;
140     class ToggleBreakpointFunctor;
141
142     class PauseReasonDeclaration {
143     public:
144         PauseReasonDeclaration(Debugger& debugger, ReasonForPause reason)
145             : m_debugger(debugger)
146         {
147             m_debugger.m_reasonForPause = reason;
148         }
149
150         ~PauseReasonDeclaration()
151         {
152             m_debugger.m_reasonForPause = NotPaused;
153         }
154     private:
155         Debugger& m_debugger;
156     };
157
158     bool hasBreakpoint(SourceID, const TextPosition&, Breakpoint* hitBreakpoint);
159
160     void updateNeedForOpDebugCallbacks();
161
162     // These update functions are only needed because our current breakpoints are
163     // key'ed off the source position instead of the bytecode PC. This ensures
164     // that we don't break on the same line more than once. Once we switch to a
165     // bytecode PC key'ed breakpoint, we will not need these anymore and should
166     // be able to remove them.
167     void updateCallFrame(JSC::CallFrame*);
168     void updateCallFrameAndPauseIfNeeded(JSC::CallFrame*);
169     void pauseIfNeeded(JSC::CallFrame*);
170
171     enum SteppingMode {
172         SteppingModeDisabled,
173         SteppingModeEnabled
174     };
175     void setSteppingMode(SteppingMode);
176
177     enum BreakpointState {
178         BreakpointDisabled,
179         BreakpointEnabled
180     };
181     void toggleBreakpoint(CodeBlock*, Breakpoint&, BreakpointState);
182     void applyBreakpoints(CodeBlock*);
183     void toggleBreakpoint(Breakpoint&, BreakpointState);
184
185     void clearDebuggerRequests(JSGlobalObject*);
186
187     template<typename Functor> inline void forEachCodeBlock(Functor&);
188
189     VM* m_vm;
190     HashSet<JSGlobalObject*> m_globalObjects;
191
192     PauseOnExceptionsState m_pauseOnExceptionsState;
193     bool m_pauseOnNextStatement : 1;
194     bool m_isPaused : 1;
195     bool m_breakpointsActivated : 1;
196     bool m_hasHandlerForExceptionCallback : 1;
197     bool m_isInWorkerThread : 1;
198     unsigned m_steppingMode : 1; // SteppingMode
199
200     ReasonForPause m_reasonForPause;
201     JSValue m_currentException;
202     CallFrame* m_pauseOnCallFrame;
203     CallFrame* m_currentCallFrame;
204     unsigned m_lastExecutedLine;
205     SourceID m_lastExecutedSourceID;
206
207     BreakpointID m_topBreakpointID;
208     BreakpointID m_pausingBreakpointID;
209     BreakpointIDToBreakpointMap m_breakpointIDToBreakpoint;
210     SourceIDToBreakpointsMap m_sourceIDToBreakpoints;
211
212     RefPtr<JSC::DebuggerCallFrame> m_currentDebuggerCallFrame;
213
214     friend class DebuggerPausedScope;
215     friend class TemporaryPausedState;
216     friend class LLIntOffsetsExtractor;
217 };
218
219 } // namespace JSC
220
221 #endif // Debugger_h