forked from facebook/hermes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDebuggerAPI.h
More file actions
304 lines (244 loc) · 10 KB
/
DebuggerAPI.h
File metadata and controls
304 lines (244 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#ifndef HERMES_DEBUGGERAPI_H
#define HERMES_DEBUGGERAPI_H
#ifdef HERMES_ENABLE_DEBUGGER
#include <hermes/hermes.h>
#include <cassert>
#include <memory>
#include <vector>
#include "hermes/Public/DebuggerTypes.h"
// Forward declarations of internal types.
namespace hermes {
namespace vm {
class CodeBlock;
class Debugger;
struct DebugCommand;
class HermesValue;
} // namespace vm
} // namespace hermes
namespace facebook {
namespace hermes {
class HermesRuntime;
namespace debugger {
class Debugger;
class EventObserver;
/// Represents a variable in the debugger.
struct HERMES_EXPORT VariableInfo {
/// Name of the variable in the source.
String name;
/// Value of the variable.
::facebook::jsi::Value value;
};
/// An EvalResult represents the result of an Eval command.
struct HERMES_EXPORT EvalResult {
/// The resulting JavaScript object, or the thrown exception.
::facebook::jsi::Value value;
/// Indicates that the result was an exception.
bool isException = false;
/// If isException is true, details about the exception.
ExceptionDetails exceptionDetails;
EvalResult(EvalResult &&) = default;
EvalResult() = default;
EvalResult(
::facebook::jsi::Value value,
bool isException,
ExceptionDetails exceptionDetails)
: value(std::move(value)),
isException(isException),
exceptionDetails(std::move(exceptionDetails)) {}
};
/// ProgramState represents the state of a paused program. An instance of
/// ProgramState is available as the getProgramState() member function of class
/// Debugger.
class HERMES_EXPORT ProgramState {
public:
/// \return the reason for the Pause.
PauseReason getPauseReason() const {
return pauseReason_;
}
/// \return the breakpoint if the PauseReason is Breakpoint, otherwise
/// kInvalidBreakpoint.
BreakpointID getBreakpoint() const {
return breakpoint_;
}
/// \return the evaluation result if the PauseReason is due to EvalComplete.
EvalResult getEvalResult() const;
/// \returns a stack trace for the current execution.
const StackTrace &getStackTrace() const {
return stackTrace_;
}
/// \returns lexical information about the state in a given frame.
LexicalInfo getLexicalInfo(uint32_t frameIndex) const;
/// \return information about a variable in a given lexical scope, in a given
/// frame.
VariableInfo getVariableInfo(
uint32_t frameIndex,
ScopeDepth scopeDepth,
uint32_t variableIndexInScope) const;
/// \return information about the `this` value at a given stack depth.
VariableInfo getVariableInfoForThis(uint32_t frameIndex) const;
/// \return the number of variables in a given frame.
/// This is deprecated: prefer using getLexicalInfoInFrame().
uint32_t getVariablesCountInFrame(uint32_t frameIndex) const {
auto info = getLexicalInfo(frameIndex);
uint32_t result = 0;
for (ScopeDepth i = 0, max = info.getScopesCount(); i < max; i++)
result += info.getVariablesCountInScope(i);
return result;
}
/// \return info for a variable at a given index \p variableIndex, in a given
/// frame at index \p frameIndex.
/// This is deprecated. Prefer the getVariableInfo() that takes three
/// parameters.
VariableInfo getVariableInfo(uint32_t frameIndex, uint32_t variableIndex)
const {
LexicalInfo info = getLexicalInfo(frameIndex);
uint32_t remaining = variableIndex;
for (ScopeDepth scope = 0;; scope++) {
assert(scope < info.getScopesCount() && "Index out of bounds");
uint32_t count = info.getVariablesCountInScope(scope);
if (remaining < count) {
return getVariableInfo(frameIndex, scope, remaining);
}
remaining -= count;
}
}
private:
friend Debugger;
/// ProgramState must not be copied, because some of its implementation
/// requires querying the live program state and so the state must not be
/// retained after the pause returns.
/// ProgramState must not be copied.
ProgramState(const ProgramState &) = delete;
ProgramState &operator=(const ProgramState &) = delete;
::hermes::vm::Debugger *impl() const;
ProgramState(Debugger *dbg) : dbg_(dbg) {}
Debugger *dbg_;
PauseReason pauseReason_{};
StackTrace stackTrace_;
EvalResult evalResult_;
BreakpointID breakpoint_{kInvalidBreakpoint};
};
/// Command represents an action that you can request the debugger to perform
/// when returned from didPause().
class HERMES_EXPORT Command {
public:
/// Commands may be moved.
Command(Command &&);
Command &operator=(Command &&);
~Command();
/// \return a Command that steps with the given StepMode \p mode.
static Command step(StepMode mode);
/// \return a Command that continues execution.
static Command continueExecution();
/// \return a Command that evaluates JavaScript code \p src in the
/// frame at index \p frameIndex.
static Command eval(const String &src, uint32_t frameIndex);
private:
friend Debugger;
explicit Command(::hermes::vm::DebugCommand &&);
std::unique_ptr<::hermes::vm::DebugCommand> debugCommand_;
};
/// Debugger allows access to the Hermes debugging functionality. An instance of
/// Debugger is available from HermesRuntime, and also passed to your
/// EventObserver.
class HERMES_EXPORT Debugger {
public:
/// Set the Debugger event observer. The event observer is notified of
/// debugging event, specifically when the program pauses. This is simply a
/// raw pointer: it is the client's responsibility to clear the event observer
/// if the event observer is deallocated before the Debugger.
void setEventObserver(EventObserver *observer);
/// Sets the property %isDebuggerAttached in %DebuggerInternal object.
void setIsDebuggerAttached(bool isAttached);
/// Asynchronously triggers a pause. This may be called from any thread. This
/// is inherently racey and the exact point at which the program pauses is not
/// guaranteed. You can discover when the program has paused through the event
/// observer.
void triggerAsyncPause(AsyncPauseKind kind);
/// \return the ProgramState representing the state of the paused program.
/// This may only be invoked when the program is paused.
const ProgramState &getProgramState() const {
return state_;
}
/// \return the source map URL for the \p fileId.
String getSourceMappingUrl(uint32_t fileId) const;
/// -- Breakpoint Management --
/// Sets a breakpoint on a given SourceLocation.
/// \return the ID of the breakpoint, 0 if it wasn't created.
BreakpointID setBreakpoint(SourceLocation loc);
/// Sets the condition on breakpoint \p breakpoint.
/// The condition will be stored with the breakpoint,
/// and if non-empty, will be executed to determine whether to actually
/// pause on the breakpoint; only if ToBoolean(condition) is true
/// and does not throw will the debugger pause on \p breakpoint.
/// \param condition the code to execute to determine whether to break;
/// if empty, the condition is considered to not be set.
void setBreakpointCondition(BreakpointID breakpoint, const String &condition);
/// Deletes a breakpoint.
void deleteBreakpoint(BreakpointID breakpoint);
/// Deletes all breakpoints.
void deleteAllBreakpoints();
/// Mark a breakpoint as enabled. Breakpoints are by default enabled.
void setBreakpointEnabled(BreakpointID breakpoint, bool enable);
/// \return information on a breakpoint.
BreakpointInfo getBreakpointInfo(BreakpointID breakpoint);
/// \return a list of extant breakpoints.
std::vector<BreakpointID> getBreakpoints();
/// Set whether the debugger should pause when an exception is thrown.
void setPauseOnThrowMode(PauseOnThrowMode mode);
/// \return whether the debugger pauses when an exception is thrown.
PauseOnThrowMode getPauseOnThrowMode() const;
/// Set whether the debugger should pause after a script was loaded.
void setShouldPauseOnScriptLoad(bool flag);
/// \return whether the debugger should pause after a script was loaded.
bool getShouldPauseOnScriptLoad() const;
private:
friend std::unique_ptr<HermesRuntime> hermes::makeHermesRuntime(
const ::hermes::vm::RuntimeConfig &);
friend std::unique_ptr<jsi::ThreadSafeRuntime>
hermes::makeThreadSafeHermesRuntime(const ::hermes::vm::RuntimeConfig &);
friend ProgramState;
/// Debuggers may not be moved or copied.
Debugger(const Debugger &) = delete;
void operator=(const Debugger &) = delete;
Debugger(Debugger &&) = delete;
void operator=(Debugger &&) = delete;
/// Implementation detail used by ProgramState.
::facebook::jsi::Value jsiValueFromHermesValue(::hermes::vm::HermesValue hv);
explicit Debugger(
::facebook::hermes::HermesRuntime *runtime,
::hermes::vm::Debugger *impl);
::facebook::hermes::HermesRuntime *const runtime_;
EventObserver *eventObserver_ = nullptr;
::hermes::vm::Debugger *impl_;
ProgramState state_;
};
/// A subclass of EventObserver may be set on the Debugger via
/// setEventObserver(). It receives notifications when the Debugger pauses.
class HERMES_EXPORT EventObserver {
public:
/// didPause() is invoked when the JavaScript program has paused. The
/// The Debugger \p debugger can be used to manipulate breakpoints and enqueue
/// debugger commands such as stepping, etc. It can also be used to discover
/// the call stack and variables via debugger.getProgramState().
/// \return a Command for the debugger to perform.
virtual Command didPause(Debugger &debugger) = 0;
/// Invoked when the debugger resolves a previously unresolved breakpoint.
/// Note that the debugger is *not* paused during this,
/// and thus debugger.getProgramState() is not valid.
/// This callback may not invoke JavaScript or enqueue debugger commands.
virtual void breakpointResolved(Debugger &debugger, BreakpointID breakpoint) {
}
virtual ~EventObserver();
};
} // namespace debugger
} // namespace hermes
} // namespace facebook
#endif // HERMES_ENABLE_DEBUGGER
#endif // HERMES_DEBUGGERAPI_H