// some reason could not be entered FailedToEnter will return true.
class EnterDebugger BASE_EMBEDDED {
public:
- EnterDebugger() : set_(!it_.done()) {
- // If there is no JavaScript frames on the stack don't switch to new break
- // and break frame.
- if (set_) {
- // Store the previous break is and frame id.
- break_id_ = Top::break_id();
- break_frame_id_ = Top::break_frame_id();
-
- // Create the new break info.
+ EnterDebugger() : has_js_frames_(!it_.done()) {
+ // Store the previous break id and frame id.
+ break_id_ = Top::break_id();
+ break_frame_id_ = Top::break_frame_id();
+
+ // Create the new break info. If there is no JavaScript frames there is no
+ // break frame id.
+ if (has_js_frames_) {
Top::new_break(it_.frame()->id());
+ } else {
+ Top::new_break(StackFrame::NO_ID);
}
// Make sure that debugger is loaded and enter the debugger context.
}
~EnterDebugger() {
- if (set_) {
- // Restore to the previous break state.
- Top::set_break(break_frame_id_, break_id_);
- }
+ // Restore to the previous break state.
+ Top::set_break(break_frame_id_, break_id_);
}
// Check whether the debugger could be entered.
inline bool FailedToEnter() { return load_failed_; }
// Check whether there are any JavaScript frames on the stack.
- inline bool HasJavaScriptFrames() { return set_; }
+ inline bool HasJavaScriptFrames() { return has_js_frames_; }
private:
JavaScriptFrameIterator it_;
- const bool set_; // Was the break actually set?
+ const bool has_js_frames_; // Were there any JavaScript frames?
StackFrame::Id break_frame_id_; // Previous break frame id.
int break_id_; // Previous break id.
bool load_failed_; // Did the debugger fail to load?
"}";
v8::Local<v8::Function> frame_function_name;
+
+// Source for The JavaScript function which returns the number of frames.
+static const char* frame_count_source =
+ "function frame_count(exec_state) {"
+ " return exec_state.frameCount();"
+ "}";
+v8::Handle<v8::Function> frame_count;
+
+
// Global variable to store the last function hit - used by some tests.
char last_function_hit[80];
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
// Count the number of breaks.
if (event == v8::Break) {
break_point_hit_count++;
}
-// Debug event handler which counts a number of events.
+// Debug event handler which counts a number of events and collects the stack
+// height if there is a function compiled for that.
int exception_hit_count = 0;
int uncaught_exception_hit_count = 0;
+int last_js_stack_height = -1;
static void DebugEventCounterClear() {
break_point_hit_count = 0;
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
// Count the number of breaks.
if (event == v8::Break) {
break_point_hit_count++;
uncaught_exception_hit_count++;
}
}
+
+ // Collect the JavsScript stack height if the function frame_count is
+ // compiled.
+ if (!frame_count.IsEmpty()) {
+ static const int kArgc = 1;
+ v8::Handle<v8::Value> argv[kArgc] = { exec_state };
+ // Using exec_state as receiver is just to have a receiver.
+ v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv);
+ last_js_stack_height = result->Int32Value();
+ }
}
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
if (event == v8::Break) {
for (int i = 0; checks[i].expr != NULL; i++) {
const int argc = 3;
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
if (event == v8::Break) {
break_point_hit_count++;
v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(data);
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
if (event == v8::Break) {
break_point_hit_count++;
PrepareStep(step_action);
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
if (event == v8::Break || event == v8::Exception) {
// Check that the current function is the expected.
CHECK(break_point_hit_count <
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
// Perform a garbage collection when break point is hit and continue. Based
// on the number of break points hit either scavenge or mark compact
// collector is used.
v8::Handle<v8::Object> exec_state,
v8::Handle<v8::Object> event_data,
v8::Handle<v8::Value> data) {
+ // When hitting a debug event listener there must be a break set.
+ CHECK(v8::internal::Top::is_break());
+
if (event == v8::Break) {
// Count the number of breaks.
break_point_hit_count++;
// Test break on exceptions. For each exception break combination the number
// of debug event exception callbacks and message callbacks are collected. The
-// number of debug event exception callbacks are cused to check that the
+// number of debug event exception callbacks are used to check that the
// debugger is called correctly and the number of message callbacks is used to
// check that uncaught exceptions are still returned even if there is a break
// for them.
}
+// Test break on exception from compiler errors. When compiling using
+// v8::Script::Compile there is no JavaScript stack whereas when compiling using
+// eval there are JavaScript frames.
+TEST(BreakOnCompileException) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+
+ v8::internal::Top::TraceException(false);
+
+ // Create a function for checking the function when hitting a break point.
+ frame_count = CompileFunction(&env, frame_count_source, "frame_count");
+
+ v8::V8::AddMessageListener(MessageCallbackCount);
+ v8::Debug::AddDebugEventListener(DebugEventCounter);
+
+ DebugEventCounterClear();
+ MessageCallbackCountClear();
+
+ // Check initial state.
+ CHECK_EQ(0, exception_hit_count);
+ CHECK_EQ(0, uncaught_exception_hit_count);
+ CHECK_EQ(0, message_callback_count);
+ CHECK_EQ(-1, last_js_stack_height);
+
+ // Throws SyntaxError: Unexpected end of input
+ v8::Script::Compile(v8::String::New("+++"));
+ CHECK_EQ(1, exception_hit_count);
+ CHECK_EQ(1, uncaught_exception_hit_count);
+ CHECK_EQ(1, message_callback_count);
+ CHECK_EQ(0, last_js_stack_height); // No JavaScript stack.
+
+ // Throws SyntaxError: Unexpected identifier
+ v8::Script::Compile(v8::String::New("x x"));
+ CHECK_EQ(2, exception_hit_count);
+ CHECK_EQ(2, uncaught_exception_hit_count);
+ CHECK_EQ(2, message_callback_count);
+ CHECK_EQ(0, last_js_stack_height); // No JavaScript stack.
+
+ // Throws SyntaxError: Unexpected end of input
+ v8::Script::Compile(v8::String::New("eval('+++')"))->Run();
+ CHECK_EQ(3, exception_hit_count);
+ CHECK_EQ(3, uncaught_exception_hit_count);
+ CHECK_EQ(3, message_callback_count);
+ CHECK_EQ(1, last_js_stack_height);
+
+ // Throws SyntaxError: Unexpected identifier
+ v8::Script::Compile(v8::String::New("eval('x x')"))->Run();
+ CHECK_EQ(4, exception_hit_count);
+ CHECK_EQ(4, uncaught_exception_hit_count);
+ CHECK_EQ(4, message_callback_count);
+ CHECK_EQ(1, last_js_stack_height);
+}
+
+
TEST(StepWithException) {
v8::HandleScope scope;
DebugLocalContext env;
}
-// Source for The JavaScript function which returns the number of frames.
-static const char* frame_count_source =
- "function frame_count(exec_state) {"
- " return exec_state.frameCount();"
- "}";
-v8::Handle<v8::Function> frame_count;
-
-
// Source for a JavaScript function which returns the source line for the top
// frame.
static const char* frame_source_line_source =