deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / cctest / test-debug.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include <stdlib.h>
29
30 #include "src/v8.h"
31
32 #include "src/api.h"
33 #include "src/base/platform/condition-variable.h"
34 #include "src/base/platform/platform.h"
35 #include "src/compilation-cache.h"
36 #include "src/debug.h"
37 #include "src/deoptimizer.h"
38 #include "src/frames.h"
39 #include "src/utils.h"
40 #include "test/cctest/cctest.h"
41
42
43 using ::v8::base::Mutex;
44 using ::v8::base::LockGuard;
45 using ::v8::base::ConditionVariable;
46 using ::v8::base::OS;
47 using ::v8::base::Semaphore;
48 using ::v8::internal::EmbeddedVector;
49 using ::v8::internal::Object;
50 using ::v8::internal::Handle;
51 using ::v8::internal::Heap;
52 using ::v8::internal::JSGlobalProxy;
53 using ::v8::internal::Code;
54 using ::v8::internal::Debug;
55 using ::v8::internal::Debugger;
56 using ::v8::internal::CommandMessage;
57 using ::v8::internal::CommandMessageQueue;
58 using ::v8::internal::StackFrame;
59 using ::v8::internal::StepAction;
60 using ::v8::internal::StepIn;  // From StepAction enum
61 using ::v8::internal::StepNext;  // From StepAction enum
62 using ::v8::internal::StepOut;  // From StepAction enum
63 using ::v8::internal::Vector;
64 using ::v8::internal::StrLength;
65
66 // Size of temp buffer for formatting small strings.
67 #define SMALL_STRING_BUFFER_SIZE 80
68
69 // --- H e l p e r   C l a s s e s
70
71
72 // Helper class for creating a V8 enviromnent for running tests
73 class DebugLocalContext {
74  public:
75   inline DebugLocalContext(
76       v8::Isolate* isolate, v8::ExtensionConfiguration* extensions = 0,
77       v8::Handle<v8::ObjectTemplate> global_template =
78           v8::Handle<v8::ObjectTemplate>(),
79       v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
80       : scope_(isolate),
81         context_(v8::Context::New(isolate, extensions, global_template,
82                                   global_object)) {
83     context_->Enter();
84   }
85   inline DebugLocalContext(
86       v8::ExtensionConfiguration* extensions = 0,
87       v8::Handle<v8::ObjectTemplate> global_template =
88           v8::Handle<v8::ObjectTemplate>(),
89       v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
90       : scope_(CcTest::isolate()),
91         context_(v8::Context::New(CcTest::isolate(), extensions,
92                                   global_template, global_object)) {
93     context_->Enter();
94   }
95   inline ~DebugLocalContext() {
96     context_->Exit();
97   }
98   inline v8::Local<v8::Context> context() { return context_; }
99   inline v8::Context* operator->() { return *context_; }
100   inline v8::Context* operator*() { return *context_; }
101   inline v8::Isolate* GetIsolate() { return context_->GetIsolate(); }
102   inline bool IsReady() { return !context_.IsEmpty(); }
103   void ExposeDebug() {
104     v8::internal::Isolate* isolate =
105         reinterpret_cast<v8::internal::Isolate*>(context_->GetIsolate());
106     v8::internal::Factory* factory = isolate->factory();
107     // Expose the debug context global object in the global object for testing.
108     CHECK(isolate->debug()->Load());
109     Handle<v8::internal::Context> debug_context =
110         isolate->debug()->debug_context();
111     debug_context->set_security_token(
112         v8::Utils::OpenHandle(*context_)->security_token());
113
114     Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
115         v8::Utils::OpenHandle(*context_->Global())));
116     Handle<v8::internal::String> debug_string =
117         factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("debug"));
118     v8::internal::Runtime::DefineObjectProperty(global, debug_string,
119         handle(debug_context->global_proxy(), isolate), DONT_ENUM).Check();
120   }
121
122  private:
123   v8::HandleScope scope_;
124   v8::Local<v8::Context> context_;
125 };
126
127
128 // --- H e l p e r   F u n c t i o n s
129
130
131 // Compile and run the supplied source and return the fequested function.
132 static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
133                                                const char* source,
134                                                const char* function_name) {
135   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source))
136       ->Run();
137   return v8::Local<v8::Function>::Cast((*env)->Global()->Get(
138       v8::String::NewFromUtf8(env->GetIsolate(), function_name)));
139 }
140
141
142 // Compile and run the supplied source and return the requested function.
143 static v8::Local<v8::Function> CompileFunction(v8::Isolate* isolate,
144                                                const char* source,
145                                                const char* function_name) {
146   v8::Script::Compile(v8::String::NewFromUtf8(isolate, source))->Run();
147   v8::Local<v8::Object> global = isolate->GetCurrentContext()->Global();
148   return v8::Local<v8::Function>::Cast(
149       global->Get(v8::String::NewFromUtf8(isolate, function_name)));
150 }
151
152
153 // Is there any debug info for the function?
154 static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
155   Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
156   Handle<v8::internal::SharedFunctionInfo> shared(f->shared());
157   return Debug::HasDebugInfo(shared);
158 }
159
160
161 // Set a break point in a function and return the associated break point
162 // number.
163 static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
164   static int break_point = 0;
165   v8::internal::Isolate* isolate = fun->GetIsolate();
166   v8::internal::Debug* debug = isolate->debug();
167   debug->SetBreakPoint(
168       fun,
169       Handle<Object>(v8::internal::Smi::FromInt(++break_point), isolate),
170       &position);
171   return break_point;
172 }
173
174
175 // Set a break point in a function and return the associated break point
176 // number.
177 static int SetBreakPoint(v8::Handle<v8::Function> fun, int position) {
178   return SetBreakPoint(v8::Utils::OpenHandle(*fun), position);
179 }
180
181
182 // Set a break point in a function using the Debug object and return the
183 // associated break point number.
184 static int SetBreakPointFromJS(v8::Isolate* isolate,
185                                const char* function_name,
186                                int line, int position) {
187   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
188   SNPrintF(buffer,
189            "debug.Debug.setBreakPoint(%s,%d,%d)",
190            function_name, line, position);
191   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
192   v8::Handle<v8::String> str = v8::String::NewFromUtf8(isolate, buffer.start());
193   return v8::Script::Compile(str)->Run()->Int32Value();
194 }
195
196
197 // Set a break point in a script identified by id using the global Debug object.
198 static int SetScriptBreakPointByIdFromJS(v8::Isolate* isolate, int script_id,
199                                          int line, int column) {
200   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
201   if (column >= 0) {
202     // Column specified set script break point on precise location.
203     SNPrintF(buffer,
204              "debug.Debug.setScriptBreakPointById(%d,%d,%d)",
205              script_id, line, column);
206   } else {
207     // Column not specified set script break point on line.
208     SNPrintF(buffer,
209              "debug.Debug.setScriptBreakPointById(%d,%d)",
210              script_id, line);
211   }
212   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
213   {
214     v8::TryCatch try_catch;
215     v8::Handle<v8::String> str =
216         v8::String::NewFromUtf8(isolate, buffer.start());
217     v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
218     CHECK(!try_catch.HasCaught());
219     return value->Int32Value();
220   }
221 }
222
223
224 // Set a break point in a script identified by name using the global Debug
225 // object.
226 static int SetScriptBreakPointByNameFromJS(v8::Isolate* isolate,
227                                            const char* script_name, int line,
228                                            int column) {
229   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
230   if (column >= 0) {
231     // Column specified set script break point on precise location.
232     SNPrintF(buffer,
233              "debug.Debug.setScriptBreakPointByName(\"%s\",%d,%d)",
234              script_name, line, column);
235   } else {
236     // Column not specified set script break point on line.
237     SNPrintF(buffer,
238              "debug.Debug.setScriptBreakPointByName(\"%s\",%d)",
239              script_name, line);
240   }
241   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
242   {
243     v8::TryCatch try_catch;
244     v8::Handle<v8::String> str =
245         v8::String::NewFromUtf8(isolate, buffer.start());
246     v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
247     CHECK(!try_catch.HasCaught());
248     return value->Int32Value();
249   }
250 }
251
252
253 // Clear a break point.
254 static void ClearBreakPoint(int break_point) {
255   v8::internal::Isolate* isolate = CcTest::i_isolate();
256   v8::internal::Debug* debug = isolate->debug();
257   debug->ClearBreakPoint(
258       Handle<Object>(v8::internal::Smi::FromInt(break_point), isolate));
259 }
260
261
262 // Clear a break point using the global Debug object.
263 static void ClearBreakPointFromJS(v8::Isolate* isolate,
264                                   int break_point_number) {
265   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
266   SNPrintF(buffer,
267            "debug.Debug.clearBreakPoint(%d)",
268            break_point_number);
269   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
270   v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
271 }
272
273
274 static void EnableScriptBreakPointFromJS(v8::Isolate* isolate,
275                                          int break_point_number) {
276   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
277   SNPrintF(buffer,
278            "debug.Debug.enableScriptBreakPoint(%d)",
279            break_point_number);
280   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
281   v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
282 }
283
284
285 static void DisableScriptBreakPointFromJS(v8::Isolate* isolate,
286                                           int break_point_number) {
287   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
288   SNPrintF(buffer,
289            "debug.Debug.disableScriptBreakPoint(%d)",
290            break_point_number);
291   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
292   v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
293 }
294
295
296 static void ChangeScriptBreakPointConditionFromJS(v8::Isolate* isolate,
297                                                   int break_point_number,
298                                                   const char* condition) {
299   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
300   SNPrintF(buffer,
301            "debug.Debug.changeScriptBreakPointCondition(%d, \"%s\")",
302            break_point_number, condition);
303   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
304   v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
305 }
306
307
308 static void ChangeScriptBreakPointIgnoreCountFromJS(v8::Isolate* isolate,
309                                                     int break_point_number,
310                                                     int ignoreCount) {
311   EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
312   SNPrintF(buffer,
313            "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
314            break_point_number, ignoreCount);
315   buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
316   v8::Script::Compile(v8::String::NewFromUtf8(isolate, buffer.start()))->Run();
317 }
318
319
320 // Change break on exception.
321 static void ChangeBreakOnException(bool caught, bool uncaught) {
322   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
323   debug->ChangeBreakOnException(v8::internal::BreakException, caught);
324   debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
325 }
326
327
328 // Change break on exception using the global Debug object.
329 static void ChangeBreakOnExceptionFromJS(v8::Isolate* isolate, bool caught,
330                                          bool uncaught) {
331   if (caught) {
332     v8::Script::Compile(
333         v8::String::NewFromUtf8(isolate, "debug.Debug.setBreakOnException()"))
334         ->Run();
335   } else {
336     v8::Script::Compile(
337         v8::String::NewFromUtf8(isolate, "debug.Debug.clearBreakOnException()"))
338         ->Run();
339   }
340   if (uncaught) {
341     v8::Script::Compile(
342         v8::String::NewFromUtf8(
343             isolate, "debug.Debug.setBreakOnUncaughtException()"))->Run();
344   } else {
345     v8::Script::Compile(
346         v8::String::NewFromUtf8(
347             isolate, "debug.Debug.clearBreakOnUncaughtException()"))->Run();
348   }
349 }
350
351
352 // Prepare to step to next break location.
353 static void PrepareStep(StepAction step_action) {
354   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
355   debug->PrepareStep(step_action, 1, StackFrame::NO_ID);
356 }
357
358
359 // This function is in namespace v8::internal to be friend with class
360 // v8::internal::Debug.
361 namespace v8 {
362 namespace internal {
363
364 // Collect the currently debugged functions.
365 Handle<FixedArray> GetDebuggedFunctions() {
366   Debug* debug = CcTest::i_isolate()->debug();
367
368   v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
369
370   // Find the number of debugged functions.
371   int count = 0;
372   while (node) {
373     count++;
374     node = node->next();
375   }
376
377   // Allocate array for the debugged functions
378   Handle<FixedArray> debugged_functions =
379       CcTest::i_isolate()->factory()->NewFixedArray(count);
380
381   // Run through the debug info objects and collect all functions.
382   count = 0;
383   while (node) {
384     debugged_functions->set(count++, *node->debug_info());
385     node = node->next();
386   }
387
388   return debugged_functions;
389 }
390
391
392 // Check that the debugger has been fully unloaded.
393 void CheckDebuggerUnloaded(bool check_functions) {
394   // Check that the debugger context is cleared and that there is no debug
395   // information stored for the debugger.
396   CHECK(CcTest::i_isolate()->debug()->debug_context().is_null());
397   CHECK(!CcTest::i_isolate()->debug()->debug_info_list_);
398
399   // Collect garbage to ensure weak handles are cleared.
400   CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
401   CcTest::heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
402
403   // Iterate the head and check that there are no debugger related objects left.
404   HeapIterator iterator(CcTest::heap());
405   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
406     CHECK(!obj->IsDebugInfo());
407     CHECK(!obj->IsBreakPointInfo());
408
409     // If deep check of functions is requested check that no debug break code
410     // is left in all functions.
411     if (check_functions) {
412       if (obj->IsJSFunction()) {
413         JSFunction* fun = JSFunction::cast(obj);
414         for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) {
415           RelocInfo::Mode rmode = it.rinfo()->rmode();
416           if (RelocInfo::IsCodeTarget(rmode)) {
417             CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
418           } else if (RelocInfo::IsJSReturn(rmode)) {
419             CHECK(!it.rinfo()->IsPatchedReturnSequence());
420           }
421         }
422       }
423     }
424   }
425 }
426
427
428 } }  // namespace v8::internal
429
430
431 // Check that the debugger has been fully unloaded.
432 static void CheckDebuggerUnloaded(bool check_functions = false) {
433   // Let debugger to unload itself synchronously
434   v8::Debug::ProcessDebugMessages();
435
436   v8::internal::CheckDebuggerUnloaded(check_functions);
437 }
438
439
440 // Compile a function, set a break point and check that the call at the break
441 // location in the code is the expected debug_break function.
442 void CheckDebugBreakFunction(DebugLocalContext* env,
443                              const char* source, const char* name,
444                              int position, v8::internal::RelocInfo::Mode mode,
445                              Code* debug_break) {
446   i::Debug* debug = CcTest::i_isolate()->debug();
447
448   // Create function and set the break point.
449   Handle<i::JSFunction> fun =
450       v8::Utils::OpenHandle(*CompileFunction(env, source, name));
451   int bp = SetBreakPoint(fun, position);
452
453   // Check that the debug break function is as expected.
454   Handle<i::SharedFunctionInfo> shared(fun->shared());
455   CHECK(Debug::HasDebugInfo(shared));
456   i::BreakLocation location = i::BreakLocation::FromPosition(
457       Debug::GetDebugInfo(shared), i::SOURCE_BREAK_LOCATIONS, position,
458       i::STATEMENT_ALIGNED);
459   i::RelocInfo::Mode actual_mode = location.rmode();
460   if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
461     actual_mode = i::RelocInfo::CODE_TARGET;
462   }
463   CHECK_EQ(mode, actual_mode);
464   if (mode != i::RelocInfo::JS_RETURN) {
465     CHECK_EQ(debug_break, *location.CodeTarget());
466   } else {
467     i::RelocInfo rinfo = location.rinfo();
468     CHECK(i::RelocInfo::IsJSReturn(rinfo.rmode()));
469     CHECK(rinfo.IsPatchedReturnSequence());
470   }
471
472   // Clear the break point and check that the debug break function is no longer
473   // there
474   ClearBreakPoint(bp);
475   CHECK(!debug->HasDebugInfo(shared));
476   CHECK(debug->EnsureDebugInfo(shared, fun));
477   location = i::BreakLocation::FromPosition(Debug::GetDebugInfo(shared),
478                                             i::SOURCE_BREAK_LOCATIONS, position,
479                                             i::STATEMENT_ALIGNED);
480   actual_mode = location.rmode();
481   if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
482     actual_mode = i::RelocInfo::CODE_TARGET;
483   }
484   CHECK_EQ(mode, actual_mode);
485   if (mode == i::RelocInfo::JS_RETURN) {
486     i::RelocInfo rinfo = location.rinfo();
487     CHECK(!rinfo.IsPatchedReturnSequence());
488   }
489 }
490
491
492 // --- D e b u g   E v e n t   H a n d l e r s
493 // ---
494 // --- The different tests uses a number of debug event handlers.
495 // ---
496
497
498 // Source for the JavaScript function which picks out the function
499 // name of a frame.
500 const char* frame_function_name_source =
501     "function frame_function_name(exec_state, frame_number) {"
502     "  return exec_state.frame(frame_number).func().name();"
503     "}";
504 v8::Local<v8::Function> frame_function_name;
505
506
507 // Source for the JavaScript function which pick out the name of the
508 // first argument of a frame.
509 const char* frame_argument_name_source =
510     "function frame_argument_name(exec_state, frame_number) {"
511     "  return exec_state.frame(frame_number).argumentName(0);"
512     "}";
513 v8::Local<v8::Function> frame_argument_name;
514
515
516 // Source for the JavaScript function which pick out the value of the
517 // first argument of a frame.
518 const char* frame_argument_value_source =
519     "function frame_argument_value(exec_state, frame_number) {"
520     "  return exec_state.frame(frame_number).argumentValue(0).value_;"
521     "}";
522 v8::Local<v8::Function> frame_argument_value;
523
524
525 // Source for the JavaScript function which pick out the name of the
526 // first argument of a frame.
527 const char* frame_local_name_source =
528     "function frame_local_name(exec_state, frame_number) {"
529     "  return exec_state.frame(frame_number).localName(0);"
530     "}";
531 v8::Local<v8::Function> frame_local_name;
532
533
534 // Source for the JavaScript function which pick out the value of the
535 // first argument of a frame.
536 const char* frame_local_value_source =
537     "function frame_local_value(exec_state, frame_number) {"
538     "  return exec_state.frame(frame_number).localValue(0).value_;"
539     "}";
540 v8::Local<v8::Function> frame_local_value;
541
542
543 // Source for the JavaScript function which picks out the source line for the
544 // top frame.
545 const char* frame_source_line_source =
546     "function frame_source_line(exec_state) {"
547     "  return exec_state.frame(0).sourceLine();"
548     "}";
549 v8::Local<v8::Function> frame_source_line;
550
551
552 // Source for the JavaScript function which picks out the source column for the
553 // top frame.
554 const char* frame_source_column_source =
555     "function frame_source_column(exec_state) {"
556     "  return exec_state.frame(0).sourceColumn();"
557     "}";
558 v8::Local<v8::Function> frame_source_column;
559
560
561 // Source for the JavaScript function which picks out the script name for the
562 // top frame.
563 const char* frame_script_name_source =
564     "function frame_script_name(exec_state) {"
565     "  return exec_state.frame(0).func().script().name();"
566     "}";
567 v8::Local<v8::Function> frame_script_name;
568
569
570 // Source for the JavaScript function which returns the number of frames.
571 static const char* frame_count_source =
572     "function frame_count(exec_state) {"
573     "  return exec_state.frameCount();"
574     "}";
575 v8::Handle<v8::Function> frame_count;
576
577
578 // Global variable to store the last function hit - used by some tests.
579 char last_function_hit[80];
580
581 // Global variable to store the name for last script hit - used by some tests.
582 char last_script_name_hit[80];
583
584 // Global variables to store the last source position - used by some tests.
585 int last_source_line = -1;
586 int last_source_column = -1;
587
588 // Debug event handler which counts the break points which have been hit.
589 int break_point_hit_count = 0;
590 int break_point_hit_count_deoptimize = 0;
591 static void DebugEventBreakPointHitCount(
592     const v8::Debug::EventDetails& event_details) {
593   v8::DebugEvent event = event_details.GetEvent();
594   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
595   v8::internal::Isolate* isolate = CcTest::i_isolate();
596   Debug* debug = isolate->debug();
597   // When hitting a debug event listener there must be a break set.
598   CHECK_NE(debug->break_id(), 0);
599
600   // Count the number of breaks.
601   if (event == v8::Break) {
602     break_point_hit_count++;
603     if (!frame_function_name.IsEmpty()) {
604       // Get the name of the function.
605       const int argc = 2;
606       v8::Handle<v8::Value> argv[argc] = {
607         exec_state, v8::Integer::New(CcTest::isolate(), 0)
608       };
609       v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
610                                                                argc, argv);
611       if (result->IsUndefined()) {
612         last_function_hit[0] = '\0';
613       } else {
614         CHECK(result->IsString());
615         v8::Handle<v8::String> function_name(result.As<v8::String>());
616         function_name->WriteUtf8(last_function_hit);
617       }
618     }
619
620     if (!frame_source_line.IsEmpty()) {
621       // Get the source line.
622       const int argc = 1;
623       v8::Handle<v8::Value> argv[argc] = { exec_state };
624       v8::Handle<v8::Value> result = frame_source_line->Call(exec_state,
625                                                              argc, argv);
626       CHECK(result->IsNumber());
627       last_source_line = result->Int32Value();
628     }
629
630     if (!frame_source_column.IsEmpty()) {
631       // Get the source column.
632       const int argc = 1;
633       v8::Handle<v8::Value> argv[argc] = { exec_state };
634       v8::Handle<v8::Value> result = frame_source_column->Call(exec_state,
635                                                                argc, argv);
636       CHECK(result->IsNumber());
637       last_source_column = result->Int32Value();
638     }
639
640     if (!frame_script_name.IsEmpty()) {
641       // Get the script name of the function script.
642       const int argc = 1;
643       v8::Handle<v8::Value> argv[argc] = { exec_state };
644       v8::Handle<v8::Value> result = frame_script_name->Call(exec_state,
645                                                              argc, argv);
646       if (result->IsUndefined()) {
647         last_script_name_hit[0] = '\0';
648       } else {
649         CHECK(result->IsString());
650         v8::Handle<v8::String> script_name(result.As<v8::String>());
651         script_name->WriteUtf8(last_script_name_hit);
652       }
653     }
654
655     // Perform a full deoptimization when the specified number of
656     // breaks have been hit.
657     if (break_point_hit_count == break_point_hit_count_deoptimize) {
658       i::Deoptimizer::DeoptimizeAll(isolate);
659     }
660   }
661 }
662
663
664 // Debug event handler which counts a number of events and collects the stack
665 // height if there is a function compiled for that.
666 int exception_hit_count = 0;
667 int uncaught_exception_hit_count = 0;
668 int last_js_stack_height = -1;
669 v8::Handle<v8::Function> debug_event_listener_callback;
670 int debug_event_listener_callback_result;
671
672 static void DebugEventCounterClear() {
673   break_point_hit_count = 0;
674   exception_hit_count = 0;
675   uncaught_exception_hit_count = 0;
676 }
677
678 static void DebugEventCounter(
679     const v8::Debug::EventDetails& event_details) {
680   v8::DebugEvent event = event_details.GetEvent();
681   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
682   v8::Handle<v8::Object> event_data = event_details.GetEventData();
683   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
684
685   // When hitting a debug event listener there must be a break set.
686   CHECK_NE(debug->break_id(), 0);
687
688   // Count the number of breaks.
689   if (event == v8::Break) {
690     break_point_hit_count++;
691   } else if (event == v8::Exception) {
692     exception_hit_count++;
693
694     // Check whether the exception was uncaught.
695     v8::Local<v8::String> fun_name =
696         v8::String::NewFromUtf8(CcTest::isolate(), "uncaught");
697     v8::Local<v8::Function> fun =
698         v8::Local<v8::Function>::Cast(event_data->Get(fun_name));
699     v8::Local<v8::Value> result = fun->Call(event_data, 0, NULL);
700     if (result->IsTrue()) {
701       uncaught_exception_hit_count++;
702     }
703   }
704
705   // Collect the JavsScript stack height if the function frame_count is
706   // compiled.
707   if (!frame_count.IsEmpty()) {
708     static const int kArgc = 1;
709     v8::Handle<v8::Value> argv[kArgc] = { exec_state };
710     // Using exec_state as receiver is just to have a receiver.
711     v8::Handle<v8::Value> result = frame_count->Call(exec_state, kArgc, argv);
712     last_js_stack_height = result->Int32Value();
713   }
714
715   // Run callback from DebugEventListener and check the result.
716   if (!debug_event_listener_callback.IsEmpty()) {
717     v8::Handle<v8::Value> result =
718         debug_event_listener_callback->Call(event_data, 0, NULL);
719     CHECK(!result.IsEmpty());
720     CHECK_EQ(debug_event_listener_callback_result, result->Int32Value());
721   }
722 }
723
724
725 // Debug event handler which evaluates a number of expressions when a break
726 // point is hit. Each evaluated expression is compared with an expected value.
727 // For this debug event handler to work the following two global varaibles
728 // must be initialized.
729 //   checks: An array of expressions and expected results
730 //   evaluate_check_function: A JavaScript function (see below)
731
732 // Structure for holding checks to do.
733 struct EvaluateCheck {
734   const char* expr;  // An expression to evaluate when a break point is hit.
735   v8::Handle<v8::Value> expected;  // The expected result.
736 };
737
738
739 // Array of checks to do.
740 struct EvaluateCheck* checks = NULL;
741 // Source for The JavaScript function which can do the evaluation when a break
742 // point is hit.
743 const char* evaluate_check_source =
744     "function evaluate_check(exec_state, expr, expected) {"
745     "  return exec_state.frame(0).evaluate(expr).value() === expected;"
746     "}";
747 v8::Local<v8::Function> evaluate_check_function;
748
749 // The actual debug event described by the longer comment above.
750 static void DebugEventEvaluate(
751     const v8::Debug::EventDetails& event_details) {
752   v8::DebugEvent event = event_details.GetEvent();
753   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
754   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
755   // When hitting a debug event listener there must be a break set.
756   CHECK_NE(debug->break_id(), 0);
757
758   if (event == v8::Break) {
759     break_point_hit_count++;
760     for (int i = 0; checks[i].expr != NULL; i++) {
761       const int argc = 3;
762       v8::Handle<v8::Value> argv[argc] = {
763           exec_state,
764           v8::String::NewFromUtf8(CcTest::isolate(), checks[i].expr),
765           checks[i].expected};
766       v8::Handle<v8::Value> result =
767           evaluate_check_function->Call(exec_state, argc, argv);
768       if (!result->IsTrue()) {
769         v8::String::Utf8Value utf8(checks[i].expected);
770         V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *utf8);
771       }
772     }
773   }
774 }
775
776
777 // This debug event listener removes a breakpoint in a function
778 int debug_event_remove_break_point = 0;
779 static void DebugEventRemoveBreakPoint(
780     const v8::Debug::EventDetails& event_details) {
781   v8::DebugEvent event = event_details.GetEvent();
782   v8::Handle<v8::Value> data = event_details.GetCallbackData();
783   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
784   // When hitting a debug event listener there must be a break set.
785   CHECK_NE(debug->break_id(), 0);
786
787   if (event == v8::Break) {
788     break_point_hit_count++;
789     CHECK(data->IsFunction());
790     ClearBreakPoint(debug_event_remove_break_point);
791   }
792 }
793
794
795 // Debug event handler which counts break points hit and performs a step
796 // afterwards.
797 StepAction step_action = StepIn;  // Step action to perform when stepping.
798 static void DebugEventStep(
799     const v8::Debug::EventDetails& event_details) {
800   v8::DebugEvent event = event_details.GetEvent();
801   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
802   // When hitting a debug event listener there must be a break set.
803   CHECK_NE(debug->break_id(), 0);
804
805   if (event == v8::Break) {
806     break_point_hit_count++;
807     PrepareStep(step_action);
808   }
809 }
810
811
812 // Debug event handler which counts break points hit and performs a step
813 // afterwards. For each call the expected function is checked.
814 // For this debug event handler to work the following two global varaibles
815 // must be initialized.
816 //   expected_step_sequence: An array of the expected function call sequence.
817 //   frame_function_name: A JavaScript function (see below).
818
819 // String containing the expected function call sequence. Note: this only works
820 // if functions have name length of one.
821 const char* expected_step_sequence = NULL;
822
823 // The actual debug event described by the longer comment above.
824 static void DebugEventStepSequence(
825     const v8::Debug::EventDetails& event_details) {
826   v8::DebugEvent event = event_details.GetEvent();
827   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
828   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
829   // When hitting a debug event listener there must be a break set.
830   CHECK_NE(debug->break_id(), 0);
831
832   if (event == v8::Break || event == v8::Exception) {
833     // Check that the current function is the expected.
834     CHECK(break_point_hit_count <
835           StrLength(expected_step_sequence));
836     const int argc = 2;
837     v8::Handle<v8::Value> argv[argc] = {
838       exec_state, v8::Integer::New(CcTest::isolate(), 0)
839     };
840     v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
841                                                              argc, argv);
842     CHECK(result->IsString());
843     v8::String::Utf8Value function_name(result->ToString(CcTest::isolate()));
844     CHECK_EQ(1, StrLength(*function_name));
845     CHECK_EQ((*function_name)[0],
846               expected_step_sequence[break_point_hit_count]);
847
848     // Perform step.
849     break_point_hit_count++;
850     PrepareStep(step_action);
851   }
852 }
853
854
855 // Debug event handler which performs a garbage collection.
856 static void DebugEventBreakPointCollectGarbage(
857     const v8::Debug::EventDetails& event_details) {
858   v8::DebugEvent event = event_details.GetEvent();
859   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
860   // When hitting a debug event listener there must be a break set.
861   CHECK_NE(debug->break_id(), 0);
862
863   // Perform a garbage collection when break point is hit and continue. Based
864   // on the number of break points hit either scavenge or mark compact
865   // collector is used.
866   if (event == v8::Break) {
867     break_point_hit_count++;
868     if (break_point_hit_count % 2 == 0) {
869       // Scavenge.
870       CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
871     } else {
872       // Mark sweep compact.
873       CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
874     }
875   }
876 }
877
878
879 // Debug event handler which re-issues a debug break and calls the garbage
880 // collector to have the heap verified.
881 static void DebugEventBreak(
882     const v8::Debug::EventDetails& event_details) {
883   v8::DebugEvent event = event_details.GetEvent();
884   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
885   // When hitting a debug event listener there must be a break set.
886   CHECK_NE(debug->break_id(), 0);
887
888   if (event == v8::Break) {
889     // Count the number of breaks.
890     break_point_hit_count++;
891
892     // Run the garbage collector to enforce heap verification if option
893     // --verify-heap is set.
894     CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
895
896     // Set the break flag again to come back here as soon as possible.
897     v8::Debug::DebugBreak(CcTest::isolate());
898   }
899 }
900
901
902 // Debug event handler which re-issues a debug break until a limit has been
903 // reached.
904 int max_break_point_hit_count = 0;
905 bool terminate_after_max_break_point_hit = false;
906 static void DebugEventBreakMax(
907     const v8::Debug::EventDetails& event_details) {
908   v8::DebugEvent event = event_details.GetEvent();
909   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
910   v8::Isolate* v8_isolate = CcTest::isolate();
911   v8::internal::Isolate* isolate = CcTest::i_isolate();
912   v8::internal::Debug* debug = isolate->debug();
913   // When hitting a debug event listener there must be a break set.
914   CHECK_NE(debug->break_id(), 0);
915
916   if (event == v8::Break) {
917     if (break_point_hit_count < max_break_point_hit_count) {
918       // Count the number of breaks.
919       break_point_hit_count++;
920
921       // Collect the JavsScript stack height if the function frame_count is
922       // compiled.
923       if (!frame_count.IsEmpty()) {
924         static const int kArgc = 1;
925         v8::Handle<v8::Value> argv[kArgc] = { exec_state };
926         // Using exec_state as receiver is just to have a receiver.
927         v8::Handle<v8::Value> result =
928             frame_count->Call(exec_state, kArgc, argv);
929         last_js_stack_height = result->Int32Value();
930       }
931
932       // Set the break flag again to come back here as soon as possible.
933       v8::Debug::DebugBreak(v8_isolate);
934
935     } else if (terminate_after_max_break_point_hit) {
936       // Terminate execution after the last break if requested.
937       v8::V8::TerminateExecution(v8_isolate);
938     }
939
940     // Perform a full deoptimization when the specified number of
941     // breaks have been hit.
942     if (break_point_hit_count == break_point_hit_count_deoptimize) {
943       i::Deoptimizer::DeoptimizeAll(isolate);
944     }
945   }
946 }
947
948
949 // --- M e s s a g e   C a l l b a c k
950
951
952 // Message callback which counts the number of messages.
953 int message_callback_count = 0;
954
955 static void MessageCallbackCountClear() {
956   message_callback_count = 0;
957 }
958
959 static void MessageCallbackCount(v8::Handle<v8::Message> message,
960                                  v8::Handle<v8::Value> data) {
961   message_callback_count++;
962 }
963
964
965 // --- T h e   A c t u a l   T e s t s
966
967
968 // Test that the debug break function is the expected one for different kinds
969 // of break locations.
970 TEST(DebugStub) {
971   using ::v8::internal::Builtins;
972   using ::v8::internal::Isolate;
973   DebugLocalContext env;
974   v8::HandleScope scope(env->GetIsolate());
975
976   CheckDebugBreakFunction(&env,
977                           "function f1(){}", "f1",
978                           0,
979                           v8::internal::RelocInfo::JS_RETURN,
980                           NULL);
981   CheckDebugBreakFunction(&env,
982                           "function f2(){x=1;}", "f2",
983                           0,
984                           v8::internal::RelocInfo::CODE_TARGET,
985                           CcTest::i_isolate()->builtins()->builtin(
986                               Builtins::kStoreIC_DebugBreak));
987   CheckDebugBreakFunction(&env,
988                           "function f3(){var a=x;}", "f3",
989                           0,
990                           v8::internal::RelocInfo::CODE_TARGET,
991                           CcTest::i_isolate()->builtins()->builtin(
992                               Builtins::kLoadIC_DebugBreak));
993
994 // TODO(1240753): Make the test architecture independent or split
995 // parts of the debugger into architecture dependent files. This
996 // part currently disabled as it is not portable between IA32/ARM.
997 // Currently on ICs for keyed store/load on ARM.
998 #if !defined (__arm__) && !defined(__thumb__)
999   CheckDebugBreakFunction(
1000       &env,
1001       "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
1002       "f4",
1003       0,
1004       v8::internal::RelocInfo::CODE_TARGET,
1005       CcTest::i_isolate()->builtins()->builtin(
1006           Builtins::kKeyedStoreIC_DebugBreak));
1007   CheckDebugBreakFunction(
1008       &env,
1009       "function f5(){var index='propertyName'; var a={}; return a[index];}",
1010       "f5",
1011       0,
1012       v8::internal::RelocInfo::CODE_TARGET,
1013       CcTest::i_isolate()->builtins()->builtin(
1014           Builtins::kKeyedLoadIC_DebugBreak));
1015 #endif
1016
1017   CheckDebugBreakFunction(
1018       &env,
1019       "function f6(a){return a==null;}",
1020       "f6",
1021       0,
1022       v8::internal::RelocInfo::CODE_TARGET,
1023       CcTest::i_isolate()->builtins()->builtin(
1024           Builtins::kCompareNilIC_DebugBreak));
1025
1026   // Check the debug break code stubs for call ICs with different number of
1027   // parameters.
1028   // TODO(verwaest): XXX update test.
1029   // Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
1030   // Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
1031   // Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
1032
1033   // CheckDebugBreakFunction(&env,
1034   //                         "function f4_0(){x();}", "f4_0",
1035   //                         0,
1036   //                         v8::internal::RelocInfo::CODE_TARGET,
1037   //                         *debug_break_0);
1038
1039   // CheckDebugBreakFunction(&env,
1040   //                         "function f4_1(){x(1);}", "f4_1",
1041   //                         0,
1042   //                         v8::internal::RelocInfo::CODE_TARGET,
1043   //                         *debug_break_1);
1044
1045   // CheckDebugBreakFunction(&env,
1046   //                         "function f4_4(){x(1,2,3,4);}", "f4_4",
1047   //                         0,
1048   //                         v8::internal::RelocInfo::CODE_TARGET,
1049   //                         *debug_break_4);
1050 }
1051
1052
1053 // Test that the debug info in the VM is in sync with the functions being
1054 // debugged.
1055 TEST(DebugInfo) {
1056   DebugLocalContext env;
1057   v8::HandleScope scope(env->GetIsolate());
1058   // Create a couple of functions for the test.
1059   v8::Local<v8::Function> foo =
1060       CompileFunction(&env, "function foo(){}", "foo");
1061   v8::Local<v8::Function> bar =
1062       CompileFunction(&env, "function bar(){}", "bar");
1063   // Initially no functions are debugged.
1064   CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
1065   CHECK(!HasDebugInfo(foo));
1066   CHECK(!HasDebugInfo(bar));
1067   // One function (foo) is debugged.
1068   int bp1 = SetBreakPoint(foo, 0);
1069   CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
1070   CHECK(HasDebugInfo(foo));
1071   CHECK(!HasDebugInfo(bar));
1072   // Two functions are debugged.
1073   int bp2 = SetBreakPoint(bar, 0);
1074   CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
1075   CHECK(HasDebugInfo(foo));
1076   CHECK(HasDebugInfo(bar));
1077   // One function (bar) is debugged.
1078   ClearBreakPoint(bp1);
1079   CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
1080   CHECK(!HasDebugInfo(foo));
1081   CHECK(HasDebugInfo(bar));
1082   // No functions are debugged.
1083   ClearBreakPoint(bp2);
1084   CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
1085   CHECK(!HasDebugInfo(foo));
1086   CHECK(!HasDebugInfo(bar));
1087 }
1088
1089
1090 // Test that a break point can be set at an IC store location.
1091 TEST(BreakPointICStore) {
1092   break_point_hit_count = 0;
1093   DebugLocalContext env;
1094   v8::HandleScope scope(env->GetIsolate());
1095
1096   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1097   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1098                                               "function foo(){bar=0;}"))->Run();
1099   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1100       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1101
1102   // Run without breakpoints.
1103   foo->Call(env->Global(), 0, NULL);
1104   CHECK_EQ(0, break_point_hit_count);
1105
1106   // Run with breakpoint
1107   int bp = SetBreakPoint(foo, 0);
1108   foo->Call(env->Global(), 0, NULL);
1109   CHECK_EQ(1, break_point_hit_count);
1110   foo->Call(env->Global(), 0, NULL);
1111   CHECK_EQ(2, break_point_hit_count);
1112
1113   // Run without breakpoints.
1114   ClearBreakPoint(bp);
1115   foo->Call(env->Global(), 0, NULL);
1116   CHECK_EQ(2, break_point_hit_count);
1117
1118   v8::Debug::SetDebugEventListener(NULL);
1119   CheckDebuggerUnloaded();
1120 }
1121
1122
1123 // Test that a break point can be set at an IC load location.
1124 TEST(BreakPointICLoad) {
1125   break_point_hit_count = 0;
1126   DebugLocalContext env;
1127   v8::HandleScope scope(env->GetIsolate());
1128   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1129   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "bar=1"))
1130       ->Run();
1131   v8::Script::Compile(
1132       v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){var x=bar;}"))
1133       ->Run();
1134   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1135       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1136
1137   // Run without breakpoints.
1138   foo->Call(env->Global(), 0, NULL);
1139   CHECK_EQ(0, break_point_hit_count);
1140
1141   // Run with breakpoint.
1142   int bp = SetBreakPoint(foo, 0);
1143   foo->Call(env->Global(), 0, NULL);
1144   CHECK_EQ(1, break_point_hit_count);
1145   foo->Call(env->Global(), 0, NULL);
1146   CHECK_EQ(2, break_point_hit_count);
1147
1148   // Run without breakpoints.
1149   ClearBreakPoint(bp);
1150   foo->Call(env->Global(), 0, NULL);
1151   CHECK_EQ(2, break_point_hit_count);
1152
1153   v8::Debug::SetDebugEventListener(NULL);
1154   CheckDebuggerUnloaded();
1155 }
1156
1157
1158 // Test that a break point can be set at an IC call location.
1159 TEST(BreakPointICCall) {
1160   break_point_hit_count = 0;
1161   DebugLocalContext env;
1162   v8::HandleScope scope(env->GetIsolate());
1163   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1164   v8::Script::Compile(
1165       v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){}"))->Run();
1166   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1167                                               "function foo(){bar();}"))->Run();
1168   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1169       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1170
1171   // Run without breakpoints.
1172   foo->Call(env->Global(), 0, NULL);
1173   CHECK_EQ(0, break_point_hit_count);
1174
1175   // Run with breakpoint
1176   int bp = SetBreakPoint(foo, 0);
1177   foo->Call(env->Global(), 0, NULL);
1178   CHECK_EQ(1, break_point_hit_count);
1179   foo->Call(env->Global(), 0, NULL);
1180   CHECK_EQ(2, break_point_hit_count);
1181
1182   // Run without breakpoints.
1183   ClearBreakPoint(bp);
1184   foo->Call(env->Global(), 0, NULL);
1185   CHECK_EQ(2, break_point_hit_count);
1186
1187   v8::Debug::SetDebugEventListener(NULL);
1188   CheckDebuggerUnloaded();
1189 }
1190
1191
1192 // Test that a break point can be set at an IC call location and survive a GC.
1193 TEST(BreakPointICCallWithGC) {
1194   break_point_hit_count = 0;
1195   DebugLocalContext env;
1196   v8::HandleScope scope(env->GetIsolate());
1197   v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
1198   v8::Script::Compile(
1199       v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){return 1;}"))
1200       ->Run();
1201   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1202                                               "function foo(){return bar();}"))
1203       ->Run();
1204   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1205       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1206
1207   // Run without breakpoints.
1208   CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1209   CHECK_EQ(0, break_point_hit_count);
1210
1211   // Run with breakpoint.
1212   int bp = SetBreakPoint(foo, 0);
1213   CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1214   CHECK_EQ(1, break_point_hit_count);
1215   CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1216   CHECK_EQ(2, break_point_hit_count);
1217
1218   // Run without breakpoints.
1219   ClearBreakPoint(bp);
1220   foo->Call(env->Global(), 0, NULL);
1221   CHECK_EQ(2, break_point_hit_count);
1222
1223   v8::Debug::SetDebugEventListener(NULL);
1224   CheckDebuggerUnloaded();
1225 }
1226
1227
1228 // Test that a break point can be set at an IC call location and survive a GC.
1229 TEST(BreakPointConstructCallWithGC) {
1230   break_point_hit_count = 0;
1231   DebugLocalContext env;
1232   v8::HandleScope scope(env->GetIsolate());
1233   v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
1234   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1235                                               "function bar(){ this.x = 1;}"))
1236       ->Run();
1237   v8::Script::Compile(
1238       v8::String::NewFromUtf8(env->GetIsolate(),
1239                               "function foo(){return new bar(1).x;}"))->Run();
1240   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1241       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1242
1243   // Run without breakpoints.
1244   CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1245   CHECK_EQ(0, break_point_hit_count);
1246
1247   // Run with breakpoint.
1248   int bp = SetBreakPoint(foo, 0);
1249   CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1250   CHECK_EQ(1, break_point_hit_count);
1251   CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1252   CHECK_EQ(2, break_point_hit_count);
1253
1254   // Run without breakpoints.
1255   ClearBreakPoint(bp);
1256   foo->Call(env->Global(), 0, NULL);
1257   CHECK_EQ(2, break_point_hit_count);
1258
1259   v8::Debug::SetDebugEventListener(NULL);
1260   CheckDebuggerUnloaded();
1261 }
1262
1263
1264 // Test that a break point can be set at a return store location.
1265 TEST(BreakPointReturn) {
1266   break_point_hit_count = 0;
1267   DebugLocalContext env;
1268   v8::HandleScope scope(env->GetIsolate());
1269
1270   // Create a functions for checking the source line and column when hitting
1271   // a break point.
1272   frame_source_line = CompileFunction(&env,
1273                                       frame_source_line_source,
1274                                       "frame_source_line");
1275   frame_source_column = CompileFunction(&env,
1276                                         frame_source_column_source,
1277                                         "frame_source_column");
1278
1279
1280   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1281   v8::Script::Compile(
1282       v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){}"))->Run();
1283   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
1284       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
1285
1286   // Run without breakpoints.
1287   foo->Call(env->Global(), 0, NULL);
1288   CHECK_EQ(0, break_point_hit_count);
1289
1290   // Run with breakpoint
1291   int bp = SetBreakPoint(foo, 0);
1292   foo->Call(env->Global(), 0, NULL);
1293   CHECK_EQ(1, break_point_hit_count);
1294   CHECK_EQ(0, last_source_line);
1295   CHECK_EQ(15, last_source_column);
1296   foo->Call(env->Global(), 0, NULL);
1297   CHECK_EQ(2, break_point_hit_count);
1298   CHECK_EQ(0, last_source_line);
1299   CHECK_EQ(15, last_source_column);
1300
1301   // Run without breakpoints.
1302   ClearBreakPoint(bp);
1303   foo->Call(env->Global(), 0, NULL);
1304   CHECK_EQ(2, break_point_hit_count);
1305
1306   v8::Debug::SetDebugEventListener(NULL);
1307   CheckDebuggerUnloaded();
1308 }
1309
1310
1311 static void CallWithBreakPoints(v8::Local<v8::Object> recv,
1312                                 v8::Local<v8::Function> f,
1313                                 int break_point_count,
1314                                 int call_count) {
1315   break_point_hit_count = 0;
1316   for (int i = 0; i < call_count; i++) {
1317     f->Call(recv, 0, NULL);
1318     CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
1319   }
1320 }
1321
1322
1323 // Test GC during break point processing.
1324 TEST(GCDuringBreakPointProcessing) {
1325   break_point_hit_count = 0;
1326   DebugLocalContext env;
1327   v8::HandleScope scope(env->GetIsolate());
1328
1329   v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
1330   v8::Local<v8::Function> foo;
1331
1332   // Test IC store break point with garbage collection.
1333   foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1334   SetBreakPoint(foo, 0);
1335   CallWithBreakPoints(env->Global(), foo, 1, 10);
1336
1337   // Test IC load break point with garbage collection.
1338   foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1339   SetBreakPoint(foo, 0);
1340   CallWithBreakPoints(env->Global(), foo, 1, 10);
1341
1342   // Test IC call break point with garbage collection.
1343   foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
1344   SetBreakPoint(foo, 0);
1345   CallWithBreakPoints(env->Global(), foo, 1, 10);
1346
1347   // Test return break point with garbage collection.
1348   foo = CompileFunction(&env, "function foo(){}", "foo");
1349   SetBreakPoint(foo, 0);
1350   CallWithBreakPoints(env->Global(), foo, 1, 25);
1351
1352   // Test debug break slot break point with garbage collection.
1353   foo = CompileFunction(&env, "function foo(){var a;}", "foo");
1354   SetBreakPoint(foo, 0);
1355   CallWithBreakPoints(env->Global(), foo, 1, 25);
1356
1357   v8::Debug::SetDebugEventListener(NULL);
1358   CheckDebuggerUnloaded();
1359 }
1360
1361
1362 // Call the function three times with different garbage collections in between
1363 // and make sure that the break point survives.
1364 static void CallAndGC(v8::Local<v8::Object> recv,
1365                       v8::Local<v8::Function> f) {
1366   break_point_hit_count = 0;
1367
1368   for (int i = 0; i < 3; i++) {
1369     // Call function.
1370     f->Call(recv, 0, NULL);
1371     CHECK_EQ(1 + i * 3, break_point_hit_count);
1372
1373     // Scavenge and call function.
1374     CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
1375     f->Call(recv, 0, NULL);
1376     CHECK_EQ(2 + i * 3, break_point_hit_count);
1377
1378     // Mark sweep (and perhaps compact) and call function.
1379     CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
1380     f->Call(recv, 0, NULL);
1381     CHECK_EQ(3 + i * 3, break_point_hit_count);
1382   }
1383 }
1384
1385
1386 // Test that a break point can be set at a return store location.
1387 TEST(BreakPointSurviveGC) {
1388   break_point_hit_count = 0;
1389   DebugLocalContext env;
1390   v8::HandleScope scope(env->GetIsolate());
1391
1392   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1393   v8::Local<v8::Function> foo;
1394
1395   // Test IC store break point with garbage collection.
1396   {
1397     CompileFunction(&env, "function foo(){}", "foo");
1398     foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1399     SetBreakPoint(foo, 0);
1400   }
1401   CallAndGC(env->Global(), foo);
1402
1403   // Test IC load break point with garbage collection.
1404   {
1405     CompileFunction(&env, "function foo(){}", "foo");
1406     foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1407     SetBreakPoint(foo, 0);
1408   }
1409   CallAndGC(env->Global(), foo);
1410
1411   // Test IC call break point with garbage collection.
1412   {
1413     CompileFunction(&env, "function foo(){}", "foo");
1414     foo = CompileFunction(&env,
1415                           "function bar(){};function foo(){bar();}",
1416                           "foo");
1417     SetBreakPoint(foo, 0);
1418   }
1419   CallAndGC(env->Global(), foo);
1420
1421   // Test return break point with garbage collection.
1422   {
1423     CompileFunction(&env, "function foo(){}", "foo");
1424     foo = CompileFunction(&env, "function foo(){}", "foo");
1425     SetBreakPoint(foo, 0);
1426   }
1427   CallAndGC(env->Global(), foo);
1428
1429   // Test non IC break point with garbage collection.
1430   {
1431     CompileFunction(&env, "function foo(){}", "foo");
1432     foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
1433     SetBreakPoint(foo, 0);
1434   }
1435   CallAndGC(env->Global(), foo);
1436
1437
1438   v8::Debug::SetDebugEventListener(NULL);
1439   CheckDebuggerUnloaded();
1440 }
1441
1442
1443 // Test that break points can be set using the global Debug object.
1444 TEST(BreakPointThroughJavaScript) {
1445   break_point_hit_count = 0;
1446   DebugLocalContext env;
1447   v8::HandleScope scope(env->GetIsolate());
1448   env.ExposeDebug();
1449
1450   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1451   v8::Script::Compile(
1452       v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){}"))->Run();
1453   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
1454                                               "function foo(){bar();bar();}"))
1455       ->Run();
1456   //                                               012345678901234567890
1457   //                                                         1         2
1458   // Break points are set at position 3 and 9
1459   v8::Local<v8::Script> foo =
1460       v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "foo()"));
1461
1462   // Run without breakpoints.
1463   foo->Run();
1464   CHECK_EQ(0, break_point_hit_count);
1465
1466   // Run with one breakpoint
1467   int bp1 = SetBreakPointFromJS(env->GetIsolate(), "foo", 0, 3);
1468   foo->Run();
1469   CHECK_EQ(1, break_point_hit_count);
1470   foo->Run();
1471   CHECK_EQ(2, break_point_hit_count);
1472
1473   // Run with two breakpoints
1474   int bp2 = SetBreakPointFromJS(env->GetIsolate(), "foo", 0, 9);
1475   foo->Run();
1476   CHECK_EQ(4, break_point_hit_count);
1477   foo->Run();
1478   CHECK_EQ(6, break_point_hit_count);
1479
1480   // Run with one breakpoint
1481   ClearBreakPointFromJS(env->GetIsolate(), bp2);
1482   foo->Run();
1483   CHECK_EQ(7, break_point_hit_count);
1484   foo->Run();
1485   CHECK_EQ(8, break_point_hit_count);
1486
1487   // Run without breakpoints.
1488   ClearBreakPointFromJS(env->GetIsolate(), bp1);
1489   foo->Run();
1490   CHECK_EQ(8, break_point_hit_count);
1491
1492   v8::Debug::SetDebugEventListener(NULL);
1493   CheckDebuggerUnloaded();
1494
1495   // Make sure that the break point numbers are consecutive.
1496   CHECK_EQ(1, bp1);
1497   CHECK_EQ(2, bp2);
1498 }
1499
1500
1501 // Test that break points on scripts identified by name can be set using the
1502 // global Debug object.
1503 TEST(ScriptBreakPointByNameThroughJavaScript) {
1504   break_point_hit_count = 0;
1505   DebugLocalContext env;
1506   v8::HandleScope scope(env->GetIsolate());
1507   env.ExposeDebug();
1508
1509   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1510
1511   v8::Local<v8::String> script = v8::String::NewFromUtf8(
1512     env->GetIsolate(),
1513     "function f() {\n"
1514     "  function h() {\n"
1515     "    a = 0;  // line 2\n"
1516     "  }\n"
1517     "  b = 1;  // line 4\n"
1518     "  return h();\n"
1519     "}\n"
1520     "\n"
1521     "function g() {\n"
1522     "  function h() {\n"
1523     "    a = 0;\n"
1524     "  }\n"
1525     "  b = 2;  // line 12\n"
1526     "  h();\n"
1527     "  b = 3;  // line 14\n"
1528     "  f();    // line 15\n"
1529     "}");
1530
1531   // Compile the script and get the two functions.
1532   v8::ScriptOrigin origin =
1533       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1534   v8::Script::Compile(script, &origin)->Run();
1535   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1536       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1537   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
1538       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
1539
1540   // Call f and g without break points.
1541   break_point_hit_count = 0;
1542   f->Call(env->Global(), 0, NULL);
1543   CHECK_EQ(0, break_point_hit_count);
1544   g->Call(env->Global(), 0, NULL);
1545   CHECK_EQ(0, break_point_hit_count);
1546
1547   // Call f and g with break point on line 12.
1548   int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 12, 0);
1549   break_point_hit_count = 0;
1550   f->Call(env->Global(), 0, NULL);
1551   CHECK_EQ(0, break_point_hit_count);
1552   g->Call(env->Global(), 0, NULL);
1553   CHECK_EQ(1, break_point_hit_count);
1554
1555   // Remove the break point again.
1556   break_point_hit_count = 0;
1557   ClearBreakPointFromJS(env->GetIsolate(), sbp1);
1558   f->Call(env->Global(), 0, NULL);
1559   CHECK_EQ(0, break_point_hit_count);
1560   g->Call(env->Global(), 0, NULL);
1561   CHECK_EQ(0, break_point_hit_count);
1562
1563   // Call f and g with break point on line 2.
1564   int sbp2 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 2, 0);
1565   break_point_hit_count = 0;
1566   f->Call(env->Global(), 0, NULL);
1567   CHECK_EQ(1, break_point_hit_count);
1568   g->Call(env->Global(), 0, NULL);
1569   CHECK_EQ(2, break_point_hit_count);
1570
1571   // Call f and g with break point on line 2, 4, 12, 14 and 15.
1572   int sbp3 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 4, 0);
1573   int sbp4 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 12, 0);
1574   int sbp5 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 14, 0);
1575   int sbp6 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 15, 0);
1576   break_point_hit_count = 0;
1577   f->Call(env->Global(), 0, NULL);
1578   CHECK_EQ(2, break_point_hit_count);
1579   g->Call(env->Global(), 0, NULL);
1580   CHECK_EQ(7, break_point_hit_count);
1581
1582   // Remove all the break points again.
1583   break_point_hit_count = 0;
1584   ClearBreakPointFromJS(env->GetIsolate(), sbp2);
1585   ClearBreakPointFromJS(env->GetIsolate(), sbp3);
1586   ClearBreakPointFromJS(env->GetIsolate(), sbp4);
1587   ClearBreakPointFromJS(env->GetIsolate(), sbp5);
1588   ClearBreakPointFromJS(env->GetIsolate(), sbp6);
1589   f->Call(env->Global(), 0, NULL);
1590   CHECK_EQ(0, break_point_hit_count);
1591   g->Call(env->Global(), 0, NULL);
1592   CHECK_EQ(0, break_point_hit_count);
1593
1594   v8::Debug::SetDebugEventListener(NULL);
1595   CheckDebuggerUnloaded();
1596
1597   // Make sure that the break point numbers are consecutive.
1598   CHECK_EQ(1, sbp1);
1599   CHECK_EQ(2, sbp2);
1600   CHECK_EQ(3, sbp3);
1601   CHECK_EQ(4, sbp4);
1602   CHECK_EQ(5, sbp5);
1603   CHECK_EQ(6, sbp6);
1604 }
1605
1606
1607 TEST(ScriptBreakPointByIdThroughJavaScript) {
1608   break_point_hit_count = 0;
1609   DebugLocalContext env;
1610   v8::HandleScope scope(env->GetIsolate());
1611   env.ExposeDebug();
1612
1613   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1614
1615   v8::Local<v8::String> source = v8::String::NewFromUtf8(
1616     env->GetIsolate(),
1617     "function f() {\n"
1618     "  function h() {\n"
1619     "    a = 0;  // line 2\n"
1620     "  }\n"
1621     "  b = 1;  // line 4\n"
1622     "  return h();\n"
1623     "}\n"
1624     "\n"
1625     "function g() {\n"
1626     "  function h() {\n"
1627     "    a = 0;\n"
1628     "  }\n"
1629     "  b = 2;  // line 12\n"
1630     "  h();\n"
1631     "  b = 3;  // line 14\n"
1632     "  f();    // line 15\n"
1633     "}");
1634
1635   // Compile the script and get the two functions.
1636   v8::ScriptOrigin origin =
1637       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1638   v8::Local<v8::Script> script = v8::Script::Compile(source, &origin);
1639   script->Run();
1640   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1641       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1642   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
1643       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
1644
1645   // Get the script id knowing that internally it is a 32 integer.
1646   int script_id = script->GetUnboundScript()->GetId();
1647
1648   // Call f and g without break points.
1649   break_point_hit_count = 0;
1650   f->Call(env->Global(), 0, NULL);
1651   CHECK_EQ(0, break_point_hit_count);
1652   g->Call(env->Global(), 0, NULL);
1653   CHECK_EQ(0, break_point_hit_count);
1654
1655   // Call f and g with break point on line 12.
1656   int sbp1 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 12, 0);
1657   break_point_hit_count = 0;
1658   f->Call(env->Global(), 0, NULL);
1659   CHECK_EQ(0, break_point_hit_count);
1660   g->Call(env->Global(), 0, NULL);
1661   CHECK_EQ(1, break_point_hit_count);
1662
1663   // Remove the break point again.
1664   break_point_hit_count = 0;
1665   ClearBreakPointFromJS(env->GetIsolate(), sbp1);
1666   f->Call(env->Global(), 0, NULL);
1667   CHECK_EQ(0, break_point_hit_count);
1668   g->Call(env->Global(), 0, NULL);
1669   CHECK_EQ(0, break_point_hit_count);
1670
1671   // Call f and g with break point on line 2.
1672   int sbp2 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 2, 0);
1673   break_point_hit_count = 0;
1674   f->Call(env->Global(), 0, NULL);
1675   CHECK_EQ(1, break_point_hit_count);
1676   g->Call(env->Global(), 0, NULL);
1677   CHECK_EQ(2, break_point_hit_count);
1678
1679   // Call f and g with break point on line 2, 4, 12, 14 and 15.
1680   int sbp3 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 4, 0);
1681   int sbp4 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 12, 0);
1682   int sbp5 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 14, 0);
1683   int sbp6 = SetScriptBreakPointByIdFromJS(env->GetIsolate(), script_id, 15, 0);
1684   break_point_hit_count = 0;
1685   f->Call(env->Global(), 0, NULL);
1686   CHECK_EQ(2, break_point_hit_count);
1687   g->Call(env->Global(), 0, NULL);
1688   CHECK_EQ(7, break_point_hit_count);
1689
1690   // Remove all the break points again.
1691   break_point_hit_count = 0;
1692   ClearBreakPointFromJS(env->GetIsolate(), sbp2);
1693   ClearBreakPointFromJS(env->GetIsolate(), sbp3);
1694   ClearBreakPointFromJS(env->GetIsolate(), sbp4);
1695   ClearBreakPointFromJS(env->GetIsolate(), sbp5);
1696   ClearBreakPointFromJS(env->GetIsolate(), sbp6);
1697   f->Call(env->Global(), 0, NULL);
1698   CHECK_EQ(0, break_point_hit_count);
1699   g->Call(env->Global(), 0, NULL);
1700   CHECK_EQ(0, break_point_hit_count);
1701
1702   v8::Debug::SetDebugEventListener(NULL);
1703   CheckDebuggerUnloaded();
1704
1705   // Make sure that the break point numbers are consecutive.
1706   CHECK_EQ(1, sbp1);
1707   CHECK_EQ(2, sbp2);
1708   CHECK_EQ(3, sbp3);
1709   CHECK_EQ(4, sbp4);
1710   CHECK_EQ(5, sbp5);
1711   CHECK_EQ(6, sbp6);
1712 }
1713
1714
1715 // Test conditional script break points.
1716 TEST(EnableDisableScriptBreakPoint) {
1717   break_point_hit_count = 0;
1718   DebugLocalContext env;
1719   v8::HandleScope scope(env->GetIsolate());
1720   env.ExposeDebug();
1721
1722   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1723
1724   v8::Local<v8::String> script = v8::String::NewFromUtf8(
1725     env->GetIsolate(),
1726     "function f() {\n"
1727     "  a = 0;  // line 1\n"
1728     "};");
1729
1730   // Compile the script and get function f.
1731   v8::ScriptOrigin origin =
1732       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1733   v8::Script::Compile(script, &origin)->Run();
1734   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1735       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1736
1737   // Set script break point on line 1 (in function f).
1738   int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
1739
1740   // Call f while enabeling and disabling the script break point.
1741   break_point_hit_count = 0;
1742   f->Call(env->Global(), 0, NULL);
1743   CHECK_EQ(1, break_point_hit_count);
1744
1745   DisableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1746   f->Call(env->Global(), 0, NULL);
1747   CHECK_EQ(1, break_point_hit_count);
1748
1749   EnableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1750   f->Call(env->Global(), 0, NULL);
1751   CHECK_EQ(2, break_point_hit_count);
1752
1753   DisableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1754   f->Call(env->Global(), 0, NULL);
1755   CHECK_EQ(2, break_point_hit_count);
1756
1757   // Reload the script and get f again checking that the disabeling survives.
1758   v8::Script::Compile(script, &origin)->Run();
1759   f = v8::Local<v8::Function>::Cast(
1760       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1761   f->Call(env->Global(), 0, NULL);
1762   CHECK_EQ(2, break_point_hit_count);
1763
1764   EnableScriptBreakPointFromJS(env->GetIsolate(), sbp);
1765   f->Call(env->Global(), 0, NULL);
1766   CHECK_EQ(3, break_point_hit_count);
1767
1768   v8::Debug::SetDebugEventListener(NULL);
1769   CheckDebuggerUnloaded();
1770 }
1771
1772
1773 // Test conditional script break points.
1774 TEST(ConditionalScriptBreakPoint) {
1775   break_point_hit_count = 0;
1776   DebugLocalContext env;
1777   v8::HandleScope scope(env->GetIsolate());
1778   env.ExposeDebug();
1779
1780   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1781
1782   v8::Local<v8::String> script = v8::String::NewFromUtf8(
1783     env->GetIsolate(),
1784     "count = 0;\n"
1785     "function f() {\n"
1786     "  g(count++);  // line 2\n"
1787     "};\n"
1788     "function g(x) {\n"
1789     "  var a=x;  // line 5\n"
1790     "};");
1791
1792   // Compile the script and get function f.
1793   v8::ScriptOrigin origin =
1794       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1795   v8::Script::Compile(script, &origin)->Run();
1796   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1797       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1798
1799   // Set script break point on line 5 (in function g).
1800   int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 5, 0);
1801
1802   // Call f with different conditions on the script break point.
1803   break_point_hit_count = 0;
1804   ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "false");
1805   f->Call(env->Global(), 0, NULL);
1806   CHECK_EQ(0, break_point_hit_count);
1807
1808   ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "true");
1809   break_point_hit_count = 0;
1810   f->Call(env->Global(), 0, NULL);
1811   CHECK_EQ(1, break_point_hit_count);
1812
1813   ChangeScriptBreakPointConditionFromJS(env->GetIsolate(), sbp1, "x % 2 == 0");
1814   break_point_hit_count = 0;
1815   for (int i = 0; i < 10; i++) {
1816     f->Call(env->Global(), 0, NULL);
1817   }
1818   CHECK_EQ(5, break_point_hit_count);
1819
1820   // Reload the script and get f again checking that the condition survives.
1821   v8::Script::Compile(script, &origin)->Run();
1822   f = v8::Local<v8::Function>::Cast(
1823       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1824
1825   break_point_hit_count = 0;
1826   for (int i = 0; i < 10; i++) {
1827     f->Call(env->Global(), 0, NULL);
1828   }
1829   CHECK_EQ(5, break_point_hit_count);
1830
1831   v8::Debug::SetDebugEventListener(NULL);
1832   CheckDebuggerUnloaded();
1833 }
1834
1835
1836 // Test ignore count on script break points.
1837 TEST(ScriptBreakPointIgnoreCount) {
1838   break_point_hit_count = 0;
1839   DebugLocalContext env;
1840   v8::HandleScope scope(env->GetIsolate());
1841   env.ExposeDebug();
1842
1843   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1844
1845   v8::Local<v8::String> script = v8::String::NewFromUtf8(
1846     env->GetIsolate(),
1847     "function f() {\n"
1848     "  a = 0;  // line 1\n"
1849     "};");
1850
1851   // Compile the script and get function f.
1852   v8::ScriptOrigin origin =
1853       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1854   v8::Script::Compile(script, &origin)->Run();
1855   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
1856       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1857
1858   // Set script break point on line 1 (in function f).
1859   int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
1860
1861   // Call f with different ignores on the script break point.
1862   break_point_hit_count = 0;
1863   ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 1);
1864   f->Call(env->Global(), 0, NULL);
1865   CHECK_EQ(0, break_point_hit_count);
1866   f->Call(env->Global(), 0, NULL);
1867   CHECK_EQ(1, break_point_hit_count);
1868
1869   ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 5);
1870   break_point_hit_count = 0;
1871   for (int i = 0; i < 10; i++) {
1872     f->Call(env->Global(), 0, NULL);
1873   }
1874   CHECK_EQ(5, break_point_hit_count);
1875
1876   // Reload the script and get f again checking that the ignore survives.
1877   v8::Script::Compile(script, &origin)->Run();
1878   f = v8::Local<v8::Function>::Cast(
1879       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1880
1881   break_point_hit_count = 0;
1882   for (int i = 0; i < 10; i++) {
1883     f->Call(env->Global(), 0, NULL);
1884   }
1885   CHECK_EQ(5, break_point_hit_count);
1886
1887   v8::Debug::SetDebugEventListener(NULL);
1888   CheckDebuggerUnloaded();
1889 }
1890
1891
1892 // Test that script break points survive when a script is reloaded.
1893 TEST(ScriptBreakPointReload) {
1894   break_point_hit_count = 0;
1895   DebugLocalContext env;
1896   v8::HandleScope scope(env->GetIsolate());
1897   env.ExposeDebug();
1898
1899   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1900
1901   v8::Local<v8::Function> f;
1902   v8::Local<v8::String> script = v8::String::NewFromUtf8(
1903     env->GetIsolate(),
1904     "function f() {\n"
1905     "  function h() {\n"
1906     "    a = 0;  // line 2\n"
1907     "  }\n"
1908     "  b = 1;  // line 4\n"
1909     "  return h();\n"
1910     "}");
1911
1912   v8::ScriptOrigin origin_1 =
1913       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "1"));
1914   v8::ScriptOrigin origin_2 =
1915       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "2"));
1916
1917   // Set a script break point before the script is loaded.
1918   SetScriptBreakPointByNameFromJS(env->GetIsolate(), "1", 2, 0);
1919
1920   // Compile the script and get the function.
1921   v8::Script::Compile(script, &origin_1)->Run();
1922   f = v8::Local<v8::Function>::Cast(
1923       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1924
1925   // Call f and check that the script break point is active.
1926   break_point_hit_count = 0;
1927   f->Call(env->Global(), 0, NULL);
1928   CHECK_EQ(1, break_point_hit_count);
1929
1930   // Compile the script again with a different script data and get the
1931   // function.
1932   v8::Script::Compile(script, &origin_2)->Run();
1933   f = v8::Local<v8::Function>::Cast(
1934       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1935
1936   // Call f and check that no break points are set.
1937   break_point_hit_count = 0;
1938   f->Call(env->Global(), 0, NULL);
1939   CHECK_EQ(0, break_point_hit_count);
1940
1941   // Compile the script again and get the function.
1942   v8::Script::Compile(script, &origin_1)->Run();
1943   f = v8::Local<v8::Function>::Cast(
1944       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1945
1946   // Call f and check that the script break point is active.
1947   break_point_hit_count = 0;
1948   f->Call(env->Global(), 0, NULL);
1949   CHECK_EQ(1, break_point_hit_count);
1950
1951   v8::Debug::SetDebugEventListener(NULL);
1952   CheckDebuggerUnloaded();
1953 }
1954
1955
1956 // Test when several scripts has the same script data
1957 TEST(ScriptBreakPointMultiple) {
1958   break_point_hit_count = 0;
1959   DebugLocalContext env;
1960   v8::HandleScope scope(env->GetIsolate());
1961   env.ExposeDebug();
1962
1963   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
1964
1965   v8::Local<v8::Function> f;
1966   v8::Local<v8::String> script_f =
1967       v8::String::NewFromUtf8(env->GetIsolate(),
1968                               "function f() {\n"
1969                               "  a = 0;  // line 1\n"
1970                               "}");
1971
1972   v8::Local<v8::Function> g;
1973   v8::Local<v8::String> script_g =
1974       v8::String::NewFromUtf8(env->GetIsolate(),
1975                               "function g() {\n"
1976                               "  b = 0;  // line 1\n"
1977                               "}");
1978
1979   v8::ScriptOrigin origin =
1980       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
1981
1982   // Set a script break point before the scripts are loaded.
1983   int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
1984
1985   // Compile the scripts with same script data and get the functions.
1986   v8::Script::Compile(script_f, &origin)->Run();
1987   f = v8::Local<v8::Function>::Cast(
1988       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
1989   v8::Script::Compile(script_g, &origin)->Run();
1990   g = v8::Local<v8::Function>::Cast(
1991       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
1992
1993   // Call f and g and check that the script break point is active.
1994   break_point_hit_count = 0;
1995   f->Call(env->Global(), 0, NULL);
1996   CHECK_EQ(1, break_point_hit_count);
1997   g->Call(env->Global(), 0, NULL);
1998   CHECK_EQ(2, break_point_hit_count);
1999
2000   // Clear the script break point.
2001   ClearBreakPointFromJS(env->GetIsolate(), sbp);
2002
2003   // Call f and g and check that the script break point is no longer active.
2004   break_point_hit_count = 0;
2005   f->Call(env->Global(), 0, NULL);
2006   CHECK_EQ(0, break_point_hit_count);
2007   g->Call(env->Global(), 0, NULL);
2008   CHECK_EQ(0, break_point_hit_count);
2009
2010   // Set script break point with the scripts loaded.
2011   sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
2012
2013   // Call f and g and check that the script break point is active.
2014   break_point_hit_count = 0;
2015   f->Call(env->Global(), 0, NULL);
2016   CHECK_EQ(1, break_point_hit_count);
2017   g->Call(env->Global(), 0, NULL);
2018   CHECK_EQ(2, break_point_hit_count);
2019
2020   v8::Debug::SetDebugEventListener(NULL);
2021   CheckDebuggerUnloaded();
2022 }
2023
2024
2025 // Test the script origin which has both name and line offset.
2026 TEST(ScriptBreakPointLineOffset) {
2027   break_point_hit_count = 0;
2028   DebugLocalContext env;
2029   v8::HandleScope scope(env->GetIsolate());
2030   env.ExposeDebug();
2031
2032   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2033
2034   v8::Local<v8::Function> f;
2035   v8::Local<v8::String> script = v8::String::NewFromUtf8(
2036       env->GetIsolate(),
2037       "function f() {\n"
2038       "  a = 0;  // line 8 as this script has line offset 7\n"
2039       "  b = 0;  // line 9 as this script has line offset 7\n"
2040       "}");
2041
2042   // Create script origin both name and line offset.
2043   v8::ScriptOrigin origin(
2044       v8::String::NewFromUtf8(env->GetIsolate(), "test.html"),
2045       v8::Integer::New(env->GetIsolate(), 7));
2046
2047   // Set two script break points before the script is loaded.
2048   int sbp1 =
2049       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 8, 0);
2050   int sbp2 =
2051       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0);
2052
2053   // Compile the script and get the function.
2054   v8::Script::Compile(script, &origin)->Run();
2055   f = v8::Local<v8::Function>::Cast(
2056       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
2057
2058   // Call f and check that the script break point is active.
2059   break_point_hit_count = 0;
2060   f->Call(env->Global(), 0, NULL);
2061   CHECK_EQ(2, break_point_hit_count);
2062
2063   // Clear the script break points.
2064   ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2065   ClearBreakPointFromJS(env->GetIsolate(), sbp2);
2066
2067   // Call f and check that no script break points are active.
2068   break_point_hit_count = 0;
2069   f->Call(env->Global(), 0, NULL);
2070   CHECK_EQ(0, break_point_hit_count);
2071
2072   // Set a script break point with the script loaded.
2073   sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0);
2074
2075   // Call f and check that the script break point is active.
2076   break_point_hit_count = 0;
2077   f->Call(env->Global(), 0, NULL);
2078   CHECK_EQ(1, break_point_hit_count);
2079
2080   v8::Debug::SetDebugEventListener(NULL);
2081   CheckDebuggerUnloaded();
2082 }
2083
2084
2085 // Test script break points set on lines.
2086 TEST(ScriptBreakPointLine) {
2087   DebugLocalContext env;
2088   v8::HandleScope scope(env->GetIsolate());
2089   env.ExposeDebug();
2090
2091   // Create a function for checking the function when hitting a break point.
2092   frame_function_name = CompileFunction(&env,
2093                                         frame_function_name_source,
2094                                         "frame_function_name");
2095
2096   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2097
2098   v8::Local<v8::Function> f;
2099   v8::Local<v8::Function> g;
2100   v8::Local<v8::String> script =
2101       v8::String::NewFromUtf8(env->GetIsolate(),
2102                               "a = 0                      // line 0\n"
2103                               "function f() {\n"
2104                               "  a = 1;                   // line 2\n"
2105                               "}\n"
2106                               " a = 2;                    // line 4\n"
2107                               "  /* xx */ function g() {  // line 5\n"
2108                               "    function h() {         // line 6\n"
2109                               "      a = 3;               // line 7\n"
2110                               "    }\n"
2111                               "    h();                   // line 9\n"
2112                               "    a = 4;                 // line 10\n"
2113                               "  }\n"
2114                               " a=5;                      // line 12");
2115
2116   // Set a couple script break point before the script is loaded.
2117   int sbp1 =
2118       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 0, -1);
2119   int sbp2 =
2120       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 1, -1);
2121   int sbp3 =
2122       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 5, -1);
2123
2124   // Compile the script and get the function.
2125   break_point_hit_count = 0;
2126   v8::ScriptOrigin origin(
2127       v8::String::NewFromUtf8(env->GetIsolate(), "test.html"),
2128       v8::Integer::New(env->GetIsolate(), 0));
2129   v8::Script::Compile(script, &origin)->Run();
2130   f = v8::Local<v8::Function>::Cast(
2131       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
2132   g = v8::Local<v8::Function>::Cast(
2133       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
2134
2135   // Check that a break point was hit when the script was run.
2136   CHECK_EQ(1, break_point_hit_count);
2137   CHECK_EQ(0, StrLength(last_function_hit));
2138
2139   // Call f and check that the script break point.
2140   f->Call(env->Global(), 0, NULL);
2141   CHECK_EQ(2, break_point_hit_count);
2142   CHECK_EQ(0, strcmp("f", last_function_hit));
2143
2144   // Call g and check that the script break point.
2145   g->Call(env->Global(), 0, NULL);
2146   CHECK_EQ(3, break_point_hit_count);
2147   CHECK_EQ(0, strcmp("g", last_function_hit));
2148
2149   // Clear the script break point on g and set one on h.
2150   ClearBreakPointFromJS(env->GetIsolate(), sbp3);
2151   int sbp4 =
2152       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 6, -1);
2153
2154   // Call g and check that the script break point in h is hit.
2155   g->Call(env->Global(), 0, NULL);
2156   CHECK_EQ(4, break_point_hit_count);
2157   CHECK_EQ(0, strcmp("h", last_function_hit));
2158
2159   // Clear break points in f and h. Set a new one in the script between
2160   // functions f and g and test that there is no break points in f and g any
2161   // more.
2162   ClearBreakPointFromJS(env->GetIsolate(), sbp2);
2163   ClearBreakPointFromJS(env->GetIsolate(), sbp4);
2164   int sbp5 =
2165       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 4, -1);
2166   break_point_hit_count = 0;
2167   f->Call(env->Global(), 0, NULL);
2168   g->Call(env->Global(), 0, NULL);
2169   CHECK_EQ(0, break_point_hit_count);
2170
2171   // Reload the script which should hit two break points.
2172   break_point_hit_count = 0;
2173   v8::Script::Compile(script, &origin)->Run();
2174   CHECK_EQ(2, break_point_hit_count);
2175   CHECK_EQ(0, StrLength(last_function_hit));
2176
2177   // Set a break point in the code after the last function decleration.
2178   int sbp6 =
2179       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 12, -1);
2180
2181   // Reload the script which should hit three break points.
2182   break_point_hit_count = 0;
2183   v8::Script::Compile(script, &origin)->Run();
2184   CHECK_EQ(3, break_point_hit_count);
2185   CHECK_EQ(0, StrLength(last_function_hit));
2186
2187   // Clear the last break points, and reload the script which should not hit any
2188   // break points.
2189   ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2190   ClearBreakPointFromJS(env->GetIsolate(), sbp5);
2191   ClearBreakPointFromJS(env->GetIsolate(), sbp6);
2192   break_point_hit_count = 0;
2193   v8::Script::Compile(script, &origin)->Run();
2194   CHECK_EQ(0, break_point_hit_count);
2195
2196   v8::Debug::SetDebugEventListener(NULL);
2197   CheckDebuggerUnloaded();
2198 }
2199
2200
2201 // Test top level script break points set on lines.
2202 TEST(ScriptBreakPointLineTopLevel) {
2203   DebugLocalContext env;
2204   v8::HandleScope scope(env->GetIsolate());
2205   env.ExposeDebug();
2206
2207   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2208
2209   v8::Local<v8::String> script =
2210       v8::String::NewFromUtf8(env->GetIsolate(),
2211                               "function f() {\n"
2212                               "  a = 1;                   // line 1\n"
2213                               "}\n"
2214                               "a = 2;                     // line 3\n");
2215   v8::Local<v8::Function> f;
2216   {
2217     v8::HandleScope scope(env->GetIsolate());
2218     CompileRunWithOrigin(script, "test.html");
2219   }
2220   f = v8::Local<v8::Function>::Cast(
2221       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
2222
2223   CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
2224
2225   SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
2226
2227   // Call f and check that there was no break points.
2228   break_point_hit_count = 0;
2229   f->Call(env->Global(), 0, NULL);
2230   CHECK_EQ(0, break_point_hit_count);
2231
2232   // Recompile and run script and check that break point was hit.
2233   break_point_hit_count = 0;
2234   CompileRunWithOrigin(script, "test.html");
2235   CHECK_EQ(1, break_point_hit_count);
2236
2237   // Call f and check that there are still no break points.
2238   break_point_hit_count = 0;
2239   f = v8::Local<v8::Function>::Cast(
2240       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
2241   CHECK_EQ(0, break_point_hit_count);
2242
2243   v8::Debug::SetDebugEventListener(NULL);
2244   CheckDebuggerUnloaded();
2245 }
2246
2247
2248 // Test that it is possible to add and remove break points in a top level
2249 // function which has no references but has not been collected yet.
2250 TEST(ScriptBreakPointTopLevelCrash) {
2251   DebugLocalContext env;
2252   v8::HandleScope scope(env->GetIsolate());
2253   env.ExposeDebug();
2254
2255   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2256
2257   v8::Local<v8::String> script_source =
2258       v8::String::NewFromUtf8(env->GetIsolate(),
2259                               "function f() {\n"
2260                               "  return 0;\n"
2261                               "}\n"
2262                               "f()");
2263
2264   int sbp1 =
2265       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
2266   {
2267     v8::HandleScope scope(env->GetIsolate());
2268     break_point_hit_count = 0;
2269     CompileRunWithOrigin(script_source, "test.html");
2270     CHECK_EQ(1, break_point_hit_count);
2271   }
2272
2273   int sbp2 =
2274       SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1);
2275   ClearBreakPointFromJS(env->GetIsolate(), sbp1);
2276   ClearBreakPointFromJS(env->GetIsolate(), sbp2);
2277
2278   v8::Debug::SetDebugEventListener(NULL);
2279   CheckDebuggerUnloaded();
2280 }
2281
2282
2283 // Test that it is possible to remove the last break point for a function
2284 // inside the break handling of that break point.
2285 TEST(RemoveBreakPointInBreak) {
2286   DebugLocalContext env;
2287   v8::HandleScope scope(env->GetIsolate());
2288
2289   v8::Local<v8::Function> foo =
2290       CompileFunction(&env, "function foo(){a=1;}", "foo");
2291   debug_event_remove_break_point = SetBreakPoint(foo, 0);
2292
2293   // Register the debug event listener pasing the function
2294   v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo);
2295
2296   break_point_hit_count = 0;
2297   foo->Call(env->Global(), 0, NULL);
2298   CHECK_EQ(1, break_point_hit_count);
2299
2300   break_point_hit_count = 0;
2301   foo->Call(env->Global(), 0, NULL);
2302   CHECK_EQ(0, break_point_hit_count);
2303
2304   v8::Debug::SetDebugEventListener(NULL);
2305   CheckDebuggerUnloaded();
2306 }
2307
2308
2309 // Test that the debugger statement causes a break.
2310 TEST(DebuggerStatement) {
2311   break_point_hit_count = 0;
2312   DebugLocalContext env;
2313   v8::HandleScope scope(env->GetIsolate());
2314   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2315   v8::Script::Compile(
2316       v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){debugger}"))
2317       ->Run();
2318   v8::Script::Compile(
2319       v8::String::NewFromUtf8(env->GetIsolate(),
2320                               "function foo(){debugger;debugger;}"))->Run();
2321   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
2322       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
2323   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
2324       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "bar")));
2325
2326   // Run function with debugger statement
2327   bar->Call(env->Global(), 0, NULL);
2328   CHECK_EQ(1, break_point_hit_count);
2329
2330   // Run function with two debugger statement
2331   foo->Call(env->Global(), 0, NULL);
2332   CHECK_EQ(3, break_point_hit_count);
2333
2334   v8::Debug::SetDebugEventListener(NULL);
2335   CheckDebuggerUnloaded();
2336 }
2337
2338
2339 // Test setting a breakpoint on the debugger statement.
2340 TEST(DebuggerStatementBreakpoint) {
2341     break_point_hit_count = 0;
2342     DebugLocalContext env;
2343     v8::HandleScope scope(env->GetIsolate());
2344     v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2345     v8::Script::Compile(
2346         v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){debugger;}"))
2347         ->Run();
2348     v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
2349         env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
2350
2351     // The debugger statement triggers breakpint hit
2352     foo->Call(env->Global(), 0, NULL);
2353     CHECK_EQ(1, break_point_hit_count);
2354
2355     int bp = SetBreakPoint(foo, 0);
2356
2357     // Set breakpoint does not duplicate hits
2358     foo->Call(env->Global(), 0, NULL);
2359     CHECK_EQ(2, break_point_hit_count);
2360
2361     ClearBreakPoint(bp);
2362     v8::Debug::SetDebugEventListener(NULL);
2363     CheckDebuggerUnloaded();
2364 }
2365
2366
2367 // Test that the evaluation of expressions when a break point is hit generates
2368 // the correct results.
2369 TEST(DebugEvaluate) {
2370   DebugLocalContext env;
2371   v8::Isolate* isolate = env->GetIsolate();
2372   v8::HandleScope scope(isolate);
2373   env.ExposeDebug();
2374
2375   // Create a function for checking the evaluation when hitting a break point.
2376   evaluate_check_function = CompileFunction(&env,
2377                                             evaluate_check_source,
2378                                             "evaluate_check");
2379   // Register the debug event listener
2380   v8::Debug::SetDebugEventListener(DebugEventEvaluate);
2381
2382   // Different expected vaules of x and a when in a break point (u = undefined,
2383   // d = Hello, world!).
2384   struct EvaluateCheck checks_uu[] = {
2385     {"x", v8::Undefined(isolate)},
2386     {"a", v8::Undefined(isolate)},
2387     {NULL, v8::Handle<v8::Value>()}
2388   };
2389   struct EvaluateCheck checks_hu[] = {
2390     {"x", v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")},
2391     {"a", v8::Undefined(isolate)},
2392     {NULL, v8::Handle<v8::Value>()}
2393   };
2394   struct EvaluateCheck checks_hh[] = {
2395     {"x", v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")},
2396     {"a", v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")},
2397     {NULL, v8::Handle<v8::Value>()}
2398   };
2399
2400   // Simple test function. The "y=0" is in the function foo to provide a break
2401   // location. For "y=0" the "y" is at position 15 in the foo function
2402   // therefore setting breakpoint at position 15 will break at "y=0" and
2403   // setting it higher will break after.
2404   v8::Local<v8::Function> foo = CompileFunction(&env,
2405     "function foo(x) {"
2406     "  var a;"
2407     "  y=0;"  // To ensure break location 1.
2408     "  a=x;"
2409     "  y=0;"  // To ensure break location 2.
2410     "}",
2411     "foo");
2412   const int foo_break_position_1 = 15;
2413   const int foo_break_position_2 = 29;
2414
2415   // Arguments with one parameter "Hello, world!"
2416   v8::Handle<v8::Value> argv_foo[1] = {
2417       v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")};
2418
2419   // Call foo with breakpoint set before a=x and undefined as parameter.
2420   int bp = SetBreakPoint(foo, foo_break_position_1);
2421   checks = checks_uu;
2422   foo->Call(env->Global(), 0, NULL);
2423
2424   // Call foo with breakpoint set before a=x and parameter "Hello, world!".
2425   checks = checks_hu;
2426   foo->Call(env->Global(), 1, argv_foo);
2427
2428   // Call foo with breakpoint set after a=x and parameter "Hello, world!".
2429   ClearBreakPoint(bp);
2430   SetBreakPoint(foo, foo_break_position_2);
2431   checks = checks_hh;
2432   foo->Call(env->Global(), 1, argv_foo);
2433
2434   // Test that overriding Object.prototype will not interfere into evaluation
2435   // on call frame.
2436   v8::Local<v8::Function> zoo =
2437       CompileFunction(&env,
2438                       "x = undefined;"
2439                       "function zoo(t) {"
2440                       "  var a=x;"
2441                       "  Object.prototype.x = 42;"
2442                       "  x=t;"
2443                       "  y=0;"  // To ensure break location.
2444                       "  delete Object.prototype.x;"
2445                       "  x=a;"
2446                       "}",
2447                       "zoo");
2448   const int zoo_break_position = 50;
2449
2450   // Arguments with one parameter "Hello, world!"
2451   v8::Handle<v8::Value> argv_zoo[1] = {
2452       v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!")};
2453
2454   // Call zoo with breakpoint set at y=0.
2455   DebugEventCounterClear();
2456   bp = SetBreakPoint(zoo, zoo_break_position);
2457   checks = checks_hu;
2458   zoo->Call(env->Global(), 1, argv_zoo);
2459   CHECK_EQ(1, break_point_hit_count);
2460   ClearBreakPoint(bp);
2461
2462   // Test function with an inner function. The "y=0" is in function barbar
2463   // to provide a break location. For "y=0" the "y" is at position 8 in the
2464   // barbar function therefore setting breakpoint at position 8 will break at
2465   // "y=0" and setting it higher will break after.
2466   v8::Local<v8::Function> bar = CompileFunction(&env,
2467     "y = 0;"
2468     "x = 'Goodbye, world!';"
2469     "function bar(x, b) {"
2470     "  var a;"
2471     "  function barbar() {"
2472     "    y=0; /* To ensure break location.*/"
2473     "    a=x;"
2474     "  };"
2475     "  debug.Debug.clearAllBreakPoints();"
2476     "  barbar();"
2477     "  y=0;a=x;"
2478     "}",
2479     "bar");
2480   const int barbar_break_position = 8;
2481
2482   // Call bar setting breakpoint before a=x in barbar and undefined as
2483   // parameter.
2484   checks = checks_uu;
2485   v8::Handle<v8::Value> argv_bar_1[2] = {
2486     v8::Undefined(isolate),
2487     v8::Number::New(isolate, barbar_break_position)
2488   };
2489   bar->Call(env->Global(), 2, argv_bar_1);
2490
2491   // Call bar setting breakpoint before a=x in barbar and parameter
2492   // "Hello, world!".
2493   checks = checks_hu;
2494   v8::Handle<v8::Value> argv_bar_2[2] = {
2495     v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!"),
2496     v8::Number::New(env->GetIsolate(), barbar_break_position)
2497   };
2498   bar->Call(env->Global(), 2, argv_bar_2);
2499
2500   // Call bar setting breakpoint after a=x in barbar and parameter
2501   // "Hello, world!".
2502   checks = checks_hh;
2503   v8::Handle<v8::Value> argv_bar_3[2] = {
2504     v8::String::NewFromUtf8(env->GetIsolate(), "Hello, world!"),
2505     v8::Number::New(env->GetIsolate(), barbar_break_position + 1)
2506   };
2507   bar->Call(env->Global(), 2, argv_bar_3);
2508
2509   v8::Debug::SetDebugEventListener(NULL);
2510   CheckDebuggerUnloaded();
2511 }
2512
2513
2514 int debugEventCount = 0;
2515 static void CheckDebugEvent(const v8::Debug::EventDetails& eventDetails) {
2516   if (eventDetails.GetEvent() == v8::Break) ++debugEventCount;
2517 }
2518
2519
2520 // Test that the conditional breakpoints work event if code generation from
2521 // strings is prohibited in the debugee context.
2522 TEST(ConditionalBreakpointWithCodeGenerationDisallowed) {
2523   DebugLocalContext env;
2524   v8::HandleScope scope(env->GetIsolate());
2525   env.ExposeDebug();
2526
2527   v8::Debug::SetDebugEventListener(CheckDebugEvent);
2528
2529   v8::Local<v8::Function> foo = CompileFunction(&env,
2530     "function foo(x) {\n"
2531     "  var s = 'String value2';\n"
2532     "  return s + x;\n"
2533     "}",
2534     "foo");
2535
2536   // Set conditional breakpoint with condition 'true'.
2537   CompileRun("debug.Debug.setBreakPoint(foo, 2, 0, 'true')");
2538
2539   debugEventCount = 0;
2540   env->AllowCodeGenerationFromStrings(false);
2541   foo->Call(env->Global(), 0, NULL);
2542   CHECK_EQ(1, debugEventCount);
2543
2544   v8::Debug::SetDebugEventListener(NULL);
2545   CheckDebuggerUnloaded();
2546 }
2547
2548
2549 bool checkedDebugEvals = true;
2550 v8::Handle<v8::Function> checkGlobalEvalFunction;
2551 v8::Handle<v8::Function> checkFrameEvalFunction;
2552 static void CheckDebugEval(const v8::Debug::EventDetails& eventDetails) {
2553   if (eventDetails.GetEvent() == v8::Break) {
2554     ++debugEventCount;
2555     v8::HandleScope handleScope(CcTest::isolate());
2556
2557     v8::Handle<v8::Value> args[] = { eventDetails.GetExecutionState() };
2558     CHECK(checkGlobalEvalFunction->Call(
2559         eventDetails.GetEventContext()->Global(), 1, args)->IsTrue());
2560     CHECK(checkFrameEvalFunction->Call(
2561         eventDetails.GetEventContext()->Global(), 1, args)->IsTrue());
2562   }
2563 }
2564
2565
2566 // Test that the evaluation of expressions when a break point is hit generates
2567 // the correct results in case code generation from strings is disallowed in the
2568 // debugee context.
2569 TEST(DebugEvaluateWithCodeGenerationDisallowed) {
2570   DebugLocalContext env;
2571   v8::HandleScope scope(env->GetIsolate());
2572   env.ExposeDebug();
2573
2574   v8::Debug::SetDebugEventListener(CheckDebugEval);
2575
2576   v8::Local<v8::Function> foo = CompileFunction(&env,
2577     "var global = 'Global';\n"
2578     "function foo(x) {\n"
2579     "  var local = 'Local';\n"
2580     "  debugger;\n"
2581     "  return local + x;\n"
2582     "}",
2583     "foo");
2584   checkGlobalEvalFunction = CompileFunction(&env,
2585     "function checkGlobalEval(exec_state) {\n"
2586     "  return exec_state.evaluateGlobal('global').value() === 'Global';\n"
2587     "}",
2588     "checkGlobalEval");
2589
2590   checkFrameEvalFunction = CompileFunction(&env,
2591     "function checkFrameEval(exec_state) {\n"
2592     "  return exec_state.frame(0).evaluate('local').value() === 'Local';\n"
2593     "}",
2594     "checkFrameEval");
2595   debugEventCount = 0;
2596   env->AllowCodeGenerationFromStrings(false);
2597   foo->Call(env->Global(), 0, NULL);
2598   CHECK_EQ(1, debugEventCount);
2599
2600   checkGlobalEvalFunction.Clear();
2601   checkFrameEvalFunction.Clear();
2602   v8::Debug::SetDebugEventListener(NULL);
2603   CheckDebuggerUnloaded();
2604 }
2605
2606
2607 // Copies a C string to a 16-bit string.  Does not check for buffer overflow.
2608 // Does not use the V8 engine to convert strings, so it can be used
2609 // in any thread.  Returns the length of the string.
2610 int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
2611   int i;
2612   for (i = 0; input_buffer[i] != '\0'; ++i) {
2613     // ASCII does not use chars > 127, but be careful anyway.
2614     output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
2615   }
2616   output_buffer[i] = 0;
2617   return i;
2618 }
2619
2620
2621 // Copies a 16-bit string to a C string by dropping the high byte of
2622 // each character.  Does not check for buffer overflow.
2623 // Can be used in any thread.  Requires string length as an input.
2624 int Utf16ToAscii(const uint16_t* input_buffer, int length,
2625                  char* output_buffer, int output_len = -1) {
2626   if (output_len >= 0) {
2627     if (length > output_len - 1) {
2628       length = output_len - 1;
2629     }
2630   }
2631
2632   for (int i = 0; i < length; ++i) {
2633     output_buffer[i] = static_cast<char>(input_buffer[i]);
2634   }
2635   output_buffer[length] = '\0';
2636   return length;
2637 }
2638
2639
2640 // We match parts of the message to get evaluate result int value.
2641 bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
2642   if (strstr(message, "\"command\":\"evaluate\"") == NULL) {
2643     return false;
2644   }
2645   const char* prefix = "\"text\":\"";
2646   char* pos1 = strstr(message, prefix);
2647   if (pos1 == NULL) {
2648     return false;
2649   }
2650   pos1 += strlen(prefix);
2651   char* pos2 = strchr(pos1, '"');
2652   if (pos2 == NULL) {
2653     return false;
2654   }
2655   Vector<char> buf(buffer, buffer_size);
2656   int len = static_cast<int>(pos2 - pos1);
2657   if (len > buffer_size - 1) {
2658     len = buffer_size - 1;
2659   }
2660   StrNCpy(buf, pos1, len);
2661   buffer[buffer_size - 1] = '\0';
2662   return true;
2663 }
2664
2665
2666 struct EvaluateResult {
2667   static const int kBufferSize = 20;
2668   char buffer[kBufferSize];
2669 };
2670
2671 struct DebugProcessDebugMessagesData {
2672   static const int kArraySize = 5;
2673   int counter;
2674   EvaluateResult results[kArraySize];
2675
2676   void reset() {
2677     counter = 0;
2678   }
2679   EvaluateResult* current() {
2680     return &results[counter % kArraySize];
2681   }
2682   void next() {
2683     counter++;
2684   }
2685 };
2686
2687 DebugProcessDebugMessagesData process_debug_messages_data;
2688
2689 static void DebugProcessDebugMessagesHandler(
2690     const v8::Debug::Message& message) {
2691   v8::Handle<v8::String> json = message.GetJSON();
2692   v8::String::Utf8Value utf8(json);
2693   EvaluateResult* array_item = process_debug_messages_data.current();
2694
2695   bool res = GetEvaluateStringResult(*utf8,
2696                                      array_item->buffer,
2697                                      EvaluateResult::kBufferSize);
2698   if (res) {
2699     process_debug_messages_data.next();
2700   }
2701 }
2702
2703
2704 // Test that the evaluation of expressions works even from ProcessDebugMessages
2705 // i.e. with empty stack.
2706 TEST(DebugEvaluateWithoutStack) {
2707   v8::Debug::SetMessageHandler(DebugProcessDebugMessagesHandler);
2708
2709   DebugLocalContext env;
2710   v8::HandleScope scope(env->GetIsolate());
2711
2712   const char* source =
2713       "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
2714
2715   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source))
2716       ->Run();
2717
2718   v8::Debug::ProcessDebugMessages();
2719
2720   const int kBufferSize = 1000;
2721   uint16_t buffer[kBufferSize];
2722
2723   const char* command_111 = "{\"seq\":111,"
2724       "\"type\":\"request\","
2725       "\"command\":\"evaluate\","
2726       "\"arguments\":{"
2727       "    \"global\":true,"
2728       "    \"expression\":\"v1\",\"disable_break\":true"
2729       "}}";
2730
2731   v8::Isolate* isolate = CcTest::isolate();
2732   v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_111, buffer));
2733
2734   const char* command_112 = "{\"seq\":112,"
2735       "\"type\":\"request\","
2736       "\"command\":\"evaluate\","
2737       "\"arguments\":{"
2738       "    \"global\":true,"
2739       "    \"expression\":\"getAnimal()\",\"disable_break\":true"
2740       "}}";
2741
2742   v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_112, buffer));
2743
2744   const char* command_113 = "{\"seq\":113,"
2745      "\"type\":\"request\","
2746      "\"command\":\"evaluate\","
2747      "\"arguments\":{"
2748      "    \"global\":true,"
2749      "    \"expression\":\"239 + 566\",\"disable_break\":true"
2750      "}}";
2751
2752   v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_113, buffer));
2753
2754   v8::Debug::ProcessDebugMessages();
2755
2756   CHECK_EQ(3, process_debug_messages_data.counter);
2757
2758   CHECK_EQ(strcmp("Pinguin", process_debug_messages_data.results[0].buffer), 0);
2759   CHECK_EQ(strcmp("Capybara", process_debug_messages_data.results[1].buffer),
2760            0);
2761   CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0);
2762
2763   v8::Debug::SetMessageHandler(NULL);
2764   v8::Debug::SetDebugEventListener(NULL);
2765   CheckDebuggerUnloaded();
2766 }
2767
2768
2769 // Simple test of the stepping mechanism using only store ICs.
2770 TEST(DebugStepLinear) {
2771   DebugLocalContext env;
2772   v8::HandleScope scope(env->GetIsolate());
2773
2774   // Create a function for testing stepping.
2775   v8::Local<v8::Function> foo = CompileFunction(&env,
2776                                                 "function foo(){a=1;b=1;c=1;}",
2777                                                 "foo");
2778
2779   // Run foo to allow it to get optimized.
2780   CompileRun("a=0; b=0; c=0; foo();");
2781
2782   SetBreakPoint(foo, 3);
2783
2784   // Register a debug event listener which steps and counts.
2785   v8::Debug::SetDebugEventListener(DebugEventStep);
2786
2787   step_action = StepIn;
2788   break_point_hit_count = 0;
2789   foo->Call(env->Global(), 0, NULL);
2790
2791   // With stepping all break locations are hit.
2792   CHECK_EQ(4, break_point_hit_count);
2793
2794   v8::Debug::SetDebugEventListener(NULL);
2795   CheckDebuggerUnloaded();
2796
2797   // Register a debug event listener which just counts.
2798   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2799
2800   SetBreakPoint(foo, 3);
2801   break_point_hit_count = 0;
2802   foo->Call(env->Global(), 0, NULL);
2803
2804   // Without stepping only active break points are hit.
2805   CHECK_EQ(1, break_point_hit_count);
2806
2807   v8::Debug::SetDebugEventListener(NULL);
2808   CheckDebuggerUnloaded();
2809 }
2810
2811
2812 // Test of the stepping mechanism for keyed load in a loop.
2813 TEST(DebugStepKeyedLoadLoop) {
2814   DebugLocalContext env;
2815   v8::HandleScope scope(env->GetIsolate());
2816
2817   // Register a debug event listener which steps and counts.
2818   v8::Debug::SetDebugEventListener(DebugEventStep);
2819
2820   // Create a function for testing stepping of keyed load. The statement 'y=1'
2821   // is there to have more than one breakable statement in the loop, TODO(315).
2822   v8::Local<v8::Function> foo = CompileFunction(
2823       &env,
2824       "function foo(a) {\n"
2825       "  var x;\n"
2826       "  var len = a.length;\n"
2827       "  for (var i = 0; i < len; i++) {\n"
2828       "    y = 1;\n"
2829       "    x = a[i];\n"
2830       "  }\n"
2831       "}\n"
2832       "y=0\n",
2833       "foo");
2834
2835   // Create array [0,1,2,3,4,5,6,7,8,9]
2836   v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
2837   for (int i = 0; i < 10; i++) {
2838     a->Set(v8::Number::New(env->GetIsolate(), i),
2839            v8::Number::New(env->GetIsolate(), i));
2840   }
2841
2842   // Call function without any break points to ensure inlining is in place.
2843   const int kArgc = 1;
2844   v8::Handle<v8::Value> args[kArgc] = { a };
2845   foo->Call(env->Global(), kArgc, args);
2846
2847   // Set up break point and step through the function.
2848   SetBreakPoint(foo, 3);
2849   step_action = StepNext;
2850   break_point_hit_count = 0;
2851   foo->Call(env->Global(), kArgc, args);
2852
2853   // With stepping all break locations are hit.
2854   CHECK_EQ(45, break_point_hit_count);
2855
2856   v8::Debug::SetDebugEventListener(NULL);
2857   CheckDebuggerUnloaded();
2858 }
2859
2860
2861 // Test of the stepping mechanism for keyed store in a loop.
2862 TEST(DebugStepKeyedStoreLoop) {
2863   DebugLocalContext env;
2864   v8::HandleScope scope(env->GetIsolate());
2865
2866   // Register a debug event listener which steps and counts.
2867   v8::Debug::SetDebugEventListener(DebugEventStep);
2868
2869   // Create a function for testing stepping of keyed store. The statement 'y=1'
2870   // is there to have more than one breakable statement in the loop, TODO(315).
2871   v8::Local<v8::Function> foo = CompileFunction(
2872       &env,
2873       "function foo(a) {\n"
2874       "  var len = a.length;\n"
2875       "  for (var i = 0; i < len; i++) {\n"
2876       "    y = 1;\n"
2877       "    a[i] = 42;\n"
2878       "  }\n"
2879       "}\n"
2880       "y=0\n",
2881       "foo");
2882
2883   // Create array [0,1,2,3,4,5,6,7,8,9]
2884   v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
2885   for (int i = 0; i < 10; i++) {
2886     a->Set(v8::Number::New(env->GetIsolate(), i),
2887            v8::Number::New(env->GetIsolate(), i));
2888   }
2889
2890   // Call function without any break points to ensure inlining is in place.
2891   const int kArgc = 1;
2892   v8::Handle<v8::Value> args[kArgc] = { a };
2893   foo->Call(env->Global(), kArgc, args);
2894
2895   // Set up break point and step through the function.
2896   SetBreakPoint(foo, 3);
2897   step_action = StepNext;
2898   break_point_hit_count = 0;
2899   foo->Call(env->Global(), kArgc, args);
2900
2901   // With stepping all break locations are hit.
2902   CHECK_EQ(44, break_point_hit_count);
2903
2904   v8::Debug::SetDebugEventListener(NULL);
2905   CheckDebuggerUnloaded();
2906 }
2907
2908
2909 // Test of the stepping mechanism for named load in a loop.
2910 TEST(DebugStepNamedLoadLoop) {
2911   DebugLocalContext env;
2912   v8::HandleScope scope(env->GetIsolate());
2913
2914   // Register a debug event listener which steps and counts.
2915   v8::Debug::SetDebugEventListener(DebugEventStep);
2916
2917   // Create a function for testing stepping of named load.
2918   v8::Local<v8::Function> foo = CompileFunction(
2919       &env,
2920       "function foo() {\n"
2921           "  var a = [];\n"
2922           "  var s = \"\";\n"
2923           "  for (var i = 0; i < 10; i++) {\n"
2924           "    var v = new V(i, i + 1);\n"
2925           "    v.y;\n"
2926           "    a.length;\n"  // Special case: array length.
2927           "    s.length;\n"  // Special case: string length.
2928           "  }\n"
2929           "}\n"
2930           "function V(x, y) {\n"
2931           "  this.x = x;\n"
2932           "  this.y = y;\n"
2933           "}\n",
2934           "foo");
2935
2936   // Call function without any break points to ensure inlining is in place.
2937   foo->Call(env->Global(), 0, NULL);
2938
2939   // Set up break point and step through the function.
2940   SetBreakPoint(foo, 4);
2941   step_action = StepNext;
2942   break_point_hit_count = 0;
2943   foo->Call(env->Global(), 0, NULL);
2944
2945   // With stepping all break locations are hit.
2946   CHECK_EQ(65, break_point_hit_count);
2947
2948   v8::Debug::SetDebugEventListener(NULL);
2949   CheckDebuggerUnloaded();
2950 }
2951
2952
2953 static void DoDebugStepNamedStoreLoop(int expected) {
2954   DebugLocalContext env;
2955   v8::HandleScope scope(env->GetIsolate());
2956
2957   // Register a debug event listener which steps and counts.
2958   v8::Debug::SetDebugEventListener(DebugEventStep);
2959
2960   // Create a function for testing stepping of named store.
2961   v8::Local<v8::Function> foo = CompileFunction(
2962       &env,
2963       "function foo() {\n"
2964           "  var a = {a:1};\n"
2965           "  for (var i = 0; i < 10; i++) {\n"
2966           "    a.a = 2\n"
2967           "  }\n"
2968           "}\n",
2969           "foo");
2970
2971   // Call function without any break points to ensure inlining is in place.
2972   foo->Call(env->Global(), 0, NULL);
2973
2974   // Set up break point and step through the function.
2975   SetBreakPoint(foo, 3);
2976   step_action = StepNext;
2977   break_point_hit_count = 0;
2978   foo->Call(env->Global(), 0, NULL);
2979
2980   // With stepping all expected break locations are hit.
2981   CHECK_EQ(expected, break_point_hit_count);
2982
2983   v8::Debug::SetDebugEventListener(NULL);
2984   CheckDebuggerUnloaded();
2985 }
2986
2987
2988 // Test of the stepping mechanism for named load in a loop.
2989 TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(34); }
2990
2991
2992 // Test the stepping mechanism with different ICs.
2993 TEST(DebugStepLinearMixedICs) {
2994   DebugLocalContext env;
2995   v8::HandleScope scope(env->GetIsolate());
2996
2997   // Register a debug event listener which steps and counts.
2998   v8::Debug::SetDebugEventListener(DebugEventStep);
2999
3000   // Create a function for testing stepping.
3001   v8::Local<v8::Function> foo = CompileFunction(&env,
3002       "function bar() {};"
3003       "function foo() {"
3004       "  var x;"
3005       "  var index='name';"
3006       "  var y = {};"
3007       "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
3008
3009   // Run functions to allow them to get optimized.
3010   CompileRun("a=0; b=0; bar(); foo();");
3011
3012   SetBreakPoint(foo, 0);
3013
3014   step_action = StepIn;
3015   break_point_hit_count = 0;
3016   foo->Call(env->Global(), 0, NULL);
3017
3018   // With stepping all break locations are hit.
3019   CHECK_EQ(11, break_point_hit_count);
3020
3021   v8::Debug::SetDebugEventListener(NULL);
3022   CheckDebuggerUnloaded();
3023
3024   // Register a debug event listener which just counts.
3025   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3026
3027   SetBreakPoint(foo, 0);
3028   break_point_hit_count = 0;
3029   foo->Call(env->Global(), 0, NULL);
3030
3031   // Without stepping only active break points are hit.
3032   CHECK_EQ(1, break_point_hit_count);
3033
3034   v8::Debug::SetDebugEventListener(NULL);
3035   CheckDebuggerUnloaded();
3036 }
3037
3038
3039 TEST(DebugStepDeclarations) {
3040   DebugLocalContext env;
3041   v8::HandleScope scope(env->GetIsolate());
3042
3043   // Register a debug event listener which steps and counts.
3044   v8::Debug::SetDebugEventListener(DebugEventStep);
3045
3046   // Create a function for testing stepping. Run it to allow it to get
3047   // optimized.
3048   const char* src = "function foo() { "
3049                     "  var a;"
3050                     "  var b = 1;"
3051                     "  var c = foo;"
3052                     "  var d = Math.floor;"
3053                     "  var e = b + d(1.2);"
3054                     "}"
3055                     "foo()";
3056   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3057
3058   SetBreakPoint(foo, 0);
3059
3060   // Stepping through the declarations.
3061   step_action = StepIn;
3062   break_point_hit_count = 0;
3063   foo->Call(env->Global(), 0, NULL);
3064   CHECK_EQ(6, break_point_hit_count);
3065
3066   // Get rid of the debug event listener.
3067   v8::Debug::SetDebugEventListener(NULL);
3068   CheckDebuggerUnloaded();
3069 }
3070
3071
3072 TEST(DebugStepLocals) {
3073   DebugLocalContext env;
3074   v8::HandleScope scope(env->GetIsolate());
3075
3076   // Register a debug event listener which steps and counts.
3077   v8::Debug::SetDebugEventListener(DebugEventStep);
3078
3079   // Create a function for testing stepping. Run it to allow it to get
3080   // optimized.
3081   const char* src = "function foo() { "
3082                     "  var a,b;"
3083                     "  a = 1;"
3084                     "  b = a + 2;"
3085                     "  b = 1 + 2 + 3;"
3086                     "  a = Math.floor(b);"
3087                     "}"
3088                     "foo()";
3089   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3090
3091   SetBreakPoint(foo, 0);
3092
3093   // Stepping through the declarations.
3094   step_action = StepIn;
3095   break_point_hit_count = 0;
3096   foo->Call(env->Global(), 0, NULL);
3097   CHECK_EQ(6, break_point_hit_count);
3098
3099   // Get rid of the debug event listener.
3100   v8::Debug::SetDebugEventListener(NULL);
3101   CheckDebuggerUnloaded();
3102 }
3103
3104
3105 TEST(DebugStepIf) {
3106   DebugLocalContext env;
3107   v8::Isolate* isolate = env->GetIsolate();
3108   v8::HandleScope scope(isolate);
3109
3110   // Register a debug event listener which steps and counts.
3111   v8::Debug::SetDebugEventListener(DebugEventStep);
3112
3113   // Create a function for testing stepping. Run it to allow it to get
3114   // optimized.
3115   const int argc = 1;
3116   const char* src = "function foo(x) { "
3117                     "  a = 1;"
3118                     "  if (x) {"
3119                     "    b = 1;"
3120                     "  } else {"
3121                     "    c = 1;"
3122                     "    d = 1;"
3123                     "  }"
3124                     "}"
3125                     "a=0; b=0; c=0; d=0; foo()";
3126   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3127   SetBreakPoint(foo, 0);
3128
3129   // Stepping through the true part.
3130   step_action = StepIn;
3131   break_point_hit_count = 0;
3132   v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
3133   foo->Call(env->Global(), argc, argv_true);
3134   CHECK_EQ(4, break_point_hit_count);
3135
3136   // Stepping through the false part.
3137   step_action = StepIn;
3138   break_point_hit_count = 0;
3139   v8::Handle<v8::Value> argv_false[argc] = { v8::False(isolate) };
3140   foo->Call(env->Global(), argc, argv_false);
3141   CHECK_EQ(5, break_point_hit_count);
3142
3143   // Get rid of the debug event listener.
3144   v8::Debug::SetDebugEventListener(NULL);
3145   CheckDebuggerUnloaded();
3146 }
3147
3148
3149 TEST(DebugStepSwitch) {
3150   DebugLocalContext env;
3151   v8::Isolate* isolate = env->GetIsolate();
3152   v8::HandleScope scope(isolate);
3153
3154   // Register a debug event listener which steps and counts.
3155   v8::Debug::SetDebugEventListener(DebugEventStep);
3156
3157   // Create a function for testing stepping. Run it to allow it to get
3158   // optimized.
3159   const int argc = 1;
3160   const char* src = "function foo(x) { "
3161                     "  a = 1;"
3162                     "  switch (x) {"
3163                     "    case 1:"
3164                     "      b = 1;"
3165                     "    case 2:"
3166                     "      c = 1;"
3167                     "      break;"
3168                     "    case 3:"
3169                     "      d = 1;"
3170                     "      e = 1;"
3171                     "      f = 1;"
3172                     "      break;"
3173                     "  }"
3174                     "}"
3175                     "a=0; b=0; c=0; d=0; e=0; f=0; foo()";
3176   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3177   SetBreakPoint(foo, 0);
3178
3179   // One case with fall-through.
3180   step_action = StepIn;
3181   break_point_hit_count = 0;
3182   v8::Handle<v8::Value> argv_1[argc] = { v8::Number::New(isolate, 1) };
3183   foo->Call(env->Global(), argc, argv_1);
3184   CHECK_EQ(6, break_point_hit_count);
3185
3186   // Another case.
3187   step_action = StepIn;
3188   break_point_hit_count = 0;
3189   v8::Handle<v8::Value> argv_2[argc] = { v8::Number::New(isolate, 2) };
3190   foo->Call(env->Global(), argc, argv_2);
3191   CHECK_EQ(5, break_point_hit_count);
3192
3193   // Last case.
3194   step_action = StepIn;
3195   break_point_hit_count = 0;
3196   v8::Handle<v8::Value> argv_3[argc] = { v8::Number::New(isolate, 3) };
3197   foo->Call(env->Global(), argc, argv_3);
3198   CHECK_EQ(7, break_point_hit_count);
3199
3200   // Get rid of the debug event listener.
3201   v8::Debug::SetDebugEventListener(NULL);
3202   CheckDebuggerUnloaded();
3203 }
3204
3205
3206 TEST(DebugStepWhile) {
3207   DebugLocalContext env;
3208   v8::Isolate* isolate = env->GetIsolate();
3209   v8::HandleScope scope(isolate);
3210
3211   // Register a debug event listener which steps and counts.
3212   v8::Debug::SetDebugEventListener(DebugEventStep);
3213
3214   // Create a function for testing stepping. Run it to allow it to get
3215   // optimized.
3216   const int argc = 1;
3217   const char* src = "function foo(x) { "
3218                     "  var a = 0;"
3219                     "  while (a < x) {"
3220                     "    a++;"
3221                     "  }"
3222                     "}"
3223                     "foo()";
3224   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3225   SetBreakPoint(foo, 8);  // "var a = 0;"
3226
3227   // Looping 0 times.  We still should break at the while-condition once.
3228   step_action = StepIn;
3229   break_point_hit_count = 0;
3230   v8::Handle<v8::Value> argv_0[argc] = { v8::Number::New(isolate, 0) };
3231   foo->Call(env->Global(), argc, argv_0);
3232   CHECK_EQ(3, break_point_hit_count);
3233
3234   // Looping 10 times.
3235   step_action = StepIn;
3236   break_point_hit_count = 0;
3237   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
3238   foo->Call(env->Global(), argc, argv_10);
3239   CHECK_EQ(23, break_point_hit_count);
3240
3241   // Looping 100 times.
3242   step_action = StepIn;
3243   break_point_hit_count = 0;
3244   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
3245   foo->Call(env->Global(), argc, argv_100);
3246   CHECK_EQ(203, break_point_hit_count);
3247
3248   // Get rid of the debug event listener.
3249   v8::Debug::SetDebugEventListener(NULL);
3250   CheckDebuggerUnloaded();
3251 }
3252
3253
3254 TEST(DebugStepDoWhile) {
3255   DebugLocalContext env;
3256   v8::Isolate* isolate = env->GetIsolate();
3257   v8::HandleScope scope(isolate);
3258
3259   // Register a debug event listener which steps and counts.
3260   v8::Debug::SetDebugEventListener(DebugEventStep);
3261
3262   // Create a function for testing stepping. Run it to allow it to get
3263   // optimized.
3264   const int argc = 1;
3265   const char* src = "function foo(x) { "
3266                     "  var a = 0;"
3267                     "  do {"
3268                     "    a++;"
3269                     "  } while (a < x)"
3270                     "}"
3271                     "foo()";
3272   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3273   SetBreakPoint(foo, 8);  // "var a = 0;"
3274
3275   // Looping 10 times.
3276   step_action = StepIn;
3277   break_point_hit_count = 0;
3278   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
3279   foo->Call(env->Global(), argc, argv_10);
3280   CHECK_EQ(22, break_point_hit_count);
3281
3282   // Looping 100 times.
3283   step_action = StepIn;
3284   break_point_hit_count = 0;
3285   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
3286   foo->Call(env->Global(), argc, argv_100);
3287   CHECK_EQ(202, break_point_hit_count);
3288
3289   // Get rid of the debug event listener.
3290   v8::Debug::SetDebugEventListener(NULL);
3291   CheckDebuggerUnloaded();
3292 }
3293
3294
3295 TEST(DebugStepFor) {
3296   DebugLocalContext env;
3297   v8::Isolate* isolate = env->GetIsolate();
3298   v8::HandleScope scope(isolate);
3299
3300   // Register a debug event listener which steps and counts.
3301   v8::Debug::SetDebugEventListener(DebugEventStep);
3302
3303   // Create a function for testing stepping. Run it to allow it to get
3304   // optimized.
3305   const int argc = 1;
3306   const char* src = "function foo(x) { "
3307                     "  a = 1;"
3308                     "  for (i = 0; i < x; i++) {"
3309                     "    b = 1;"
3310                     "  }"
3311                     "}"
3312                     "a=0; b=0; i=0; foo()";
3313   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3314
3315   SetBreakPoint(foo, 8);  // "a = 1;"
3316
3317   // Looping 10 times.
3318   step_action = StepIn;
3319   break_point_hit_count = 0;
3320   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
3321   foo->Call(env->Global(), argc, argv_10);
3322   CHECK_EQ(45, break_point_hit_count);
3323
3324   // Looping 100 times.
3325   step_action = StepIn;
3326   break_point_hit_count = 0;
3327   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
3328   foo->Call(env->Global(), argc, argv_100);
3329   CHECK_EQ(405, break_point_hit_count);
3330
3331   // Get rid of the debug event listener.
3332   v8::Debug::SetDebugEventListener(NULL);
3333   CheckDebuggerUnloaded();
3334 }
3335
3336
3337 TEST(DebugStepForContinue) {
3338   DebugLocalContext env;
3339   v8::Isolate* isolate = env->GetIsolate();
3340   v8::HandleScope scope(isolate);
3341
3342   // Register a debug event listener which steps and counts.
3343   v8::Debug::SetDebugEventListener(DebugEventStep);
3344
3345   // Create a function for testing stepping. Run it to allow it to get
3346   // optimized.
3347   const int argc = 1;
3348   const char* src = "function foo(x) { "
3349                     "  var a = 0;"
3350                     "  var b = 0;"
3351                     "  var c = 0;"
3352                     "  for (var i = 0; i < x; i++) {"
3353                     "    a++;"
3354                     "    if (a % 2 == 0) continue;"
3355                     "    b++;"
3356                     "    c++;"
3357                     "  }"
3358                     "  return b;"
3359                     "}"
3360                     "foo()";
3361   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3362   v8::Handle<v8::Value> result;
3363   SetBreakPoint(foo, 8);  // "var a = 0;"
3364
3365   // Each loop generates 4 or 5 steps depending on whether a is equal.
3366
3367   // Looping 10 times.
3368   step_action = StepIn;
3369   break_point_hit_count = 0;
3370   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
3371   result = foo->Call(env->Global(), argc, argv_10);
3372   CHECK_EQ(5, result->Int32Value());
3373   CHECK_EQ(62, break_point_hit_count);
3374
3375   // Looping 100 times.
3376   step_action = StepIn;
3377   break_point_hit_count = 0;
3378   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
3379   result = foo->Call(env->Global(), argc, argv_100);
3380   CHECK_EQ(50, result->Int32Value());
3381   CHECK_EQ(557, break_point_hit_count);
3382
3383   // Get rid of the debug event listener.
3384   v8::Debug::SetDebugEventListener(NULL);
3385   CheckDebuggerUnloaded();
3386 }
3387
3388
3389 TEST(DebugStepForBreak) {
3390   DebugLocalContext env;
3391   v8::Isolate* isolate = env->GetIsolate();
3392   v8::HandleScope scope(isolate);
3393
3394   // Register a debug event listener which steps and counts.
3395   v8::Debug::SetDebugEventListener(DebugEventStep);
3396
3397   // Create a function for testing stepping. Run it to allow it to get
3398   // optimized.
3399   const int argc = 1;
3400   const char* src = "function foo(x) { "
3401                     "  var a = 0;"
3402                     "  var b = 0;"
3403                     "  var c = 0;"
3404                     "  for (var i = 0; i < 1000; i++) {"
3405                     "    a++;"
3406                     "    if (a == x) break;"
3407                     "    b++;"
3408                     "    c++;"
3409                     "  }"
3410                     "  return b;"
3411                     "}"
3412                     "foo()";
3413   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3414   v8::Handle<v8::Value> result;
3415   SetBreakPoint(foo, 8);  // "var a = 0;"
3416
3417   // Each loop generates 5 steps except for the last (when break is executed)
3418   // which only generates 4.
3419
3420   // Looping 10 times.
3421   step_action = StepIn;
3422   break_point_hit_count = 0;
3423   v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
3424   result = foo->Call(env->Global(), argc, argv_10);
3425   CHECK_EQ(9, result->Int32Value());
3426   CHECK_EQ(64, break_point_hit_count);
3427
3428   // Looping 100 times.
3429   step_action = StepIn;
3430   break_point_hit_count = 0;
3431   v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
3432   result = foo->Call(env->Global(), argc, argv_100);
3433   CHECK_EQ(99, result->Int32Value());
3434   CHECK_EQ(604, break_point_hit_count);
3435
3436   // Get rid of the debug event listener.
3437   v8::Debug::SetDebugEventListener(NULL);
3438   CheckDebuggerUnloaded();
3439 }
3440
3441
3442 TEST(DebugStepForIn) {
3443   DebugLocalContext env;
3444   v8::HandleScope scope(env->GetIsolate());
3445
3446   // Register a debug event listener which steps and counts.
3447   v8::Debug::SetDebugEventListener(DebugEventStep);
3448
3449   // Create a function for testing stepping. Run it to allow it to get
3450   // optimized.
3451   v8::Local<v8::Function> foo;
3452   const char* src_1 = "function foo() { "
3453                       "  var a = [1, 2];"
3454                       "  for (x in a) {"
3455                       "    b = 0;"
3456                       "  }"
3457                       "}"
3458                       "foo()";
3459   foo = CompileFunction(&env, src_1, "foo");
3460   SetBreakPoint(foo, 0);  // "var a = ..."
3461
3462   step_action = StepIn;
3463   break_point_hit_count = 0;
3464   foo->Call(env->Global(), 0, NULL);
3465   CHECK_EQ(8, break_point_hit_count);
3466
3467   // Create a function for testing stepping. Run it to allow it to get
3468   // optimized.
3469   const char* src_2 = "function foo() { "
3470                       "  var a = {a:[1, 2, 3]};"
3471                       "  for (x in a.a) {"
3472                       "    b = 0;"
3473                       "  }"
3474                       "}"
3475                       "foo()";
3476   foo = CompileFunction(&env, src_2, "foo");
3477   SetBreakPoint(foo, 0);  // "var a = ..."
3478
3479   step_action = StepIn;
3480   break_point_hit_count = 0;
3481   foo->Call(env->Global(), 0, NULL);
3482   CHECK_EQ(10, break_point_hit_count);
3483
3484   // Get rid of the debug event listener.
3485   v8::Debug::SetDebugEventListener(NULL);
3486   CheckDebuggerUnloaded();
3487 }
3488
3489
3490 TEST(DebugStepWith) {
3491   DebugLocalContext env;
3492   v8::HandleScope scope(env->GetIsolate());
3493
3494   // Register a debug event listener which steps and counts.
3495   v8::Debug::SetDebugEventListener(DebugEventStep);
3496
3497   // Create a function for testing stepping. Run it to allow it to get
3498   // optimized.
3499   const char* src = "function foo(x) { "
3500                     "  var a = {};"
3501                     "  with (a) {}"
3502                     "  with (b) {}"
3503                     "}"
3504                     "foo()";
3505   env->Global()->Set(v8::String::NewFromUtf8(env->GetIsolate(), "b"),
3506                      v8::Object::New(env->GetIsolate()));
3507   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3508   v8::Handle<v8::Value> result;
3509   SetBreakPoint(foo, 8);  // "var a = {};"
3510
3511   step_action = StepIn;
3512   break_point_hit_count = 0;
3513   foo->Call(env->Global(), 0, NULL);
3514   CHECK_EQ(4, break_point_hit_count);
3515
3516   // Get rid of the debug event listener.
3517   v8::Debug::SetDebugEventListener(NULL);
3518   CheckDebuggerUnloaded();
3519 }
3520
3521
3522 TEST(DebugConditional) {
3523   DebugLocalContext env;
3524   v8::Isolate* isolate = env->GetIsolate();
3525   v8::HandleScope scope(isolate);
3526
3527   // Register a debug event listener which steps and counts.
3528   v8::Debug::SetDebugEventListener(DebugEventStep);
3529
3530   // Create a function for testing stepping. Run it to allow it to get
3531   // optimized.
3532   const char* src = "function foo(x) { "
3533                     "  var a;"
3534                     "  a = x ? 1 : 2;"
3535                     "  return a;"
3536                     "}"
3537                     "foo()";
3538   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3539   SetBreakPoint(foo, 0);  // "var a;"
3540
3541   step_action = StepIn;
3542   break_point_hit_count = 0;
3543   foo->Call(env->Global(), 0, NULL);
3544   CHECK_EQ(5, break_point_hit_count);
3545
3546   step_action = StepIn;
3547   break_point_hit_count = 0;
3548   const int argc = 1;
3549   v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
3550   foo->Call(env->Global(), argc, argv_true);
3551   CHECK_EQ(5, break_point_hit_count);
3552
3553   // Get rid of the debug event listener.
3554   v8::Debug::SetDebugEventListener(NULL);
3555   CheckDebuggerUnloaded();
3556 }
3557
3558
3559 TEST(StepInOutSimple) {
3560   DebugLocalContext env;
3561   v8::HandleScope scope(env->GetIsolate());
3562
3563   // Create a function for checking the function when hitting a break point.
3564   frame_function_name = CompileFunction(&env,
3565                                         frame_function_name_source,
3566                                         "frame_function_name");
3567
3568   // Register a debug event listener which steps and counts.
3569   v8::Debug::SetDebugEventListener(DebugEventStepSequence);
3570
3571   // Create a function for testing stepping. Run it to allow it to get
3572   // optimized.
3573   const char* src = "function a() {b();c();}; "
3574                     "function b() {c();}; "
3575                     "function c() {}; "
3576                     "a(); b(); c()";
3577   v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3578   SetBreakPoint(a, 0);
3579
3580   // Step through invocation of a with step in.
3581   step_action = StepIn;
3582   break_point_hit_count = 0;
3583   expected_step_sequence = "abcbaca";
3584   a->Call(env->Global(), 0, NULL);
3585   CHECK_EQ(StrLength(expected_step_sequence),
3586            break_point_hit_count);
3587
3588   // Step through invocation of a with step next.
3589   step_action = StepNext;
3590   break_point_hit_count = 0;
3591   expected_step_sequence = "aaa";
3592   a->Call(env->Global(), 0, NULL);
3593   CHECK_EQ(StrLength(expected_step_sequence),
3594            break_point_hit_count);
3595
3596   // Step through invocation of a with step out.
3597   step_action = StepOut;
3598   break_point_hit_count = 0;
3599   expected_step_sequence = "a";
3600   a->Call(env->Global(), 0, NULL);
3601   CHECK_EQ(StrLength(expected_step_sequence),
3602            break_point_hit_count);
3603
3604   // Get rid of the debug event listener.
3605   v8::Debug::SetDebugEventListener(NULL);
3606   CheckDebuggerUnloaded();
3607 }
3608
3609
3610 TEST(StepInOutTree) {
3611   DebugLocalContext env;
3612   v8::HandleScope scope(env->GetIsolate());
3613
3614   // Create a function for checking the function when hitting a break point.
3615   frame_function_name = CompileFunction(&env,
3616                                         frame_function_name_source,
3617                                         "frame_function_name");
3618
3619   // Register a debug event listener which steps and counts.
3620   v8::Debug::SetDebugEventListener(DebugEventStepSequence);
3621
3622   // Create a function for testing stepping. Run it to allow it to get
3623   // optimized.
3624   const char* src = "function a() {b(c(d()),d());c(d());d()}; "
3625                     "function b(x,y) {c();}; "
3626                     "function c(x) {}; "
3627                     "function d() {}; "
3628                     "a(); b(); c(); d()";
3629   v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3630   SetBreakPoint(a, 0);
3631
3632   // Step through invocation of a with step in.
3633   step_action = StepIn;
3634   break_point_hit_count = 0;
3635   expected_step_sequence = "adacadabcbadacada";
3636   a->Call(env->Global(), 0, NULL);
3637   CHECK_EQ(StrLength(expected_step_sequence),
3638            break_point_hit_count);
3639
3640   // Step through invocation of a with step next.
3641   step_action = StepNext;
3642   break_point_hit_count = 0;
3643   expected_step_sequence = "aaaa";
3644   a->Call(env->Global(), 0, NULL);
3645   CHECK_EQ(StrLength(expected_step_sequence),
3646            break_point_hit_count);
3647
3648   // Step through invocation of a with step out.
3649   step_action = StepOut;
3650   break_point_hit_count = 0;
3651   expected_step_sequence = "a";
3652   a->Call(env->Global(), 0, NULL);
3653   CHECK_EQ(StrLength(expected_step_sequence),
3654            break_point_hit_count);
3655
3656   // Get rid of the debug event listener.
3657   v8::Debug::SetDebugEventListener(NULL);
3658   CheckDebuggerUnloaded(true);
3659 }
3660
3661
3662 TEST(StepInOutBranch) {
3663   DebugLocalContext env;
3664   v8::HandleScope scope(env->GetIsolate());
3665
3666   // Create a function for checking the function when hitting a break point.
3667   frame_function_name = CompileFunction(&env,
3668                                         frame_function_name_source,
3669                                         "frame_function_name");
3670
3671   // Register a debug event listener which steps and counts.
3672   v8::Debug::SetDebugEventListener(DebugEventStepSequence);
3673
3674   // Create a function for testing stepping. Run it to allow it to get
3675   // optimized.
3676   const char* src = "function a() {b(false);c();}; "
3677                     "function b(x) {if(x){c();};}; "
3678                     "function c() {}; "
3679                     "a(); b(); c()";
3680   v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3681   SetBreakPoint(a, 0);
3682
3683   // Step through invocation of a.
3684   step_action = StepIn;
3685   break_point_hit_count = 0;
3686   expected_step_sequence = "abbaca";
3687   a->Call(env->Global(), 0, NULL);
3688   CHECK_EQ(StrLength(expected_step_sequence),
3689            break_point_hit_count);
3690
3691   // Get rid of the debug event listener.
3692   v8::Debug::SetDebugEventListener(NULL);
3693   CheckDebuggerUnloaded();
3694 }
3695
3696
3697 // Test that step in does not step into native functions.
3698 TEST(DebugStepNatives) {
3699   DebugLocalContext env;
3700   v8::HandleScope scope(env->GetIsolate());
3701
3702   // Create a function for testing stepping.
3703   v8::Local<v8::Function> foo = CompileFunction(
3704       &env,
3705       "function foo(){debugger;Math.sin(1);}",
3706       "foo");
3707
3708   // Register a debug event listener which steps and counts.
3709   v8::Debug::SetDebugEventListener(DebugEventStep);
3710
3711   step_action = StepIn;
3712   break_point_hit_count = 0;
3713   foo->Call(env->Global(), 0, NULL);
3714
3715   // With stepping all break locations are hit.
3716   CHECK_EQ(3, break_point_hit_count);
3717
3718   v8::Debug::SetDebugEventListener(NULL);
3719   CheckDebuggerUnloaded();
3720
3721   // Register a debug event listener which just counts.
3722   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3723
3724   break_point_hit_count = 0;
3725   foo->Call(env->Global(), 0, NULL);
3726
3727   // Without stepping only active break points are hit.
3728   CHECK_EQ(1, break_point_hit_count);
3729
3730   v8::Debug::SetDebugEventListener(NULL);
3731   CheckDebuggerUnloaded();
3732 }
3733
3734
3735 // Test that step in works with function.apply.
3736 TEST(DebugStepFunctionApply) {
3737   DebugLocalContext env;
3738   v8::HandleScope scope(env->GetIsolate());
3739
3740   // Create a function for testing stepping.
3741   v8::Local<v8::Function> foo = CompileFunction(
3742       &env,
3743       "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3744       "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
3745       "foo");
3746
3747   // Register a debug event listener which steps and counts.
3748   v8::Debug::SetDebugEventListener(DebugEventStep);
3749
3750   step_action = StepIn;
3751   break_point_hit_count = 0;
3752   foo->Call(env->Global(), 0, NULL);
3753
3754   // With stepping all break locations are hit.
3755   CHECK_EQ(7, break_point_hit_count);
3756
3757   v8::Debug::SetDebugEventListener(NULL);
3758   CheckDebuggerUnloaded();
3759
3760   // Register a debug event listener which just counts.
3761   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3762
3763   break_point_hit_count = 0;
3764   foo->Call(env->Global(), 0, NULL);
3765
3766   // Without stepping only the debugger statement is hit.
3767   CHECK_EQ(1, break_point_hit_count);
3768
3769   v8::Debug::SetDebugEventListener(NULL);
3770   CheckDebuggerUnloaded();
3771 }
3772
3773
3774 // Test that step in works with function.call.
3775 TEST(DebugStepFunctionCall) {
3776   DebugLocalContext env;
3777   v8::Isolate* isolate = env->GetIsolate();
3778   v8::HandleScope scope(isolate);
3779
3780   // Create a function for testing stepping.
3781   v8::Local<v8::Function> foo = CompileFunction(
3782       &env,
3783       "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3784       "function foo(a){ debugger;"
3785       "                 if (a) {"
3786       "                   bar.call(this, 1, 2, 3);"
3787       "                 } else {"
3788       "                   bar.call(this, 0);"
3789       "                 }"
3790       "}",
3791       "foo");
3792
3793   // Register a debug event listener which steps and counts.
3794   v8::Debug::SetDebugEventListener(DebugEventStep);
3795   step_action = StepIn;
3796
3797   // Check stepping where the if condition in bar is false.
3798   break_point_hit_count = 0;
3799   foo->Call(env->Global(), 0, NULL);
3800   CHECK_EQ(6, break_point_hit_count);
3801
3802   // Check stepping where the if condition in bar is true.
3803   break_point_hit_count = 0;
3804   const int argc = 1;
3805   v8::Handle<v8::Value> argv[argc] = { v8::True(isolate) };
3806   foo->Call(env->Global(), argc, argv);
3807   CHECK_EQ(8, break_point_hit_count);
3808
3809   v8::Debug::SetDebugEventListener(NULL);
3810   CheckDebuggerUnloaded();
3811
3812   // Register a debug event listener which just counts.
3813   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
3814
3815   break_point_hit_count = 0;
3816   foo->Call(env->Global(), 0, NULL);
3817
3818   // Without stepping only the debugger statement is hit.
3819   CHECK_EQ(1, break_point_hit_count);
3820
3821   v8::Debug::SetDebugEventListener(NULL);
3822   CheckDebuggerUnloaded();
3823 }
3824
3825
3826 // Tests that breakpoint will be hit if it's set in script.
3827 TEST(PauseInScript) {
3828   DebugLocalContext env;
3829   v8::HandleScope scope(env->GetIsolate());
3830   env.ExposeDebug();
3831
3832   // Register a debug event listener which counts.
3833   v8::Debug::SetDebugEventListener(DebugEventCounter);
3834
3835   // Create a script that returns a function.
3836   const char* src = "(function (evt) {})";
3837   const char* script_name = "StepInHandlerTest";
3838
3839   // Set breakpoint in the script.
3840   SetScriptBreakPointByNameFromJS(env->GetIsolate(), script_name, 0, -1);
3841   break_point_hit_count = 0;
3842
3843   v8::ScriptOrigin origin(
3844       v8::String::NewFromUtf8(env->GetIsolate(), script_name),
3845       v8::Integer::New(env->GetIsolate(), 0));
3846   v8::Handle<v8::Script> script = v8::Script::Compile(
3847       v8::String::NewFromUtf8(env->GetIsolate(), src), &origin);
3848   v8::Local<v8::Value> r = script->Run();
3849
3850   CHECK(r->IsFunction());
3851   CHECK_EQ(1, break_point_hit_count);
3852
3853   // Get rid of the debug event listener.
3854   v8::Debug::SetDebugEventListener(NULL);
3855   CheckDebuggerUnloaded();
3856 }
3857
3858
3859 // Test break on exceptions. For each exception break combination the number
3860 // of debug event exception callbacks and message callbacks are collected. The
3861 // number of debug event exception callbacks are used to check that the
3862 // debugger is called correctly and the number of message callbacks is used to
3863 // check that uncaught exceptions are still returned even if there is a break
3864 // for them.
3865 TEST(BreakOnException) {
3866   DebugLocalContext env;
3867   v8::HandleScope scope(env->GetIsolate());
3868   env.ExposeDebug();
3869
3870   // Create functions for testing break on exception.
3871   CompileFunction(&env, "function throws(){throw 1;}", "throws");
3872   v8::Local<v8::Function> caught =
3873       CompileFunction(&env,
3874                       "function caught(){try {throws();} catch(e) {};}",
3875                       "caught");
3876   v8::Local<v8::Function> notCaught =
3877       CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
3878
3879   v8::V8::AddMessageListener(MessageCallbackCount);
3880   v8::Debug::SetDebugEventListener(DebugEventCounter);
3881
3882   // Initial state should be no break on exceptions.
3883   DebugEventCounterClear();
3884   MessageCallbackCountClear();
3885   caught->Call(env->Global(), 0, NULL);
3886   CHECK_EQ(0, exception_hit_count);
3887   CHECK_EQ(0, uncaught_exception_hit_count);
3888   CHECK_EQ(0, message_callback_count);
3889   notCaught->Call(env->Global(), 0, NULL);
3890   CHECK_EQ(0, exception_hit_count);
3891   CHECK_EQ(0, uncaught_exception_hit_count);
3892   CHECK_EQ(1, message_callback_count);
3893
3894   // No break on exception
3895   DebugEventCounterClear();
3896   MessageCallbackCountClear();
3897   ChangeBreakOnException(false, false);
3898   caught->Call(env->Global(), 0, NULL);
3899   CHECK_EQ(0, exception_hit_count);
3900   CHECK_EQ(0, uncaught_exception_hit_count);
3901   CHECK_EQ(0, message_callback_count);
3902   notCaught->Call(env->Global(), 0, NULL);
3903   CHECK_EQ(0, exception_hit_count);
3904   CHECK_EQ(0, uncaught_exception_hit_count);
3905   CHECK_EQ(1, message_callback_count);
3906
3907   // Break on uncaught exception
3908   DebugEventCounterClear();
3909   MessageCallbackCountClear();
3910   ChangeBreakOnException(false, true);
3911   caught->Call(env->Global(), 0, NULL);
3912   CHECK_EQ(0, exception_hit_count);
3913   CHECK_EQ(0, uncaught_exception_hit_count);
3914   CHECK_EQ(0, message_callback_count);
3915   notCaught->Call(env->Global(), 0, NULL);
3916   CHECK_EQ(1, exception_hit_count);
3917   CHECK_EQ(1, uncaught_exception_hit_count);
3918   CHECK_EQ(1, message_callback_count);
3919
3920   // Break on exception and uncaught exception
3921   DebugEventCounterClear();
3922   MessageCallbackCountClear();
3923   ChangeBreakOnException(true, true);
3924   caught->Call(env->Global(), 0, NULL);
3925   CHECK_EQ(1, exception_hit_count);
3926   CHECK_EQ(0, uncaught_exception_hit_count);
3927   CHECK_EQ(0, message_callback_count);
3928   notCaught->Call(env->Global(), 0, NULL);
3929   CHECK_EQ(2, exception_hit_count);
3930   CHECK_EQ(1, uncaught_exception_hit_count);
3931   CHECK_EQ(1, message_callback_count);
3932
3933   // Break on exception
3934   DebugEventCounterClear();
3935   MessageCallbackCountClear();
3936   ChangeBreakOnException(true, false);
3937   caught->Call(env->Global(), 0, NULL);
3938   CHECK_EQ(1, exception_hit_count);
3939   CHECK_EQ(0, uncaught_exception_hit_count);
3940   CHECK_EQ(0, message_callback_count);
3941   notCaught->Call(env->Global(), 0, NULL);
3942   CHECK_EQ(2, exception_hit_count);
3943   CHECK_EQ(1, uncaught_exception_hit_count);
3944   CHECK_EQ(1, message_callback_count);
3945
3946   // No break on exception using JavaScript
3947   DebugEventCounterClear();
3948   MessageCallbackCountClear();
3949   ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, false);
3950   caught->Call(env->Global(), 0, NULL);
3951   CHECK_EQ(0, exception_hit_count);
3952   CHECK_EQ(0, uncaught_exception_hit_count);
3953   CHECK_EQ(0, message_callback_count);
3954   notCaught->Call(env->Global(), 0, NULL);
3955   CHECK_EQ(0, exception_hit_count);
3956   CHECK_EQ(0, uncaught_exception_hit_count);
3957   CHECK_EQ(1, message_callback_count);
3958
3959   // Break on uncaught exception using JavaScript
3960   DebugEventCounterClear();
3961   MessageCallbackCountClear();
3962   ChangeBreakOnExceptionFromJS(env->GetIsolate(), false, true);
3963   caught->Call(env->Global(), 0, NULL);
3964   CHECK_EQ(0, exception_hit_count);
3965   CHECK_EQ(0, uncaught_exception_hit_count);
3966   CHECK_EQ(0, message_callback_count);
3967   notCaught->Call(env->Global(), 0, NULL);
3968   CHECK_EQ(1, exception_hit_count);
3969   CHECK_EQ(1, uncaught_exception_hit_count);
3970   CHECK_EQ(1, message_callback_count);
3971
3972   // Break on exception and uncaught exception using JavaScript
3973   DebugEventCounterClear();
3974   MessageCallbackCountClear();
3975   ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, true);
3976   caught->Call(env->Global(), 0, NULL);
3977   CHECK_EQ(1, exception_hit_count);
3978   CHECK_EQ(0, message_callback_count);
3979   CHECK_EQ(0, uncaught_exception_hit_count);
3980   notCaught->Call(env->Global(), 0, NULL);
3981   CHECK_EQ(2, exception_hit_count);
3982   CHECK_EQ(1, uncaught_exception_hit_count);
3983   CHECK_EQ(1, message_callback_count);
3984
3985   // Break on exception using JavaScript
3986   DebugEventCounterClear();
3987   MessageCallbackCountClear();
3988   ChangeBreakOnExceptionFromJS(env->GetIsolate(), true, false);
3989   caught->Call(env->Global(), 0, NULL);
3990   CHECK_EQ(1, exception_hit_count);
3991   CHECK_EQ(0, uncaught_exception_hit_count);
3992   CHECK_EQ(0, message_callback_count);
3993   notCaught->Call(env->Global(), 0, NULL);
3994   CHECK_EQ(2, exception_hit_count);
3995   CHECK_EQ(1, uncaught_exception_hit_count);
3996   CHECK_EQ(1, message_callback_count);
3997
3998   v8::Debug::SetDebugEventListener(NULL);
3999   CheckDebuggerUnloaded();
4000   v8::V8::RemoveMessageListeners(MessageCallbackCount);
4001 }
4002
4003
4004 TEST(EvalJSInDebugEventListenerOnNativeReThrownException) {
4005   DebugLocalContext env;
4006   v8::HandleScope scope(env->GetIsolate());
4007   env.ExposeDebug();
4008
4009   // Create functions for testing break on exception.
4010   v8::Local<v8::Function> noThrowJS = CompileFunction(
4011       &env, "function noThrowJS(){var a=[1]; a.push(2); return a.length;}",
4012       "noThrowJS");
4013
4014   debug_event_listener_callback = noThrowJS;
4015   debug_event_listener_callback_result = 2;
4016
4017   v8::V8::AddMessageListener(MessageCallbackCount);
4018   v8::Debug::SetDebugEventListener(DebugEventCounter);
4019   // Break on uncaught exception
4020   ChangeBreakOnException(false, true);
4021   DebugEventCounterClear();
4022   MessageCallbackCountClear();
4023
4024   // ReThrow native error
4025   {
4026     v8::TryCatch tryCatch;
4027     env->GetIsolate()->ThrowException(v8::Exception::TypeError(
4028         v8::String::NewFromUtf8(env->GetIsolate(), "Type error")));
4029     CHECK(tryCatch.HasCaught());
4030     tryCatch.ReThrow();
4031   }
4032   CHECK_EQ(1, exception_hit_count);
4033   CHECK_EQ(1, uncaught_exception_hit_count);
4034   CHECK_EQ(0, message_callback_count);  // FIXME: Should it be 1 ?
4035   CHECK(!debug_event_listener_callback.IsEmpty());
4036
4037   debug_event_listener_callback.Clear();
4038 }
4039
4040
4041 // Test break on exception from compiler errors. When compiling using
4042 // v8::Script::Compile there is no JavaScript stack whereas when compiling using
4043 // eval there are JavaScript frames.
4044 TEST(BreakOnCompileException) {
4045   DebugLocalContext env;
4046   v8::HandleScope scope(env->GetIsolate());
4047
4048   // For this test, we want to break on uncaught exceptions:
4049   ChangeBreakOnException(false, true);
4050
4051   // Create a function for checking the function when hitting a break point.
4052   frame_count = CompileFunction(&env, frame_count_source, "frame_count");
4053
4054   v8::V8::AddMessageListener(MessageCallbackCount);
4055   v8::Debug::SetDebugEventListener(DebugEventCounter);
4056
4057   DebugEventCounterClear();
4058   MessageCallbackCountClear();
4059
4060   // Check initial state.
4061   CHECK_EQ(0, exception_hit_count);
4062   CHECK_EQ(0, uncaught_exception_hit_count);
4063   CHECK_EQ(0, message_callback_count);
4064   CHECK_EQ(-1, last_js_stack_height);
4065
4066   // Throws SyntaxError: Unexpected end of input
4067   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "+++"));
4068   CHECK_EQ(1, exception_hit_count);
4069   CHECK_EQ(1, uncaught_exception_hit_count);
4070   CHECK_EQ(1, message_callback_count);
4071   CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
4072
4073   // Throws SyntaxError: Unexpected identifier
4074   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "x x"));
4075   CHECK_EQ(2, exception_hit_count);
4076   CHECK_EQ(2, uncaught_exception_hit_count);
4077   CHECK_EQ(2, message_callback_count);
4078   CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
4079
4080   // Throws SyntaxError: Unexpected end of input
4081   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "eval('+++')"))
4082       ->Run();
4083   CHECK_EQ(3, exception_hit_count);
4084   CHECK_EQ(3, uncaught_exception_hit_count);
4085   CHECK_EQ(3, message_callback_count);
4086   CHECK_EQ(1, last_js_stack_height);
4087
4088   // Throws SyntaxError: Unexpected identifier
4089   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "eval('x x')"))
4090       ->Run();
4091   CHECK_EQ(4, exception_hit_count);
4092   CHECK_EQ(4, uncaught_exception_hit_count);
4093   CHECK_EQ(4, message_callback_count);
4094   CHECK_EQ(1, last_js_stack_height);
4095 }
4096
4097
4098 TEST(StepWithException) {
4099   DebugLocalContext env;
4100   v8::HandleScope scope(env->GetIsolate());
4101
4102   // For this test, we want to break on uncaught exceptions:
4103   ChangeBreakOnException(false, true);
4104
4105   // Create a function for checking the function when hitting a break point.
4106   frame_function_name = CompileFunction(&env,
4107                                         frame_function_name_source,
4108                                         "frame_function_name");
4109
4110   // Register a debug event listener which steps and counts.
4111   v8::Debug::SetDebugEventListener(DebugEventStepSequence);
4112
4113   // Create functions for testing stepping.
4114   const char* src = "function a() { n(); }; "
4115                     "function b() { c(); }; "
4116                     "function c() { n(); }; "
4117                     "function d() { x = 1; try { e(); } catch(x) { x = 2; } }; "
4118                     "function e() { n(); }; "
4119                     "function f() { x = 1; try { g(); } catch(x) { x = 2; } }; "
4120                     "function g() { h(); }; "
4121                     "function h() { x = 1; throw 1; }; ";
4122
4123   // Step through invocation of a.
4124   v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
4125   SetBreakPoint(a, 0);
4126   step_action = StepIn;
4127   break_point_hit_count = 0;
4128   expected_step_sequence = "aa";
4129   a->Call(env->Global(), 0, NULL);
4130   CHECK_EQ(StrLength(expected_step_sequence),
4131            break_point_hit_count);
4132
4133   // Step through invocation of b + c.
4134   v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
4135   SetBreakPoint(b, 0);
4136   step_action = StepIn;
4137   break_point_hit_count = 0;
4138   expected_step_sequence = "bcc";
4139   b->Call(env->Global(), 0, NULL);
4140   CHECK_EQ(StrLength(expected_step_sequence),
4141            break_point_hit_count);
4142   // Step through invocation of d + e.
4143   v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
4144   SetBreakPoint(d, 0);
4145   ChangeBreakOnException(false, true);
4146   step_action = StepIn;
4147   break_point_hit_count = 0;
4148   expected_step_sequence = "ddedd";
4149   d->Call(env->Global(), 0, NULL);
4150   CHECK_EQ(StrLength(expected_step_sequence),
4151            break_point_hit_count);
4152
4153   // Step through invocation of d + e now with break on caught exceptions.
4154   ChangeBreakOnException(true, true);
4155   step_action = StepIn;
4156   break_point_hit_count = 0;
4157   expected_step_sequence = "ddeedd";
4158   d->Call(env->Global(), 0, NULL);
4159   CHECK_EQ(StrLength(expected_step_sequence),
4160            break_point_hit_count);
4161
4162   // Step through invocation of f + g + h.
4163   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4164   SetBreakPoint(f, 0);
4165   ChangeBreakOnException(false, true);
4166   step_action = StepIn;
4167   break_point_hit_count = 0;
4168   expected_step_sequence = "ffghhff";
4169   f->Call(env->Global(), 0, NULL);
4170   CHECK_EQ(StrLength(expected_step_sequence),
4171            break_point_hit_count);
4172
4173   // Step through invocation of f + g + h now with break on caught exceptions.
4174   ChangeBreakOnException(true, true);
4175   step_action = StepIn;
4176   break_point_hit_count = 0;
4177   expected_step_sequence = "ffghhhff";
4178   f->Call(env->Global(), 0, NULL);
4179   CHECK_EQ(StrLength(expected_step_sequence),
4180            break_point_hit_count);
4181
4182   // Get rid of the debug event listener.
4183   v8::Debug::SetDebugEventListener(NULL);
4184   CheckDebuggerUnloaded();
4185 }
4186
4187
4188 TEST(DebugBreak) {
4189   i::FLAG_stress_compaction = false;
4190 #ifdef VERIFY_HEAP
4191   i::FLAG_verify_heap = true;
4192 #endif
4193   DebugLocalContext env;
4194   v8::Isolate* isolate = env->GetIsolate();
4195   v8::HandleScope scope(isolate);
4196
4197   // Register a debug event listener which sets the break flag and counts.
4198   v8::Debug::SetDebugEventListener(DebugEventBreak);
4199
4200   // Create a function for testing stepping.
4201   const char* src = "function f0() {}"
4202                     "function f1(x1) {}"
4203                     "function f2(x1,x2) {}"
4204                     "function f3(x1,x2,x3) {}";
4205   v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
4206   v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
4207   v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
4208   v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
4209
4210   // Call the function to make sure it is compiled.
4211   v8::Handle<v8::Value> argv[] = { v8::Number::New(isolate, 1),
4212                                    v8::Number::New(isolate, 1),
4213                                    v8::Number::New(isolate, 1),
4214                                    v8::Number::New(isolate, 1) };
4215
4216   // Call all functions to make sure that they are compiled.
4217   f0->Call(env->Global(), 0, NULL);
4218   f1->Call(env->Global(), 0, NULL);
4219   f2->Call(env->Global(), 0, NULL);
4220   f3->Call(env->Global(), 0, NULL);
4221
4222   // Set the debug break flag.
4223   v8::Debug::DebugBreak(env->GetIsolate());
4224   CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate()));
4225
4226   // Call all functions with different argument count.
4227   break_point_hit_count = 0;
4228   for (unsigned int i = 0; i < arraysize(argv); i++) {
4229     f0->Call(env->Global(), i, argv);
4230     f1->Call(env->Global(), i, argv);
4231     f2->Call(env->Global(), i, argv);
4232     f3->Call(env->Global(), i, argv);
4233   }
4234
4235   // One break for each function called.
4236   CHECK(4 * arraysize(argv) == break_point_hit_count);
4237
4238   // Get rid of the debug event listener.
4239   v8::Debug::SetDebugEventListener(NULL);
4240   CheckDebuggerUnloaded();
4241 }
4242
4243
4244 // Test to ensure that JavaScript code keeps running while the debug break
4245 // through the stack limit flag is set but breaks are disabled.
4246 TEST(DisableBreak) {
4247   DebugLocalContext env;
4248   v8::HandleScope scope(env->GetIsolate());
4249
4250   // Register a debug event listener which sets the break flag and counts.
4251   v8::Debug::SetDebugEventListener(DebugEventCounter);
4252
4253   // Create a function for testing stepping.
4254   const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
4255   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4256
4257   // Set, test and cancel debug break.
4258   v8::Debug::DebugBreak(env->GetIsolate());
4259   CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate()));
4260   v8::Debug::CancelDebugBreak(env->GetIsolate());
4261   CHECK(!v8::Debug::CheckDebugBreak(env->GetIsolate()));
4262
4263   // Set the debug break flag.
4264   v8::Debug::DebugBreak(env->GetIsolate());
4265
4266   // Call all functions with different argument count.
4267   break_point_hit_count = 0;
4268   f->Call(env->Global(), 0, NULL);
4269   CHECK_EQ(1, break_point_hit_count);
4270
4271   {
4272     v8::Debug::DebugBreak(env->GetIsolate());
4273     i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
4274     v8::internal::DisableBreak disable_break(isolate->debug(), true);
4275     f->Call(env->Global(), 0, NULL);
4276     CHECK_EQ(1, break_point_hit_count);
4277   }
4278
4279   f->Call(env->Global(), 0, NULL);
4280   CHECK_EQ(2, break_point_hit_count);
4281
4282   // Get rid of the debug event listener.
4283   v8::Debug::SetDebugEventListener(NULL);
4284   CheckDebuggerUnloaded();
4285 }
4286
4287 static const char* kSimpleExtensionSource =
4288   "(function Foo() {"
4289   "  return 4;"
4290   "})() ";
4291
4292 // http://crbug.com/28933
4293 // Test that debug break is disabled when bootstrapper is active.
4294 TEST(NoBreakWhenBootstrapping) {
4295   v8::Isolate* isolate = CcTest::isolate();
4296   v8::HandleScope scope(isolate);
4297
4298   // Register a debug event listener which sets the break flag and counts.
4299   v8::Debug::SetDebugEventListener(DebugEventCounter);
4300
4301   // Set the debug break flag.
4302   v8::Debug::DebugBreak(isolate);
4303   break_point_hit_count = 0;
4304   {
4305     // Create a context with an extension to make sure that some JavaScript
4306     // code is executed during bootstrapping.
4307     v8::RegisterExtension(new v8::Extension("simpletest",
4308                                             kSimpleExtensionSource));
4309     const char* extension_names[] = { "simpletest" };
4310     v8::ExtensionConfiguration extensions(1, extension_names);
4311     v8::HandleScope handle_scope(isolate);
4312     v8::Context::New(isolate, &extensions);
4313   }
4314   // Check that no DebugBreak events occured during the context creation.
4315   CHECK_EQ(0, break_point_hit_count);
4316
4317   // Get rid of the debug event listener.
4318   v8::Debug::SetDebugEventListener(NULL);
4319   CheckDebuggerUnloaded();
4320 }
4321
4322
4323 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4324   v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
4325   result->Set(v8::Integer::New(info.GetIsolate(), 0),
4326               v8::String::NewFromUtf8(info.GetIsolate(), "a"));
4327   result->Set(v8::Integer::New(info.GetIsolate(), 1),
4328               v8::String::NewFromUtf8(info.GetIsolate(), "b"));
4329   result->Set(v8::Integer::New(info.GetIsolate(), 2),
4330               v8::String::NewFromUtf8(info.GetIsolate(), "c"));
4331   info.GetReturnValue().Set(result);
4332 }
4333
4334
4335 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4336   v8::Isolate* isolate = info.GetIsolate();
4337   v8::Handle<v8::Array> result = v8::Array::New(isolate, 2);
4338   result->Set(v8::Integer::New(isolate, 0), v8::Number::New(isolate, 1));
4339   result->Set(v8::Integer::New(isolate, 1), v8::Number::New(isolate, 10));
4340   info.GetReturnValue().Set(result);
4341 }
4342
4343
4344 static void NamedGetter(v8::Local<v8::Name> name,
4345                         const v8::PropertyCallbackInfo<v8::Value>& info) {
4346   if (name->IsSymbol()) return;
4347   v8::String::Utf8Value n(v8::Local<v8::String>::Cast(name));
4348   if (strcmp(*n, "a") == 0) {
4349     info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "AA"));
4350     return;
4351   } else if (strcmp(*n, "b") == 0) {
4352     info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "BB"));
4353     return;
4354   } else if (strcmp(*n, "c") == 0) {
4355     info.GetReturnValue().Set(v8::String::NewFromUtf8(info.GetIsolate(), "CC"));
4356     return;
4357   } else {
4358     info.GetReturnValue().SetUndefined();
4359     return;
4360   }
4361   info.GetReturnValue().Set(name);
4362 }
4363
4364
4365 static void IndexedGetter(uint32_t index,
4366                           const v8::PropertyCallbackInfo<v8::Value>& info) {
4367   info.GetReturnValue().Set(static_cast<double>(index + 1));
4368 }
4369
4370
4371 TEST(InterceptorPropertyMirror) {
4372   // Create a V8 environment with debug access.
4373   DebugLocalContext env;
4374   v8::Isolate* isolate = env->GetIsolate();
4375   v8::HandleScope scope(isolate);
4376   env.ExposeDebug();
4377
4378   // Create object with named interceptor.
4379   v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4380   named->SetHandler(v8::NamedPropertyHandlerConfiguration(
4381       NamedGetter, NULL, NULL, NULL, NamedEnum));
4382   env->Global()->Set(
4383       v8::String::NewFromUtf8(isolate, "intercepted_named"),
4384       named->NewInstance());
4385
4386   // Create object with indexed interceptor.
4387   v8::Handle<v8::ObjectTemplate> indexed = v8::ObjectTemplate::New(isolate);
4388   indexed->SetHandler(v8::IndexedPropertyHandlerConfiguration(
4389       IndexedGetter, NULL, NULL, NULL, IndexedEnum));
4390   env->Global()->Set(
4391       v8::String::NewFromUtf8(isolate, "intercepted_indexed"),
4392       indexed->NewInstance());
4393
4394   // Create object with both named and indexed interceptor.
4395   v8::Handle<v8::ObjectTemplate> both = v8::ObjectTemplate::New(isolate);
4396   both->SetHandler(v8::NamedPropertyHandlerConfiguration(
4397       NamedGetter, NULL, NULL, NULL, NamedEnum));
4398   both->SetHandler(v8::IndexedPropertyHandlerConfiguration(
4399       IndexedGetter, NULL, NULL, NULL, IndexedEnum));
4400   env->Global()->Set(
4401       v8::String::NewFromUtf8(isolate, "intercepted_both"),
4402       both->NewInstance());
4403
4404   // Get mirrors for the three objects with interceptor.
4405   CompileRun(
4406       "var named_mirror = debug.MakeMirror(intercepted_named);"
4407       "var indexed_mirror = debug.MakeMirror(intercepted_indexed);"
4408       "var both_mirror = debug.MakeMirror(intercepted_both)");
4409   CHECK(CompileRun(
4410        "named_mirror instanceof debug.ObjectMirror")->BooleanValue());
4411   CHECK(CompileRun(
4412         "indexed_mirror instanceof debug.ObjectMirror")->BooleanValue());
4413   CHECK(CompileRun(
4414         "both_mirror instanceof debug.ObjectMirror")->BooleanValue());
4415
4416   // Get the property names from the interceptors
4417   CompileRun(
4418       "named_names = named_mirror.propertyNames();"
4419       "indexed_names = indexed_mirror.propertyNames();"
4420       "both_names = both_mirror.propertyNames()");
4421   CHECK_EQ(3, CompileRun("named_names.length")->Int32Value());
4422   CHECK_EQ(2, CompileRun("indexed_names.length")->Int32Value());
4423   CHECK_EQ(5, CompileRun("both_names.length")->Int32Value());
4424
4425   // Check the expected number of properties.
4426   const char* source;
4427   source = "named_mirror.properties().length";
4428   CHECK_EQ(3, CompileRun(source)->Int32Value());
4429
4430   source = "indexed_mirror.properties().length";
4431   CHECK_EQ(2, CompileRun(source)->Int32Value());
4432
4433   source = "both_mirror.properties().length";
4434   CHECK_EQ(5, CompileRun(source)->Int32Value());
4435
4436   // 1 is PropertyKind.Named;
4437   source = "both_mirror.properties(1).length";
4438   CHECK_EQ(3, CompileRun(source)->Int32Value());
4439
4440   // 2 is PropertyKind.Indexed;
4441   source = "both_mirror.properties(2).length";
4442   CHECK_EQ(2, CompileRun(source)->Int32Value());
4443
4444   // 3 is PropertyKind.Named  | PropertyKind.Indexed;
4445   source = "both_mirror.properties(3).length";
4446   CHECK_EQ(5, CompileRun(source)->Int32Value());
4447
4448   // Get the interceptor properties for the object with only named interceptor.
4449   CompileRun("var named_values = named_mirror.properties()");
4450
4451   // Check that the properties are interceptor properties.
4452   for (int i = 0; i < 3; i++) {
4453     EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4454     SNPrintF(buffer,
4455              "named_values[%d] instanceof debug.PropertyMirror", i);
4456     CHECK(CompileRun(buffer.start())->BooleanValue());
4457
4458     SNPrintF(buffer, "named_values[%d].isNative()", i);
4459     CHECK(CompileRun(buffer.start())->BooleanValue());
4460   }
4461
4462   // Get the interceptor properties for the object with only indexed
4463   // interceptor.
4464   CompileRun("var indexed_values = indexed_mirror.properties()");
4465
4466   // Check that the properties are interceptor properties.
4467   for (int i = 0; i < 2; i++) {
4468     EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4469     SNPrintF(buffer,
4470              "indexed_values[%d] instanceof debug.PropertyMirror", i);
4471     CHECK(CompileRun(buffer.start())->BooleanValue());
4472   }
4473
4474   // Get the interceptor properties for the object with both types of
4475   // interceptors.
4476   CompileRun("var both_values = both_mirror.properties()");
4477
4478   // Check that the properties are interceptor properties.
4479   for (int i = 0; i < 5; i++) {
4480     EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4481     SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
4482     CHECK(CompileRun(buffer.start())->BooleanValue());
4483   }
4484
4485   // Check the property names.
4486   source = "both_values[0].name() == 'a'";
4487   CHECK(CompileRun(source)->BooleanValue());
4488
4489   source = "both_values[1].name() == 'b'";
4490   CHECK(CompileRun(source)->BooleanValue());
4491
4492   source = "both_values[2].name() == 'c'";
4493   CHECK(CompileRun(source)->BooleanValue());
4494
4495   source = "both_values[3].name() == 1";
4496   CHECK(CompileRun(source)->BooleanValue());
4497
4498   source = "both_values[4].name() == 10";
4499   CHECK(CompileRun(source)->BooleanValue());
4500 }
4501
4502
4503 TEST(HiddenPrototypePropertyMirror) {
4504   // Create a V8 environment with debug access.
4505   DebugLocalContext env;
4506   v8::Isolate* isolate = env->GetIsolate();
4507   v8::HandleScope scope(isolate);
4508   env.ExposeDebug();
4509
4510   v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
4511   t0->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "x"),
4512                               v8::Number::New(isolate, 0));
4513   v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
4514   t1->SetHiddenPrototype(true);
4515   t1->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "y"),
4516                               v8::Number::New(isolate, 1));
4517   v8::Handle<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
4518   t2->SetHiddenPrototype(true);
4519   t2->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "z"),
4520                               v8::Number::New(isolate, 2));
4521   v8::Handle<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
4522   t3->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "u"),
4523                               v8::Number::New(isolate, 3));
4524
4525   // Create object and set them on the global object.
4526   v8::Handle<v8::Object> o0 = t0->GetFunction()->NewInstance();
4527   env->Global()->Set(v8::String::NewFromUtf8(isolate, "o0"), o0);
4528   v8::Handle<v8::Object> o1 = t1->GetFunction()->NewInstance();
4529   env->Global()->Set(v8::String::NewFromUtf8(isolate, "o1"), o1);
4530   v8::Handle<v8::Object> o2 = t2->GetFunction()->NewInstance();
4531   env->Global()->Set(v8::String::NewFromUtf8(isolate, "o2"), o2);
4532   v8::Handle<v8::Object> o3 = t3->GetFunction()->NewInstance();
4533   env->Global()->Set(v8::String::NewFromUtf8(isolate, "o3"), o3);
4534
4535   // Get mirrors for the four objects.
4536   CompileRun(
4537       "var o0_mirror = debug.MakeMirror(o0);"
4538       "var o1_mirror = debug.MakeMirror(o1);"
4539       "var o2_mirror = debug.MakeMirror(o2);"
4540       "var o3_mirror = debug.MakeMirror(o3)");
4541   CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")->BooleanValue());
4542   CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")->BooleanValue());
4543   CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")->BooleanValue());
4544   CHECK(CompileRun("o3_mirror instanceof debug.ObjectMirror")->BooleanValue());
4545
4546   // Check that each object has one property.
4547   CHECK_EQ(1, CompileRun(
4548               "o0_mirror.propertyNames().length")->Int32Value());
4549   CHECK_EQ(1, CompileRun(
4550               "o1_mirror.propertyNames().length")->Int32Value());
4551   CHECK_EQ(1, CompileRun(
4552               "o2_mirror.propertyNames().length")->Int32Value());
4553   CHECK_EQ(1, CompileRun(
4554               "o3_mirror.propertyNames().length")->Int32Value());
4555
4556   // Set o1 as prototype for o0. o1 has the hidden prototype flag so all
4557   // properties on o1 should be seen on o0.
4558   o0->Set(v8::String::NewFromUtf8(isolate, "__proto__"), o1);
4559   CHECK_EQ(2, CompileRun(
4560               "o0_mirror.propertyNames().length")->Int32Value());
4561   CHECK_EQ(0, CompileRun(
4562               "o0_mirror.property('x').value().value()")->Int32Value());
4563   CHECK_EQ(1, CompileRun(
4564               "o0_mirror.property('y').value().value()")->Int32Value());
4565
4566   // Set o2 as prototype for o0 (it will end up after o1 as o1 has the hidden
4567   // prototype flag. o2 also has the hidden prototype flag so all properties
4568   // on o2 should be seen on o0 as well as properties on o1.
4569   o0->Set(v8::String::NewFromUtf8(isolate, "__proto__"), o2);
4570   CHECK_EQ(3, CompileRun(
4571               "o0_mirror.propertyNames().length")->Int32Value());
4572   CHECK_EQ(0, CompileRun(
4573               "o0_mirror.property('x').value().value()")->Int32Value());
4574   CHECK_EQ(1, CompileRun(
4575               "o0_mirror.property('y').value().value()")->Int32Value());
4576   CHECK_EQ(2, CompileRun(
4577               "o0_mirror.property('z').value().value()")->Int32Value());
4578
4579   // Set o3 as prototype for o0 (it will end up after o1 and o2 as both o1 and
4580   // o2 has the hidden prototype flag. o3 does not have the hidden prototype
4581   // flag so properties on o3 should not be seen on o0 whereas the properties
4582   // from o1 and o2 should still be seen on o0.
4583   // Final prototype chain: o0 -> o1 -> o2 -> o3
4584   // Hidden prototypes:           ^^    ^^
4585   o0->Set(v8::String::NewFromUtf8(isolate, "__proto__"), o3);
4586   CHECK_EQ(3, CompileRun(
4587               "o0_mirror.propertyNames().length")->Int32Value());
4588   CHECK_EQ(1, CompileRun(
4589               "o3_mirror.propertyNames().length")->Int32Value());
4590   CHECK_EQ(0, CompileRun(
4591               "o0_mirror.property('x').value().value()")->Int32Value());
4592   CHECK_EQ(1, CompileRun(
4593               "o0_mirror.property('y').value().value()")->Int32Value());
4594   CHECK_EQ(2, CompileRun(
4595               "o0_mirror.property('z').value().value()")->Int32Value());
4596   CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue());
4597
4598   // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden.
4599   CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue());
4600 }
4601
4602
4603 static void ProtperyXNativeGetter(
4604     v8::Local<v8::String> property,
4605     const v8::PropertyCallbackInfo<v8::Value>& info) {
4606   info.GetReturnValue().Set(10);
4607 }
4608
4609
4610 TEST(NativeGetterPropertyMirror) {
4611   // Create a V8 environment with debug access.
4612   DebugLocalContext env;
4613   v8::Isolate* isolate = env->GetIsolate();
4614   v8::HandleScope scope(isolate);
4615   env.ExposeDebug();
4616
4617   v8::Handle<v8::String> name = v8::String::NewFromUtf8(isolate, "x");
4618   // Create object with named accessor.
4619   v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4620   named->SetAccessor(name, &ProtperyXNativeGetter, NULL,
4621       v8::Handle<v8::Value>(), v8::DEFAULT, v8::None);
4622
4623   // Create object with named property getter.
4624   env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
4625                      named->NewInstance());
4626   CHECK_EQ(10, CompileRun("instance.x")->Int32Value());
4627
4628   // Get mirror for the object with property getter.
4629   CompileRun("var instance_mirror = debug.MakeMirror(instance);");
4630   CHECK(CompileRun(
4631       "instance_mirror instanceof debug.ObjectMirror")->BooleanValue());
4632
4633   CompileRun("var named_names = instance_mirror.propertyNames();");
4634   CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4635   CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue());
4636   CHECK(CompileRun(
4637       "instance_mirror.property('x').value().isNumber()")->BooleanValue());
4638   CHECK(CompileRun(
4639       "instance_mirror.property('x').value().value() == 10")->BooleanValue());
4640 }
4641
4642
4643 static void ProtperyXNativeGetterThrowingError(
4644     v8::Local<v8::String> property,
4645     const v8::PropertyCallbackInfo<v8::Value>& info) {
4646   CompileRun("throw new Error('Error message');");
4647 }
4648
4649
4650 TEST(NativeGetterThrowingErrorPropertyMirror) {
4651   // Create a V8 environment with debug access.
4652   DebugLocalContext env;
4653   v8::Isolate* isolate = env->GetIsolate();
4654   v8::HandleScope scope(isolate);
4655   env.ExposeDebug();
4656
4657   v8::Handle<v8::String> name = v8::String::NewFromUtf8(isolate, "x");
4658   // Create object with named accessor.
4659   v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
4660   named->SetAccessor(name, &ProtperyXNativeGetterThrowingError, NULL,
4661       v8::Handle<v8::Value>(), v8::DEFAULT, v8::None);
4662
4663   // Create object with named property getter.
4664   env->Global()->Set(v8::String::NewFromUtf8(isolate, "instance"),
4665                      named->NewInstance());
4666
4667   // Get mirror for the object with property getter.
4668   CompileRun("var instance_mirror = debug.MakeMirror(instance);");
4669   CHECK(CompileRun(
4670       "instance_mirror instanceof debug.ObjectMirror")->BooleanValue());
4671   CompileRun("named_names = instance_mirror.propertyNames();");
4672   CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4673   CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue());
4674   CHECK(CompileRun(
4675       "instance_mirror.property('x').value().isError()")->BooleanValue());
4676
4677   // Check that the message is that passed to the Error constructor.
4678   CHECK(CompileRun(
4679       "instance_mirror.property('x').value().message() == 'Error message'")->
4680           BooleanValue());
4681 }
4682
4683
4684 // Test that hidden properties object is not returned as an unnamed property
4685 // among regular properties.
4686 // See http://crbug.com/26491
4687 TEST(NoHiddenProperties) {
4688   // Create a V8 environment with debug access.
4689   DebugLocalContext env;
4690   v8::Isolate* isolate = env->GetIsolate();
4691   v8::HandleScope scope(isolate);
4692   env.ExposeDebug();
4693
4694   // Create an object in the global scope.
4695   const char* source = "var obj = {a: 1};";
4696   v8::Script::Compile(v8::String::NewFromUtf8(isolate, source))
4697       ->Run();
4698   v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
4699       env->Global()->Get(v8::String::NewFromUtf8(isolate, "obj")));
4700   // Set a hidden property on the object.
4701   obj->SetHiddenValue(
4702       v8::String::NewFromUtf8(isolate, "v8::test-debug::a"),
4703       v8::Int32::New(isolate, 11));
4704
4705   // Get mirror for the object with property getter.
4706   CompileRun("var obj_mirror = debug.MakeMirror(obj);");
4707   CHECK(CompileRun(
4708       "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
4709   CompileRun("var named_names = obj_mirror.propertyNames();");
4710   // There should be exactly one property. But there is also an unnamed
4711   // property whose value is hidden properties dictionary. The latter
4712   // property should not be in the list of reguar properties.
4713   CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4714   CHECK(CompileRun("named_names[0] == 'a'")->BooleanValue());
4715   CHECK(CompileRun(
4716       "obj_mirror.property('a').value().value() == 1")->BooleanValue());
4717
4718   // Object created by t0 will become hidden prototype of object 'obj'.
4719   v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
4720   t0->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "b"),
4721                               v8::Number::New(isolate, 2));
4722   t0->SetHiddenPrototype(true);
4723   v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
4724   t1->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "c"),
4725                               v8::Number::New(isolate, 3));
4726
4727   // Create proto objects, add hidden properties to them and set them on
4728   // the global object.
4729   v8::Handle<v8::Object> protoObj = t0->GetFunction()->NewInstance();
4730   protoObj->SetHiddenValue(
4731       v8::String::NewFromUtf8(isolate, "v8::test-debug::b"),
4732       v8::Int32::New(isolate, 12));
4733   env->Global()->Set(v8::String::NewFromUtf8(isolate, "protoObj"),
4734                      protoObj);
4735   v8::Handle<v8::Object> grandProtoObj = t1->GetFunction()->NewInstance();
4736   grandProtoObj->SetHiddenValue(
4737       v8::String::NewFromUtf8(isolate, "v8::test-debug::c"),
4738       v8::Int32::New(isolate, 13));
4739   env->Global()->Set(
4740       v8::String::NewFromUtf8(isolate, "grandProtoObj"),
4741       grandProtoObj);
4742
4743   // Setting prototypes: obj->protoObj->grandProtoObj
4744   protoObj->Set(v8::String::NewFromUtf8(isolate, "__proto__"),
4745                 grandProtoObj);
4746   obj->Set(v8::String::NewFromUtf8(isolate, "__proto__"), protoObj);
4747
4748   // Get mirror for the object with property getter.
4749   CompileRun("var obj_mirror = debug.MakeMirror(obj);");
4750   CHECK(CompileRun(
4751       "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
4752   CompileRun("var named_names = obj_mirror.propertyNames();");
4753   // There should be exactly two properties - one from the object itself and
4754   // another from its hidden prototype.
4755   CHECK_EQ(2, CompileRun("named_names.length")->Int32Value());
4756   CHECK(CompileRun("named_names.sort(); named_names[0] == 'a' &&"
4757                    "named_names[1] == 'b'")->BooleanValue());
4758   CHECK(CompileRun(
4759       "obj_mirror.property('a').value().value() == 1")->BooleanValue());
4760   CHECK(CompileRun(
4761       "obj_mirror.property('b').value().value() == 2")->BooleanValue());
4762 }
4763
4764
4765 // Multithreaded tests of JSON debugger protocol
4766
4767 // Support classes
4768
4769 // Provides synchronization between N threads, where N is a template parameter.
4770 // The Wait() call blocks a thread until it is called for the Nth time, then all
4771 // calls return.  Each ThreadBarrier object can only be used once.
4772 template <int N>
4773 class ThreadBarrier FINAL {
4774  public:
4775   ThreadBarrier() : num_blocked_(0) {}
4776
4777   ~ThreadBarrier() {
4778     LockGuard<Mutex> lock_guard(&mutex_);
4779     if (num_blocked_ != 0) {
4780       CHECK_EQ(N, num_blocked_);
4781     }
4782   }
4783
4784   void Wait() {
4785     LockGuard<Mutex> lock_guard(&mutex_);
4786     CHECK_LT(num_blocked_, N);
4787     num_blocked_++;
4788     if (N == num_blocked_) {
4789       // Signal and unblock all waiting threads.
4790       cv_.NotifyAll();
4791       printf("BARRIER\n\n");
4792       fflush(stdout);
4793     } else {  // Wait for the semaphore.
4794       while (num_blocked_ < N) {
4795         cv_.Wait(&mutex_);
4796       }
4797     }
4798     CHECK_EQ(N, num_blocked_);
4799   }
4800
4801  private:
4802   ConditionVariable cv_;
4803   Mutex mutex_;
4804   int num_blocked_;
4805
4806   STATIC_ASSERT(N > 0);
4807
4808   DISALLOW_COPY_AND_ASSIGN(ThreadBarrier);
4809 };
4810
4811
4812 // A set containing enough barriers and semaphores for any of the tests.
4813 class Barriers {
4814  public:
4815   Barriers() : semaphore_1(0), semaphore_2(0) {}
4816   ThreadBarrier<2> barrier_1;
4817   ThreadBarrier<2> barrier_2;
4818   ThreadBarrier<2> barrier_3;
4819   ThreadBarrier<2> barrier_4;
4820   ThreadBarrier<2> barrier_5;
4821   v8::base::Semaphore semaphore_1;
4822   v8::base::Semaphore semaphore_2;
4823 };
4824
4825
4826 // We match parts of the message to decide if it is a break message.
4827 bool IsBreakEventMessage(char *message) {
4828   const char* type_event = "\"type\":\"event\"";
4829   const char* event_break = "\"event\":\"break\"";
4830   // Does the message contain both type:event and event:break?
4831   return strstr(message, type_event) != NULL &&
4832          strstr(message, event_break) != NULL;
4833 }
4834
4835
4836 // We match parts of the message to decide if it is a exception message.
4837 bool IsExceptionEventMessage(char *message) {
4838   const char* type_event = "\"type\":\"event\"";
4839   const char* event_exception = "\"event\":\"exception\"";
4840   // Does the message contain both type:event and event:exception?
4841   return strstr(message, type_event) != NULL &&
4842       strstr(message, event_exception) != NULL;
4843 }
4844
4845
4846 // We match the message wether it is an evaluate response message.
4847 bool IsEvaluateResponseMessage(char* message) {
4848   const char* type_response = "\"type\":\"response\"";
4849   const char* command_evaluate = "\"command\":\"evaluate\"";
4850   // Does the message contain both type:response and command:evaluate?
4851   return strstr(message, type_response) != NULL &&
4852          strstr(message, command_evaluate) != NULL;
4853 }
4854
4855
4856 static int StringToInt(const char* s) {
4857   return atoi(s);  // NOLINT
4858 }
4859
4860
4861 // We match parts of the message to get evaluate result int value.
4862 int GetEvaluateIntResult(char *message) {
4863   const char* value = "\"value\":";
4864   char* pos = strstr(message, value);
4865   if (pos == NULL) {
4866     return -1;
4867   }
4868   int res = -1;
4869   res = StringToInt(pos + strlen(value));
4870   return res;
4871 }
4872
4873
4874 // We match parts of the message to get hit breakpoint id.
4875 int GetBreakpointIdFromBreakEventMessage(char *message) {
4876   const char* breakpoints = "\"breakpoints\":[";
4877   char* pos = strstr(message, breakpoints);
4878   if (pos == NULL) {
4879     return -1;
4880   }
4881   int res = -1;
4882   res = StringToInt(pos + strlen(breakpoints));
4883   return res;
4884 }
4885
4886
4887 // We match parts of the message to get total frames number.
4888 int GetTotalFramesInt(char *message) {
4889   const char* prefix = "\"totalFrames\":";
4890   char* pos = strstr(message, prefix);
4891   if (pos == NULL) {
4892     return -1;
4893   }
4894   pos += strlen(prefix);
4895   int res = StringToInt(pos);
4896   return res;
4897 }
4898
4899
4900 // We match parts of the message to get source line.
4901 int GetSourceLineFromBreakEventMessage(char *message) {
4902   const char* source_line = "\"sourceLine\":";
4903   char* pos = strstr(message, source_line);
4904   if (pos == NULL) {
4905     return -1;
4906   }
4907   int res = -1;
4908   res = StringToInt(pos + strlen(source_line));
4909   return res;
4910 }
4911
4912
4913 /* Test MessageQueues */
4914 /* Tests the message queues that hold debugger commands and
4915  * response messages to the debugger.  Fills queues and makes
4916  * them grow.
4917  */
4918 Barriers message_queue_barriers;
4919
4920 // This is the debugger thread, that executes no v8 calls except
4921 // placing JSON debugger commands in the queue.
4922 class MessageQueueDebuggerThread : public v8::base::Thread {
4923  public:
4924   MessageQueueDebuggerThread()
4925       : Thread(Options("MessageQueueDebuggerThread")) {}
4926   void Run();
4927 };
4928
4929
4930 static void MessageHandler(const v8::Debug::Message& message) {
4931   v8::Handle<v8::String> json = message.GetJSON();
4932   v8::String::Utf8Value utf8(json);
4933   if (IsBreakEventMessage(*utf8)) {
4934     // Lets test script wait until break occurs to send commands.
4935     // Signals when a break is reported.
4936     message_queue_barriers.semaphore_2.Signal();
4937   }
4938
4939   // Allow message handler to block on a semaphore, to test queueing of
4940   // messages while blocked.
4941   message_queue_barriers.semaphore_1.Wait();
4942 }
4943
4944
4945 void MessageQueueDebuggerThread::Run() {
4946   const int kBufferSize = 1000;
4947   uint16_t buffer_1[kBufferSize];
4948   uint16_t buffer_2[kBufferSize];
4949   const char* command_1 =
4950       "{\"seq\":117,"
4951        "\"type\":\"request\","
4952        "\"command\":\"evaluate\","
4953        "\"arguments\":{\"expression\":\"1+2\"}}";
4954   const char* command_2 =
4955     "{\"seq\":118,"
4956      "\"type\":\"request\","
4957      "\"command\":\"evaluate\","
4958      "\"arguments\":{\"expression\":\"1+a\"}}";
4959   const char* command_3 =
4960     "{\"seq\":119,"
4961      "\"type\":\"request\","
4962      "\"command\":\"evaluate\","
4963      "\"arguments\":{\"expression\":\"c.d * b\"}}";
4964   const char* command_continue =
4965     "{\"seq\":106,"
4966      "\"type\":\"request\","
4967      "\"command\":\"continue\"}";
4968   const char* command_single_step =
4969     "{\"seq\":107,"
4970      "\"type\":\"request\","
4971      "\"command\":\"continue\","
4972      "\"arguments\":{\"stepaction\":\"next\"}}";
4973
4974   /* Interleaved sequence of actions by the two threads:*/
4975   // Main thread compiles and runs source_1
4976   message_queue_barriers.semaphore_1.Signal();
4977   message_queue_barriers.barrier_1.Wait();
4978   // Post 6 commands, filling the command queue and making it expand.
4979   // These calls return immediately, but the commands stay on the queue
4980   // until the execution of source_2.
4981   // Note: AsciiToUtf16 executes before SendCommand, so command is copied
4982   // to buffer before buffer is sent to SendCommand.
4983   v8::Isolate* isolate = CcTest::isolate();
4984   v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
4985   v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
4986   v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4987   v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4988   v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4989   message_queue_barriers.barrier_2.Wait();
4990   // Main thread compiles and runs source_2.
4991   // Queued commands are executed at the start of compilation of source_2(
4992   // beforeCompile event).
4993   // Free the message handler to process all the messages from the queue. 7
4994   // messages are expected: 2 afterCompile events and 5 responses.
4995   // All the commands added so far will fail to execute as long as call stack
4996   // is empty on beforeCompile event.
4997   for (int i = 0; i < 6 ; ++i) {
4998     message_queue_barriers.semaphore_1.Signal();
4999   }
5000   message_queue_barriers.barrier_3.Wait();
5001   // Main thread compiles and runs source_3.
5002   // Don't stop in the afterCompile handler.
5003   message_queue_barriers.semaphore_1.Signal();
5004   // source_3 includes a debugger statement, which causes a break event.
5005   // Wait on break event from hitting "debugger" statement
5006   message_queue_barriers.semaphore_2.Wait();
5007   // These should execute after the "debugger" statement in source_2
5008   v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
5009   v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
5010   v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
5011   v8::Debug::SendCommand(
5012       isolate, buffer_2, AsciiToUtf16(command_single_step, buffer_2));
5013   // Run after 2 break events, 4 responses.
5014   for (int i = 0; i < 6 ; ++i) {
5015     message_queue_barriers.semaphore_1.Signal();
5016   }
5017   // Wait on break event after a single step executes.
5018   message_queue_barriers.semaphore_2.Wait();
5019   v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_2, buffer_1));
5020   v8::Debug::SendCommand(
5021       isolate, buffer_2, AsciiToUtf16(command_continue, buffer_2));
5022   // Run after 2 responses.
5023   for (int i = 0; i < 2 ; ++i) {
5024     message_queue_barriers.semaphore_1.Signal();
5025   }
5026   // Main thread continues running source_3 to end, waits for this thread.
5027 }
5028
5029
5030 // This thread runs the v8 engine.
5031 TEST(MessageQueues) {
5032   MessageQueueDebuggerThread message_queue_debugger_thread;
5033
5034   // Create a V8 environment
5035   DebugLocalContext env;
5036   v8::HandleScope scope(env->GetIsolate());
5037   v8::Debug::SetMessageHandler(MessageHandler);
5038   message_queue_debugger_thread.Start();
5039
5040   const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5041   const char* source_2 = "e = 17;";
5042   const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
5043
5044   // See MessageQueueDebuggerThread::Run for interleaved sequence of
5045   // API calls and events in the two threads.
5046   CompileRun(source_1);
5047   message_queue_barriers.barrier_1.Wait();
5048   message_queue_barriers.barrier_2.Wait();
5049   CompileRun(source_2);
5050   message_queue_barriers.barrier_3.Wait();
5051   CompileRun(source_3);
5052   message_queue_debugger_thread.Join();
5053   fflush(stdout);
5054 }
5055
5056
5057 class TestClientData : public v8::Debug::ClientData {
5058  public:
5059   TestClientData() {
5060     constructor_call_counter++;
5061   }
5062   virtual ~TestClientData() {
5063     destructor_call_counter++;
5064   }
5065
5066   static void ResetCounters() {
5067     constructor_call_counter = 0;
5068     destructor_call_counter = 0;
5069   }
5070
5071   static int constructor_call_counter;
5072   static int destructor_call_counter;
5073 };
5074
5075 int TestClientData::constructor_call_counter = 0;
5076 int TestClientData::destructor_call_counter = 0;
5077
5078
5079 // Tests that MessageQueue doesn't destroy client data when expands and
5080 // does destroy when it dies.
5081 TEST(MessageQueueExpandAndDestroy) {
5082   TestClientData::ResetCounters();
5083   { // Create a scope for the queue.
5084     CommandMessageQueue queue(1);
5085     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5086                                   new TestClientData()));
5087     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5088                                   new TestClientData()));
5089     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5090                                   new TestClientData()));
5091     CHECK_EQ(0, TestClientData::destructor_call_counter);
5092     queue.Get().Dispose();
5093     CHECK_EQ(1, TestClientData::destructor_call_counter);
5094     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5095                                   new TestClientData()));
5096     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5097                                   new TestClientData()));
5098     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5099                                   new TestClientData()));
5100     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5101                                   new TestClientData()));
5102     queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5103                                   new TestClientData()));
5104     CHECK_EQ(1, TestClientData::destructor_call_counter);
5105     queue.Get().Dispose();
5106     CHECK_EQ(2, TestClientData::destructor_call_counter);
5107   }
5108   // All the client data should be destroyed when the queue is destroyed.
5109   CHECK_EQ(TestClientData::destructor_call_counter,
5110            TestClientData::destructor_call_counter);
5111 }
5112
5113
5114 static int handled_client_data_instances_count = 0;
5115 static void MessageHandlerCountingClientData(
5116     const v8::Debug::Message& message) {
5117   if (message.GetClientData() != NULL) {
5118     handled_client_data_instances_count++;
5119   }
5120 }
5121
5122
5123 // Tests that all client data passed to the debugger are sent to the handler.
5124 TEST(SendClientDataToHandler) {
5125   // Create a V8 environment
5126   DebugLocalContext env;
5127   v8::Isolate* isolate = env->GetIsolate();
5128   v8::HandleScope scope(isolate);
5129   TestClientData::ResetCounters();
5130   handled_client_data_instances_count = 0;
5131   v8::Debug::SetMessageHandler(MessageHandlerCountingClientData);
5132   const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5133   const int kBufferSize = 1000;
5134   uint16_t buffer[kBufferSize];
5135   const char* command_1 =
5136       "{\"seq\":117,"
5137        "\"type\":\"request\","
5138        "\"command\":\"evaluate\","
5139        "\"arguments\":{\"expression\":\"1+2\"}}";
5140   const char* command_2 =
5141     "{\"seq\":118,"
5142      "\"type\":\"request\","
5143      "\"command\":\"evaluate\","
5144      "\"arguments\":{\"expression\":\"1+a\"}}";
5145   const char* command_continue =
5146     "{\"seq\":106,"
5147      "\"type\":\"request\","
5148      "\"command\":\"continue\"}";
5149
5150   v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer),
5151                          new TestClientData());
5152   v8::Debug::SendCommand(
5153       isolate, buffer, AsciiToUtf16(command_2, buffer), NULL);
5154   v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5155                          new TestClientData());
5156   v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5157                          new TestClientData());
5158   // All the messages will be processed on beforeCompile event.
5159   CompileRun(source_1);
5160   v8::Debug::SendCommand(
5161       isolate, buffer, AsciiToUtf16(command_continue, buffer));
5162   CHECK_EQ(3, TestClientData::constructor_call_counter);
5163   CHECK_EQ(TestClientData::constructor_call_counter,
5164            handled_client_data_instances_count);
5165   CHECK_EQ(TestClientData::constructor_call_counter,
5166            TestClientData::destructor_call_counter);
5167 }
5168
5169
5170 /* Test ThreadedDebugging */
5171 /* This test interrupts a running infinite loop that is
5172  * occupying the v8 thread by a break command from the
5173  * debugger thread.  It then changes the value of a
5174  * global object, to make the loop terminate.
5175  */
5176
5177 Barriers threaded_debugging_barriers;
5178
5179 class V8Thread : public v8::base::Thread {
5180  public:
5181   V8Thread() : Thread(Options("V8Thread")) {}
5182   void Run();
5183   v8::Isolate* isolate() { return isolate_; }
5184
5185  private:
5186   v8::Isolate* isolate_;
5187 };
5188
5189 class DebuggerThread : public v8::base::Thread {
5190  public:
5191   explicit DebuggerThread(v8::Isolate* isolate)
5192       : Thread(Options("DebuggerThread")), isolate_(isolate) {}
5193   void Run();
5194
5195  private:
5196   v8::Isolate* isolate_;
5197 };
5198
5199
5200 static void ThreadedAtBarrier1(
5201     const v8::FunctionCallbackInfo<v8::Value>& args) {
5202   threaded_debugging_barriers.barrier_1.Wait();
5203 }
5204
5205
5206 static void ThreadedMessageHandler(const v8::Debug::Message& message) {
5207   static char print_buffer[1000];
5208   v8::String::Value json(message.GetJSON());
5209   Utf16ToAscii(*json, json.length(), print_buffer);
5210   if (IsBreakEventMessage(print_buffer)) {
5211     // Check that we are inside the while loop.
5212     int source_line = GetSourceLineFromBreakEventMessage(print_buffer);
5213     CHECK(8 <= source_line && source_line <= 13);
5214     threaded_debugging_barriers.barrier_2.Wait();
5215   }
5216 }
5217
5218
5219 void V8Thread::Run() {
5220   const char* source =
5221       "flag = true;\n"
5222       "function bar( new_value ) {\n"
5223       "  flag = new_value;\n"
5224       "  return \"Return from bar(\" + new_value + \")\";\n"
5225       "}\n"
5226       "\n"
5227       "function foo() {\n"
5228       "  var x = 1;\n"
5229       "  while ( flag == true ) {\n"
5230       "    if ( x == 1 ) {\n"
5231       "      ThreadedAtBarrier1();\n"
5232       "    }\n"
5233       "    x = x + 1;\n"
5234       "  }\n"
5235       "}\n"
5236       "\n"
5237       "foo();\n";
5238
5239   isolate_ = v8::Isolate::New();
5240   threaded_debugging_barriers.barrier_3.Wait();
5241   {
5242     v8::Isolate::Scope isolate_scope(isolate_);
5243     DebugLocalContext env(isolate_);
5244     v8::HandleScope scope(isolate_);
5245     v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
5246     v8::Handle<v8::ObjectTemplate> global_template =
5247         v8::ObjectTemplate::New(env->GetIsolate());
5248     global_template->Set(
5249         v8::String::NewFromUtf8(env->GetIsolate(), "ThreadedAtBarrier1"),
5250         v8::FunctionTemplate::New(isolate_, ThreadedAtBarrier1));
5251     v8::Handle<v8::Context> context =
5252         v8::Context::New(isolate_, NULL, global_template);
5253     v8::Context::Scope context_scope(context);
5254
5255     CompileRun(source);
5256   }
5257   threaded_debugging_barriers.barrier_4.Wait();
5258   isolate_->Dispose();
5259 }
5260
5261
5262 void DebuggerThread::Run() {
5263   const int kBufSize = 1000;
5264   uint16_t buffer[kBufSize];
5265
5266   const char* command_1 = "{\"seq\":102,"
5267       "\"type\":\"request\","
5268       "\"command\":\"evaluate\","
5269       "\"arguments\":{\"expression\":\"bar(false)\"}}";
5270   const char* command_2 = "{\"seq\":103,"
5271       "\"type\":\"request\","
5272       "\"command\":\"continue\"}";
5273
5274   threaded_debugging_barriers.barrier_1.Wait();
5275   v8::Debug::DebugBreak(isolate_);
5276   threaded_debugging_barriers.barrier_2.Wait();
5277   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
5278   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
5279   threaded_debugging_barriers.barrier_4.Wait();
5280 }
5281
5282
5283 TEST(ThreadedDebugging) {
5284   V8Thread v8_thread;
5285
5286   // Create a V8 environment
5287   v8_thread.Start();
5288   threaded_debugging_barriers.barrier_3.Wait();
5289   DebuggerThread debugger_thread(v8_thread.isolate());
5290   debugger_thread.Start();
5291
5292   v8_thread.Join();
5293   debugger_thread.Join();
5294 }
5295
5296
5297 /* Test RecursiveBreakpoints */
5298 /* In this test, the debugger evaluates a function with a breakpoint, after
5299  * hitting a breakpoint in another function.  We do this with both values
5300  * of the flag enabling recursive breakpoints, and verify that the second
5301  * breakpoint is hit when enabled, and missed when disabled.
5302  */
5303
5304 class BreakpointsV8Thread : public v8::base::Thread {
5305  public:
5306   BreakpointsV8Thread() : Thread(Options("BreakpointsV8Thread")) {}
5307   void Run();
5308
5309   v8::Isolate* isolate() { return isolate_; }
5310
5311  private:
5312   v8::Isolate* isolate_;
5313 };
5314
5315 class BreakpointsDebuggerThread : public v8::base::Thread {
5316  public:
5317   BreakpointsDebuggerThread(bool global_evaluate, v8::Isolate* isolate)
5318       : Thread(Options("BreakpointsDebuggerThread")),
5319         global_evaluate_(global_evaluate),
5320         isolate_(isolate) {}
5321   void Run();
5322
5323  private:
5324   bool global_evaluate_;
5325   v8::Isolate* isolate_;
5326 };
5327
5328
5329 Barriers* breakpoints_barriers;
5330 int break_event_breakpoint_id;
5331 int evaluate_int_result;
5332
5333 static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
5334   static char print_buffer[1000];
5335   v8::String::Value json(message.GetJSON());
5336   Utf16ToAscii(*json, json.length(), print_buffer);
5337
5338   if (IsBreakEventMessage(print_buffer)) {
5339     break_event_breakpoint_id =
5340         GetBreakpointIdFromBreakEventMessage(print_buffer);
5341     breakpoints_barriers->semaphore_1.Signal();
5342   } else if (IsEvaluateResponseMessage(print_buffer)) {
5343     evaluate_int_result = GetEvaluateIntResult(print_buffer);
5344     breakpoints_barriers->semaphore_1.Signal();
5345   }
5346 }
5347
5348
5349 void BreakpointsV8Thread::Run() {
5350   const char* source_1 = "var y_global = 3;\n"
5351     "function cat( new_value ) {\n"
5352     "  var x = new_value;\n"
5353     "  y_global = y_global + 4;\n"
5354     "  x = 3 * x + 1;\n"
5355     "  y_global = y_global + 5;\n"
5356     "  return x;\n"
5357     "}\n"
5358     "\n"
5359     "function dog() {\n"
5360     "  var x = 1;\n"
5361     "  x = y_global;"
5362     "  var z = 3;"
5363     "  x += 100;\n"
5364     "  return x;\n"
5365     "}\n"
5366     "\n";
5367   const char* source_2 = "cat(17);\n"
5368     "cat(19);\n";
5369
5370   isolate_ = v8::Isolate::New();
5371   breakpoints_barriers->barrier_3.Wait();
5372   {
5373     v8::Isolate::Scope isolate_scope(isolate_);
5374     DebugLocalContext env(isolate_);
5375     v8::HandleScope scope(isolate_);
5376     v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
5377
5378     CompileRun(source_1);
5379     breakpoints_barriers->barrier_1.Wait();
5380     breakpoints_barriers->barrier_2.Wait();
5381     CompileRun(source_2);
5382   }
5383   breakpoints_barriers->barrier_4.Wait();
5384   isolate_->Dispose();
5385 }
5386
5387
5388 void BreakpointsDebuggerThread::Run() {
5389   const int kBufSize = 1000;
5390   uint16_t buffer[kBufSize];
5391
5392   const char* command_1 = "{\"seq\":101,"
5393       "\"type\":\"request\","
5394       "\"command\":\"setbreakpoint\","
5395       "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
5396   const char* command_2 = "{\"seq\":102,"
5397       "\"type\":\"request\","
5398       "\"command\":\"setbreakpoint\","
5399       "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
5400   const char* command_3;
5401   if (this->global_evaluate_) {
5402     command_3 = "{\"seq\":103,"
5403         "\"type\":\"request\","
5404         "\"command\":\"evaluate\","
5405         "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false,"
5406         "\"global\":true}}";
5407   } else {
5408     command_3 = "{\"seq\":103,"
5409         "\"type\":\"request\","
5410         "\"command\":\"evaluate\","
5411         "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
5412   }
5413   const char* command_4;
5414   if (this->global_evaluate_) {
5415     command_4 = "{\"seq\":104,"
5416         "\"type\":\"request\","
5417         "\"command\":\"evaluate\","
5418         "\"arguments\":{\"expression\":\"100 + 8\",\"disable_break\":true,"
5419         "\"global\":true}}";
5420   } else {
5421     command_4 = "{\"seq\":104,"
5422         "\"type\":\"request\","
5423         "\"command\":\"evaluate\","
5424         "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}";
5425   }
5426   const char* command_5 = "{\"seq\":105,"
5427       "\"type\":\"request\","
5428       "\"command\":\"continue\"}";
5429   const char* command_6 = "{\"seq\":106,"
5430       "\"type\":\"request\","
5431       "\"command\":\"continue\"}";
5432   const char* command_7;
5433   if (this->global_evaluate_) {
5434     command_7 = "{\"seq\":107,"
5435         "\"type\":\"request\","
5436         "\"command\":\"evaluate\","
5437         "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true,"
5438         "\"global\":true}}";
5439   } else {
5440     command_7 = "{\"seq\":107,"
5441         "\"type\":\"request\","
5442         "\"command\":\"evaluate\","
5443         "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
5444   }
5445   const char* command_8 = "{\"seq\":108,"
5446       "\"type\":\"request\","
5447       "\"command\":\"continue\"}";
5448
5449
5450   // v8 thread initializes, runs source_1
5451   breakpoints_barriers->barrier_1.Wait();
5452   // 1:Set breakpoint in cat() (will get id 1).
5453   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer));
5454   // 2:Set breakpoint in dog() (will get id 2).
5455   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer));
5456   breakpoints_barriers->barrier_2.Wait();
5457   // V8 thread starts compiling source_2.
5458   // Automatic break happens, to run queued commands
5459   // breakpoints_barriers->semaphore_1.Wait();
5460   // Commands 1 through 3 run, thread continues.
5461   // v8 thread runs source_2 to breakpoint in cat().
5462   // message callback receives break event.
5463   breakpoints_barriers->semaphore_1.Wait();
5464   // Must have hit breakpoint #1.
5465   CHECK_EQ(1, break_event_breakpoint_id);
5466   // 4:Evaluate dog() (which has a breakpoint).
5467   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_3, buffer));
5468   // V8 thread hits breakpoint in dog().
5469   breakpoints_barriers->semaphore_1.Wait();  // wait for break event
5470   // Must have hit breakpoint #2.
5471   CHECK_EQ(2, break_event_breakpoint_id);
5472   // 5:Evaluate (x + 1).
5473   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_4, buffer));
5474   // Evaluate (x + 1) finishes.
5475   breakpoints_barriers->semaphore_1.Wait();
5476   // Must have result 108.
5477   CHECK_EQ(108, evaluate_int_result);
5478   // 6:Continue evaluation of dog().
5479   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_5, buffer));
5480   // Evaluate dog() finishes.
5481   breakpoints_barriers->semaphore_1.Wait();
5482   // Must have result 107.
5483   CHECK_EQ(107, evaluate_int_result);
5484   // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
5485   // in cat(19).
5486   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_6, buffer));
5487   // Message callback gets break event.
5488   breakpoints_barriers->semaphore_1.Wait();  // wait for break event
5489   // Must have hit breakpoint #1.
5490   CHECK_EQ(1, break_event_breakpoint_id);
5491   // 8: Evaluate dog() with breaks disabled.
5492   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_7, buffer));
5493   // Evaluate dog() finishes.
5494   breakpoints_barriers->semaphore_1.Wait();
5495   // Must have result 116.
5496   CHECK_EQ(116, evaluate_int_result);
5497   // 9: Continue evaluation of source2, reach end.
5498   v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_8, buffer));
5499   breakpoints_barriers->barrier_4.Wait();
5500 }
5501
5502
5503 void TestRecursiveBreakpointsGeneric(bool global_evaluate) {
5504   BreakpointsV8Thread breakpoints_v8_thread;
5505
5506   // Create a V8 environment
5507   Barriers stack_allocated_breakpoints_barriers;
5508   breakpoints_barriers = &stack_allocated_breakpoints_barriers;
5509
5510   breakpoints_v8_thread.Start();
5511   breakpoints_barriers->barrier_3.Wait();
5512   BreakpointsDebuggerThread breakpoints_debugger_thread(
5513       global_evaluate, breakpoints_v8_thread.isolate());
5514   breakpoints_debugger_thread.Start();
5515
5516   breakpoints_v8_thread.Join();
5517   breakpoints_debugger_thread.Join();
5518 }
5519
5520
5521 TEST(RecursiveBreakpoints) {
5522   TestRecursiveBreakpointsGeneric(false);
5523 }
5524
5525
5526 TEST(RecursiveBreakpointsGlobal) {
5527   TestRecursiveBreakpointsGeneric(true);
5528 }
5529
5530
5531 static void DummyDebugEventListener(
5532     const v8::Debug::EventDetails& event_details) {
5533 }
5534
5535
5536 TEST(SetDebugEventListenerOnUninitializedVM) {
5537   v8::Debug::SetDebugEventListener(DummyDebugEventListener);
5538 }
5539
5540
5541 static void DummyMessageHandler(const v8::Debug::Message& message) {
5542 }
5543
5544
5545 TEST(SetMessageHandlerOnUninitializedVM) {
5546   v8::Debug::SetMessageHandler(DummyMessageHandler);
5547 }
5548
5549
5550 // Source for a JavaScript function which returns the data parameter of a
5551 // function called in the context of the debugger. If no data parameter is
5552 // passed it throws an exception.
5553 static const char* debugger_call_with_data_source =
5554     "function debugger_call_with_data(exec_state, data) {"
5555     "  if (data) return data;"
5556     "  throw 'No data!'"
5557     "}";
5558 v8::Handle<v8::Function> debugger_call_with_data;
5559
5560
5561 // Source for a JavaScript function which returns the data parameter of a
5562 // function called in the context of the debugger. If no data parameter is
5563 // passed it throws an exception.
5564 static const char* debugger_call_with_closure_source =
5565     "var x = 3;"
5566     "(function (exec_state) {"
5567     "  if (exec_state.y) return x - 1;"
5568     "  exec_state.y = x;"
5569     "  return exec_state.y"
5570     "})";
5571 v8::Handle<v8::Function> debugger_call_with_closure;
5572
5573 // Function to retrieve the number of JavaScript frames by calling a JavaScript
5574 // in the debugger.
5575 static void CheckFrameCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
5576   CHECK(v8::Debug::Call(frame_count)->IsNumber());
5577   CHECK_EQ(args[0]->Int32Value(),
5578            v8::Debug::Call(frame_count)->Int32Value());
5579 }
5580
5581
5582 // Function to retrieve the source line of the top JavaScript frame by calling a
5583 // JavaScript function in the debugger.
5584 static void CheckSourceLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
5585   CHECK(v8::Debug::Call(frame_source_line)->IsNumber());
5586   CHECK_EQ(args[0]->Int32Value(),
5587            v8::Debug::Call(frame_source_line)->Int32Value());
5588 }
5589
5590
5591 // Function to test passing an additional parameter to a JavaScript function
5592 // called in the debugger. It also tests that functions called in the debugger
5593 // can throw exceptions.
5594 static void CheckDataParameter(
5595     const v8::FunctionCallbackInfo<v8::Value>& args) {
5596   v8::Handle<v8::String> data =
5597       v8::String::NewFromUtf8(args.GetIsolate(), "Test");
5598   CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString());
5599
5600   for (int i = 0; i < 3; i++) {
5601     v8::TryCatch catcher;
5602     CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
5603     CHECK(catcher.HasCaught());
5604     CHECK(catcher.Exception()->IsString());
5605   }
5606 }
5607
5608
5609 // Function to test using a JavaScript with closure in the debugger.
5610 static void CheckClosure(const v8::FunctionCallbackInfo<v8::Value>& args) {
5611   CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber());
5612   CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value());
5613 }
5614
5615
5616 // Test functions called through the debugger.
5617 TEST(CallFunctionInDebugger) {
5618   // Create and enter a context with the functions CheckFrameCount,
5619   // CheckSourceLine and CheckDataParameter installed.
5620   v8::Isolate* isolate = CcTest::isolate();
5621   v8::HandleScope scope(isolate);
5622   v8::Handle<v8::ObjectTemplate> global_template =
5623       v8::ObjectTemplate::New(isolate);
5624   global_template->Set(
5625       v8::String::NewFromUtf8(isolate, "CheckFrameCount"),
5626       v8::FunctionTemplate::New(isolate, CheckFrameCount));
5627   global_template->Set(
5628       v8::String::NewFromUtf8(isolate, "CheckSourceLine"),
5629       v8::FunctionTemplate::New(isolate, CheckSourceLine));
5630   global_template->Set(
5631       v8::String::NewFromUtf8(isolate, "CheckDataParameter"),
5632       v8::FunctionTemplate::New(isolate, CheckDataParameter));
5633   global_template->Set(
5634       v8::String::NewFromUtf8(isolate, "CheckClosure"),
5635       v8::FunctionTemplate::New(isolate, CheckClosure));
5636   v8::Handle<v8::Context> context = v8::Context::New(isolate,
5637                                                      NULL,
5638                                                      global_template);
5639   v8::Context::Scope context_scope(context);
5640
5641   // Compile a function for checking the number of JavaScript frames.
5642   v8::Script::Compile(
5643       v8::String::NewFromUtf8(isolate, frame_count_source))->Run();
5644   frame_count = v8::Local<v8::Function>::Cast(context->Global()->Get(
5645       v8::String::NewFromUtf8(isolate, "frame_count")));
5646
5647   // Compile a function for returning the source line for the top frame.
5648   v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5649                                               frame_source_line_source))->Run();
5650   frame_source_line = v8::Local<v8::Function>::Cast(context->Global()->Get(
5651       v8::String::NewFromUtf8(isolate, "frame_source_line")));
5652
5653   // Compile a function returning the data parameter.
5654   v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5655                                               debugger_call_with_data_source))
5656       ->Run();
5657   debugger_call_with_data = v8::Local<v8::Function>::Cast(
5658       context->Global()->Get(v8::String::NewFromUtf8(
5659           isolate, "debugger_call_with_data")));
5660
5661   // Compile a function capturing closure.
5662   debugger_call_with_closure =
5663       v8::Local<v8::Function>::Cast(v8::Script::Compile(
5664           v8::String::NewFromUtf8(isolate,
5665                                   debugger_call_with_closure_source))->Run());
5666
5667   // Calling a function through the debugger returns 0 frames if there are
5668   // no JavaScript frames.
5669   CHECK(v8::Integer::New(isolate, 0)->Equals(v8::Debug::Call(frame_count)));
5670
5671   // Test that the number of frames can be retrieved.
5672   v8::Script::Compile(
5673       v8::String::NewFromUtf8(isolate, "CheckFrameCount(1)"))->Run();
5674   v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5675                                               "function f() {"
5676                                               "  CheckFrameCount(2);"
5677                                               "}; f()"))->Run();
5678
5679   // Test that the source line can be retrieved.
5680   v8::Script::Compile(
5681       v8::String::NewFromUtf8(isolate, "CheckSourceLine(0)"))->Run();
5682   v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5683                                               "function f() {\n"
5684                                               "  CheckSourceLine(1)\n"
5685                                               "  CheckSourceLine(2)\n"
5686                                               "  CheckSourceLine(3)\n"
5687                                               "}; f()"))->Run();
5688
5689   // Test that a parameter can be passed to a function called in the debugger.
5690   v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5691                                               "CheckDataParameter()"))->Run();
5692
5693   // Test that a function with closure can be run in the debugger.
5694   v8::Script::Compile(
5695       v8::String::NewFromUtf8(isolate, "CheckClosure()"))->Run();
5696
5697   // Test that the source line is correct when there is a line offset.
5698   v8::ScriptOrigin origin(v8::String::NewFromUtf8(isolate, "test"),
5699                           v8::Integer::New(isolate, 7));
5700   v8::Script::Compile(
5701       v8::String::NewFromUtf8(isolate, "CheckSourceLine(7)"), &origin)
5702       ->Run();
5703   v8::Script::Compile(v8::String::NewFromUtf8(isolate,
5704                                               "function f() {\n"
5705                                               "  CheckSourceLine(8)\n"
5706                                               "  CheckSourceLine(9)\n"
5707                                               "  CheckSourceLine(10)\n"
5708                                               "}; f()"),
5709                       &origin)->Run();
5710 }
5711
5712
5713 // Debugger message handler which counts the number of breaks.
5714 static void SendContinueCommand();
5715 static void MessageHandlerBreakPointHitCount(
5716     const v8::Debug::Message& message) {
5717   if (message.IsEvent() && message.GetEvent() == v8::Break) {
5718     // Count the number of breaks.
5719     break_point_hit_count++;
5720
5721     SendContinueCommand();
5722   }
5723 }
5724
5725
5726 // Test that clearing the debug event listener actually clears all break points
5727 // and related information.
5728 TEST(DebuggerUnload) {
5729   DebugLocalContext env;
5730
5731   // Check debugger is unloaded before it is used.
5732   CheckDebuggerUnloaded();
5733
5734   // Set a debug event listener.
5735   break_point_hit_count = 0;
5736   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
5737   {
5738     v8::HandleScope scope(env->GetIsolate());
5739     // Create a couple of functions for the test.
5740     v8::Local<v8::Function> foo =
5741         CompileFunction(&env, "function foo(){x=1}", "foo");
5742     v8::Local<v8::Function> bar =
5743         CompileFunction(&env, "function bar(){y=2}", "bar");
5744
5745     // Set some break points.
5746     SetBreakPoint(foo, 0);
5747     SetBreakPoint(foo, 4);
5748     SetBreakPoint(bar, 0);
5749     SetBreakPoint(bar, 4);
5750
5751     // Make sure that the break points are there.
5752     break_point_hit_count = 0;
5753     foo->Call(env->Global(), 0, NULL);
5754     CHECK_EQ(2, break_point_hit_count);
5755     bar->Call(env->Global(), 0, NULL);
5756     CHECK_EQ(4, break_point_hit_count);
5757   }
5758
5759   // Remove the debug event listener without clearing breakpoints. Do this
5760   // outside a handle scope.
5761   v8::Debug::SetDebugEventListener(NULL);
5762   CheckDebuggerUnloaded(true);
5763
5764   // Now set a debug message handler.
5765   break_point_hit_count = 0;
5766   v8::Debug::SetMessageHandler(MessageHandlerBreakPointHitCount);
5767   {
5768     v8::HandleScope scope(env->GetIsolate());
5769
5770     // Get the test functions again.
5771     v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast(
5772         env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo"))));
5773
5774     foo->Call(env->Global(), 0, NULL);
5775     CHECK_EQ(0, break_point_hit_count);
5776
5777     // Set break points and run again.
5778     SetBreakPoint(foo, 0);
5779     SetBreakPoint(foo, 4);
5780     foo->Call(env->Global(), 0, NULL);
5781     CHECK_EQ(2, break_point_hit_count);
5782   }
5783
5784   // Remove the debug message handler without clearing breakpoints. Do this
5785   // outside a handle scope.
5786   v8::Debug::SetMessageHandler(NULL);
5787   CheckDebuggerUnloaded(true);
5788 }
5789
5790
5791 // Sends continue command to the debugger.
5792 static void SendContinueCommand() {
5793   const int kBufferSize = 1000;
5794   uint16_t buffer[kBufferSize];
5795   const char* command_continue =
5796     "{\"seq\":0,"
5797      "\"type\":\"request\","
5798      "\"command\":\"continue\"}";
5799
5800   v8::Debug::SendCommand(
5801       CcTest::isolate(), buffer, AsciiToUtf16(command_continue, buffer));
5802 }
5803
5804
5805 // Debugger message handler which counts the number of times it is called.
5806 static int message_handler_hit_count = 0;
5807 static void MessageHandlerHitCount(const v8::Debug::Message& message) {
5808   message_handler_hit_count++;
5809
5810   static char print_buffer[1000];
5811   v8::String::Value json(message.GetJSON());
5812   Utf16ToAscii(*json, json.length(), print_buffer);
5813   if (IsExceptionEventMessage(print_buffer)) {
5814     // Send a continue command for exception events.
5815     SendContinueCommand();
5816   }
5817 }
5818
5819
5820 // Test clearing the debug message handler.
5821 TEST(DebuggerClearMessageHandler) {
5822   DebugLocalContext env;
5823   v8::HandleScope scope(env->GetIsolate());
5824
5825   // Check debugger is unloaded before it is used.
5826   CheckDebuggerUnloaded();
5827
5828   // Set a debug message handler.
5829   v8::Debug::SetMessageHandler(MessageHandlerHitCount);
5830
5831   // Run code to throw a unhandled exception. This should end up in the message
5832   // handler.
5833   CompileRun("throw 1");
5834
5835   // The message handler should be called.
5836   CHECK_GT(message_handler_hit_count, 0);
5837
5838   // Clear debug message handler.
5839   message_handler_hit_count = 0;
5840   v8::Debug::SetMessageHandler(NULL);
5841
5842   // Run code to throw a unhandled exception. This should end up in the message
5843   // handler.
5844   CompileRun("throw 1");
5845
5846   // The message handler should not be called more.
5847   CHECK_EQ(0, message_handler_hit_count);
5848
5849   CheckDebuggerUnloaded(true);
5850 }
5851
5852
5853 // Debugger message handler which clears the message handler while active.
5854 static void MessageHandlerClearingMessageHandler(
5855     const v8::Debug::Message& message) {
5856   message_handler_hit_count++;
5857
5858   // Clear debug message handler.
5859   v8::Debug::SetMessageHandler(NULL);
5860 }
5861
5862
5863 // Test clearing the debug message handler while processing a debug event.
5864 TEST(DebuggerClearMessageHandlerWhileActive) {
5865   DebugLocalContext env;
5866   v8::HandleScope scope(env->GetIsolate());
5867
5868   // Check debugger is unloaded before it is used.
5869   CheckDebuggerUnloaded();
5870
5871   // Set a debug message handler.
5872   v8::Debug::SetMessageHandler(MessageHandlerClearingMessageHandler);
5873
5874   // Run code to throw a unhandled exception. This should end up in the message
5875   // handler.
5876   CompileRun("throw 1");
5877
5878   // The message handler should be called.
5879   CHECK_EQ(1, message_handler_hit_count);
5880
5881   CheckDebuggerUnloaded(true);
5882 }
5883
5884
5885 // Test for issue http://code.google.com/p/v8/issues/detail?id=289.
5886 // Make sure that DebugGetLoadedScripts doesn't return scripts
5887 // with disposed external source.
5888 class EmptyExternalStringResource : public v8::String::ExternalStringResource {
5889  public:
5890   EmptyExternalStringResource() { empty_[0] = 0; }
5891   virtual ~EmptyExternalStringResource() {}
5892   virtual size_t length() const { return empty_.length(); }
5893   virtual const uint16_t* data() const { return empty_.start(); }
5894  private:
5895   ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
5896 };
5897
5898
5899 TEST(DebugGetLoadedScripts) {
5900   DebugLocalContext env;
5901   v8::HandleScope scope(env->GetIsolate());
5902   env.ExposeDebug();
5903
5904   EmptyExternalStringResource source_ext_str;
5905   v8::Local<v8::String> source =
5906       v8::String::NewExternal(env->GetIsolate(), &source_ext_str);
5907   v8::Handle<v8::Script> evil_script(v8::Script::Compile(source));
5908   // "use" evil_script to make the compiler happy.
5909   (void) evil_script;
5910   Handle<i::ExternalTwoByteString> i_source(
5911       i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
5912   // This situation can happen if source was an external string disposed
5913   // by its owner.
5914   i_source->set_resource(0);
5915
5916   bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
5917   i::FLAG_allow_natives_syntax = true;
5918   CompileRun(
5919       "var scripts = %DebugGetLoadedScripts();"
5920       "var count = scripts.length;"
5921       "for (var i = 0; i < count; ++i) {"
5922       "  scripts[i].line_ends;"
5923       "}");
5924   // Must not crash while accessing line_ends.
5925   i::FLAG_allow_natives_syntax = allow_natives_syntax;
5926
5927   // Some scripts are retrieved - at least the number of native scripts.
5928   CHECK_GT((*env)
5929                ->Global()
5930                ->Get(v8::String::NewFromUtf8(env->GetIsolate(), "count"))
5931                ->Int32Value(),
5932            8);
5933 }
5934
5935
5936 // Test script break points set on lines.
5937 TEST(ScriptNameAndData) {
5938   DebugLocalContext env;
5939   v8::HandleScope scope(env->GetIsolate());
5940   env.ExposeDebug();
5941
5942   // Create functions for retrieving script name and data for the function on
5943   // the top frame when hitting a break point.
5944   frame_script_name = CompileFunction(&env,
5945                                       frame_script_name_source,
5946                                       "frame_script_name");
5947
5948   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
5949
5950   // Test function source.
5951   v8::Local<v8::String> script = v8::String::NewFromUtf8(env->GetIsolate(),
5952                                                          "function f() {\n"
5953                                                          "  debugger;\n"
5954                                                          "}\n");
5955
5956   v8::ScriptOrigin origin1 =
5957       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "name"));
5958   v8::Handle<v8::Script> script1 = v8::Script::Compile(script, &origin1);
5959   script1->Run();
5960   v8::Local<v8::Function> f;
5961   f = v8::Local<v8::Function>::Cast(
5962       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5963
5964   f->Call(env->Global(), 0, NULL);
5965   CHECK_EQ(1, break_point_hit_count);
5966   CHECK_EQ(0, strcmp("name", last_script_name_hit));
5967
5968   // Compile the same script again without setting data. As the compilation
5969   // cache is disabled when debugging expect the data to be missing.
5970   v8::Script::Compile(script, &origin1)->Run();
5971   f = v8::Local<v8::Function>::Cast(
5972       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5973   f->Call(env->Global(), 0, NULL);
5974   CHECK_EQ(2, break_point_hit_count);
5975   CHECK_EQ(0, strcmp("name", last_script_name_hit));
5976
5977   v8::Local<v8::String> data_obj_source = v8::String::NewFromUtf8(
5978       env->GetIsolate(),
5979       "({ a: 'abc',\n"
5980       "  b: 123,\n"
5981       "  toString: function() { return this.a + ' ' + this.b; }\n"
5982       "})\n");
5983   v8::Script::Compile(data_obj_source)->Run();
5984   v8::ScriptOrigin origin2 =
5985       v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "new name"));
5986   v8::Handle<v8::Script> script2 = v8::Script::Compile(script, &origin2);
5987   script2->Run();
5988   f = v8::Local<v8::Function>::Cast(
5989       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5990   f->Call(env->Global(), 0, NULL);
5991   CHECK_EQ(3, break_point_hit_count);
5992   CHECK_EQ(0, strcmp("new name", last_script_name_hit));
5993
5994   v8::Handle<v8::Script> script3 = v8::Script::Compile(script, &origin2);
5995   script3->Run();
5996   f = v8::Local<v8::Function>::Cast(
5997       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
5998   f->Call(env->Global(), 0, NULL);
5999   CHECK_EQ(4, break_point_hit_count);
6000 }
6001
6002
6003 static v8::Handle<v8::Context> expected_context;
6004 static v8::Handle<v8::Value> expected_context_data;
6005
6006
6007 // Check that the expected context is the one generating the debug event.
6008 static void ContextCheckMessageHandler(const v8::Debug::Message& message) {
6009   CHECK(message.GetEventContext() == expected_context);
6010   CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6011       expected_context_data));
6012   message_handler_hit_count++;
6013
6014   static char print_buffer[1000];
6015   v8::String::Value json(message.GetJSON());
6016   Utf16ToAscii(*json, json.length(), print_buffer);
6017
6018   // Send a continue command for break events.
6019   if (IsBreakEventMessage(print_buffer)) {
6020     SendContinueCommand();
6021   }
6022 }
6023
6024
6025 // Test which creates two contexts and sets different embedder data on each.
6026 // Checks that this data is set correctly and that when the debug message
6027 // handler is called the expected context is the one active.
6028 TEST(ContextData) {
6029   v8::Isolate* isolate = CcTest::isolate();
6030   v8::HandleScope scope(isolate);
6031
6032   // Create two contexts.
6033   v8::Handle<v8::Context> context_1;
6034   v8::Handle<v8::Context> context_2;
6035   v8::Handle<v8::ObjectTemplate> global_template =
6036       v8::Handle<v8::ObjectTemplate>();
6037   v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>();
6038   context_1 = v8::Context::New(isolate, NULL, global_template, global_object);
6039   context_2 = v8::Context::New(isolate, NULL, global_template, global_object);
6040
6041   v8::Debug::SetMessageHandler(ContextCheckMessageHandler);
6042
6043   // Default data value is undefined.
6044   CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6045   CHECK(context_2->GetEmbedderData(0)->IsUndefined());
6046
6047   // Set and check different data values.
6048   v8::Handle<v8::String> data_1 = v8::String::NewFromUtf8(isolate, "1");
6049   v8::Handle<v8::String> data_2 = v8::String::NewFromUtf8(isolate, "2");
6050   context_1->SetEmbedderData(0, data_1);
6051   context_2->SetEmbedderData(0, data_2);
6052   CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6053   CHECK(context_2->GetEmbedderData(0)->StrictEquals(data_2));
6054
6055   // Simple test function which causes a break.
6056   const char* source = "function f() { debugger; }";
6057
6058   // Enter and run function in the first context.
6059   {
6060     v8::Context::Scope context_scope(context_1);
6061     expected_context = context_1;
6062     expected_context_data = data_1;
6063     v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
6064     f->Call(context_1->Global(), 0, NULL);
6065   }
6066
6067
6068   // Enter and run function in the second context.
6069   {
6070     v8::Context::Scope context_scope(context_2);
6071     expected_context = context_2;
6072     expected_context_data = data_2;
6073     v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
6074     f->Call(context_2->Global(), 0, NULL);
6075   }
6076
6077   // Two times compile event and two times break event.
6078   CHECK_GT(message_handler_hit_count, 4);
6079
6080   v8::Debug::SetMessageHandler(NULL);
6081   CheckDebuggerUnloaded();
6082 }
6083
6084
6085 // Debug message handler which issues a debug break when it hits a break event.
6086 static int message_handler_break_hit_count = 0;
6087 static void DebugBreakMessageHandler(const v8::Debug::Message& message) {
6088   // Schedule a debug break for break events.
6089   if (message.IsEvent() && message.GetEvent() == v8::Break) {
6090     message_handler_break_hit_count++;
6091     if (message_handler_break_hit_count == 1) {
6092       v8::Debug::DebugBreak(message.GetIsolate());
6093     }
6094   }
6095
6096   // Issue a continue command if this event will not cause the VM to start
6097   // running.
6098   if (!message.WillStartRunning()) {
6099     SendContinueCommand();
6100   }
6101 }
6102
6103
6104 // Test that a debug break can be scheduled while in a message handler.
6105 TEST(DebugBreakInMessageHandler) {
6106   DebugLocalContext env;
6107   v8::HandleScope scope(env->GetIsolate());
6108
6109   v8::Debug::SetMessageHandler(DebugBreakMessageHandler);
6110
6111   // Test functions.
6112   const char* script = "function f() { debugger; g(); } function g() { }";
6113   CompileRun(script);
6114   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6115       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6116   v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
6117       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
6118
6119   // Call f then g. The debugger statement in f will casue a break which will
6120   // cause another break.
6121   f->Call(env->Global(), 0, NULL);
6122   CHECK_EQ(2, message_handler_break_hit_count);
6123   // Calling g will not cause any additional breaks.
6124   g->Call(env->Global(), 0, NULL);
6125   CHECK_EQ(2, message_handler_break_hit_count);
6126 }
6127
6128
6129 #ifndef V8_INTERPRETED_REGEXP
6130 // Debug event handler which gets the function on the top frame and schedules a
6131 // break a number of times.
6132 static void DebugEventDebugBreak(
6133     const v8::Debug::EventDetails& event_details) {
6134   v8::DebugEvent event = event_details.GetEvent();
6135   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
6136
6137   if (event == v8::Break) {
6138     break_point_hit_count++;
6139
6140     // Get the name of the top frame function.
6141     if (!frame_function_name.IsEmpty()) {
6142       // Get the name of the function.
6143       const int argc = 2;
6144       v8::Handle<v8::Value> argv[argc] = {
6145         exec_state, v8::Integer::New(CcTest::isolate(), 0)
6146       };
6147       v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
6148                                                                argc, argv);
6149       if (result->IsUndefined()) {
6150         last_function_hit[0] = '\0';
6151       } else {
6152         CHECK(result->IsString());
6153         v8::Handle<v8::String> function_name(
6154             result->ToString(CcTest::isolate()));
6155         function_name->WriteUtf8(last_function_hit);
6156       }
6157     }
6158
6159     // Keep forcing breaks.
6160     if (break_point_hit_count < 20) {
6161       v8::Debug::DebugBreak(CcTest::isolate());
6162     }
6163   }
6164 }
6165
6166
6167 TEST(RegExpDebugBreak) {
6168   // This test only applies to native regexps.
6169   DebugLocalContext env;
6170   v8::HandleScope scope(env->GetIsolate());
6171
6172   // Create a function for checking the function when hitting a break point.
6173   frame_function_name = CompileFunction(&env,
6174                                         frame_function_name_source,
6175                                         "frame_function_name");
6176
6177   // Test RegExp which matches white spaces and comments at the begining of a
6178   // source line.
6179   const char* script =
6180     "var sourceLineBeginningSkip = /^(?:[ \\v\\h]*(?:\\/\\*.*?\\*\\/)*)*/;\n"
6181     "function f(s) { return s.match(sourceLineBeginningSkip)[0].length; }";
6182
6183   v8::Local<v8::Function> f = CompileFunction(env->GetIsolate(), script, "f");
6184   const int argc = 1;
6185   v8::Handle<v8::Value> argv[argc] = {
6186       v8::String::NewFromUtf8(env->GetIsolate(), "  /* xxx */ a=0;")};
6187   v8::Local<v8::Value> result = f->Call(env->Global(), argc, argv);
6188   CHECK_EQ(12, result->Int32Value());
6189
6190   v8::Debug::SetDebugEventListener(DebugEventDebugBreak);
6191   v8::Debug::DebugBreak(env->GetIsolate());
6192   result = f->Call(env->Global(), argc, argv);
6193
6194   // Check that there was only one break event. Matching RegExp should not
6195   // cause Break events.
6196   CHECK_EQ(1, break_point_hit_count);
6197   CHECK_EQ(0, strcmp("f", last_function_hit));
6198 }
6199 #endif  // V8_INTERPRETED_REGEXP
6200
6201
6202 // Common part of EvalContextData and NestedBreakEventContextData tests.
6203 static void ExecuteScriptForContextCheck(
6204     v8::Debug::MessageHandler message_handler) {
6205   // Create a context.
6206   v8::Handle<v8::Context> context_1;
6207   v8::Handle<v8::ObjectTemplate> global_template =
6208       v8::Handle<v8::ObjectTemplate>();
6209   context_1 =
6210       v8::Context::New(CcTest::isolate(), NULL, global_template);
6211
6212   v8::Debug::SetMessageHandler(message_handler);
6213
6214   // Default data value is undefined.
6215   CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6216
6217   // Set and check a data value.
6218   v8::Handle<v8::String> data_1 =
6219       v8::String::NewFromUtf8(CcTest::isolate(), "1");
6220   context_1->SetEmbedderData(0, data_1);
6221   CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6222
6223   // Simple test function with eval that causes a break.
6224   const char* source = "function f() { eval('debugger;'); }";
6225
6226   // Enter and run function in the context.
6227   {
6228     v8::Context::Scope context_scope(context_1);
6229     expected_context = context_1;
6230     expected_context_data = data_1;
6231     v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f");
6232     f->Call(context_1->Global(), 0, NULL);
6233   }
6234
6235   v8::Debug::SetMessageHandler(NULL);
6236 }
6237
6238
6239 // Test which creates a context and sets embedder data on it. Checks that this
6240 // data is set correctly and that when the debug message handler is called for
6241 // break event in an eval statement the expected context is the one returned by
6242 // Message.GetEventContext.
6243 TEST(EvalContextData) {
6244   v8::HandleScope scope(CcTest::isolate());
6245
6246   ExecuteScriptForContextCheck(ContextCheckMessageHandler);
6247
6248   // One time compile event and one time break event.
6249   CHECK_GT(message_handler_hit_count, 2);
6250   CheckDebuggerUnloaded();
6251 }
6252
6253
6254 static bool sent_eval = false;
6255 static int break_count = 0;
6256 static int continue_command_send_count = 0;
6257 // Check that the expected context is the one generating the debug event
6258 // including the case of nested break event.
6259 static void DebugEvalContextCheckMessageHandler(
6260     const v8::Debug::Message& message) {
6261   CHECK(message.GetEventContext() == expected_context);
6262   CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6263       expected_context_data));
6264   message_handler_hit_count++;
6265
6266   static char print_buffer[1000];
6267   v8::String::Value json(message.GetJSON());
6268   Utf16ToAscii(*json, json.length(), print_buffer);
6269
6270   v8::Isolate* isolate = message.GetIsolate();
6271   if (IsBreakEventMessage(print_buffer)) {
6272     break_count++;
6273     if (!sent_eval) {
6274       sent_eval = true;
6275
6276       const int kBufferSize = 1000;
6277       uint16_t buffer[kBufferSize];
6278       const char* eval_command =
6279           "{\"seq\":0,"
6280           "\"type\":\"request\","
6281           "\"command\":\"evaluate\","
6282           "\"arguments\":{\"expression\":\"debugger;\","
6283           "\"global\":true,\"disable_break\":false}}";
6284
6285       // Send evaluate command.
6286       v8::Debug::SendCommand(
6287           isolate, buffer, AsciiToUtf16(eval_command, buffer));
6288       return;
6289     } else {
6290       // It's a break event caused by the evaluation request above.
6291       SendContinueCommand();
6292       continue_command_send_count++;
6293     }
6294   } else if (IsEvaluateResponseMessage(print_buffer) &&
6295       continue_command_send_count < 2) {
6296     // Response to the evaluation request. We're still on the breakpoint so
6297     // send continue.
6298     SendContinueCommand();
6299     continue_command_send_count++;
6300   }
6301 }
6302
6303
6304 // Tests that context returned for break event is correct when the event occurs
6305 // in 'evaluate' debugger request.
6306 TEST(NestedBreakEventContextData) {
6307   v8::HandleScope scope(CcTest::isolate());
6308   break_count = 0;
6309   message_handler_hit_count = 0;
6310
6311   ExecuteScriptForContextCheck(DebugEvalContextCheckMessageHandler);
6312
6313   // One time compile event and two times break event.
6314   CHECK_GT(message_handler_hit_count, 3);
6315
6316   // One break from the source and another from the evaluate request.
6317   CHECK_EQ(break_count, 2);
6318   CheckDebuggerUnloaded();
6319 }
6320
6321
6322 // Debug event listener which counts the after compile events.
6323 int after_compile_message_count = 0;
6324 static void AfterCompileMessageHandler(const v8::Debug::Message& message) {
6325   // Count the number of scripts collected.
6326   if (message.IsEvent()) {
6327     if (message.GetEvent() == v8::AfterCompile) {
6328       after_compile_message_count++;
6329     } else if (message.GetEvent() == v8::Break) {
6330       SendContinueCommand();
6331     }
6332   }
6333 }
6334
6335
6336 // Tests that after compile event is sent as many times as there are scripts
6337 // compiled.
6338 TEST(AfterCompileMessageWhenMessageHandlerIsReset) {
6339   DebugLocalContext env;
6340   v8::HandleScope scope(env->GetIsolate());
6341   after_compile_message_count = 0;
6342   const char* script = "var a=1";
6343
6344   v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6345   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6346       ->Run();
6347   v8::Debug::SetMessageHandler(NULL);
6348
6349   v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6350   v8::Debug::DebugBreak(env->GetIsolate());
6351   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6352       ->Run();
6353
6354   // Setting listener to NULL should cause debugger unload.
6355   v8::Debug::SetMessageHandler(NULL);
6356   CheckDebuggerUnloaded();
6357
6358   // Compilation cache should be disabled when debugger is active.
6359   CHECK_EQ(2, after_compile_message_count);
6360 }
6361
6362
6363 // Syntax error event handler which counts a number of events.
6364 int compile_error_event_count = 0;
6365
6366 static void CompileErrorEventCounterClear() {
6367   compile_error_event_count = 0;
6368 }
6369
6370 static void CompileErrorEventCounter(
6371     const v8::Debug::EventDetails& event_details) {
6372   v8::DebugEvent event = event_details.GetEvent();
6373
6374   if (event == v8::CompileError) {
6375     compile_error_event_count++;
6376   }
6377 }
6378
6379
6380 // Tests that syntax error event is sent as many times as there are scripts
6381 // with syntax error compiled.
6382 TEST(SyntaxErrorMessageOnSyntaxException) {
6383   DebugLocalContext env;
6384   v8::HandleScope scope(env->GetIsolate());
6385
6386   // For this test, we want to break on uncaught exceptions:
6387   ChangeBreakOnException(false, true);
6388
6389   v8::Debug::SetDebugEventListener(CompileErrorEventCounter);
6390
6391   CompileErrorEventCounterClear();
6392
6393   // Check initial state.
6394   CHECK_EQ(0, compile_error_event_count);
6395
6396   // Throws SyntaxError: Unexpected end of input
6397   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "+++"));
6398   CHECK_EQ(1, compile_error_event_count);
6399
6400   v8::Script::Compile(
6401     v8::String::NewFromUtf8(env->GetIsolate(), "/sel\\/: \\"));
6402   CHECK_EQ(2, compile_error_event_count);
6403
6404   v8::Script::Compile(
6405     v8::String::NewFromUtf8(env->GetIsolate(), "JSON.parse('1234:')"));
6406   CHECK_EQ(2, compile_error_event_count);
6407
6408   v8::Script::Compile(
6409     v8::String::NewFromUtf8(env->GetIsolate(), "new RegExp('/\\/\\\\');"));
6410   CHECK_EQ(2, compile_error_event_count);
6411
6412   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "throw 1;"));
6413   CHECK_EQ(2, compile_error_event_count);
6414 }
6415
6416
6417 // Tests that break event is sent when message handler is reset.
6418 TEST(BreakMessageWhenMessageHandlerIsReset) {
6419   DebugLocalContext env;
6420   v8::HandleScope scope(env->GetIsolate());
6421   after_compile_message_count = 0;
6422   const char* script = "function f() {};";
6423
6424   v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6425   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6426       ->Run();
6427   v8::Debug::SetMessageHandler(NULL);
6428
6429   v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6430   v8::Debug::DebugBreak(env->GetIsolate());
6431   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6432       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6433   f->Call(env->Global(), 0, NULL);
6434
6435   // Setting message handler to NULL should cause debugger unload.
6436   v8::Debug::SetMessageHandler(NULL);
6437   CheckDebuggerUnloaded();
6438
6439   // Compilation cache should be disabled when debugger is active.
6440   CHECK_EQ(1, after_compile_message_count);
6441 }
6442
6443
6444 static int exception_event_count = 0;
6445 static void ExceptionMessageHandler(const v8::Debug::Message& message) {
6446   if (message.IsEvent() && message.GetEvent() == v8::Exception) {
6447     exception_event_count++;
6448     SendContinueCommand();
6449   }
6450 }
6451
6452
6453 // Tests that exception event is sent when message handler is reset.
6454 TEST(ExceptionMessageWhenMessageHandlerIsReset) {
6455   DebugLocalContext env;
6456   v8::HandleScope scope(env->GetIsolate());
6457
6458   // For this test, we want to break on uncaught exceptions:
6459   ChangeBreakOnException(false, true);
6460
6461   exception_event_count = 0;
6462   const char* script = "function f() {throw new Error()};";
6463
6464   v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6465   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
6466       ->Run();
6467   v8::Debug::SetMessageHandler(NULL);
6468
6469   v8::Debug::SetMessageHandler(ExceptionMessageHandler);
6470   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
6471       env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
6472   f->Call(env->Global(), 0, NULL);
6473
6474   // Setting message handler to NULL should cause debugger unload.
6475   v8::Debug::SetMessageHandler(NULL);
6476   CheckDebuggerUnloaded();
6477
6478   CHECK_EQ(1, exception_event_count);
6479 }
6480
6481
6482 // Tests after compile event is sent when there are some provisional
6483 // breakpoints out of the scripts lines range.
6484 TEST(ProvisionalBreakpointOnLineOutOfRange) {
6485   DebugLocalContext env;
6486   v8::HandleScope scope(env->GetIsolate());
6487   env.ExposeDebug();
6488   const char* script = "function f() {};";
6489   const char* resource_name = "test_resource";
6490
6491   // Set a couple of provisional breakpoint on lines out of the script lines
6492   // range.
6493   int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name,
6494                                              3, -1 /* no column */);
6495   int sbp2 =
6496       SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5);
6497
6498   after_compile_message_count = 0;
6499   v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
6500
6501   v8::ScriptOrigin origin(
6502       v8::String::NewFromUtf8(env->GetIsolate(), resource_name),
6503       v8::Integer::New(env->GetIsolate(), 10),
6504       v8::Integer::New(env->GetIsolate(), 1));
6505   // Compile a script whose first line number is greater than the breakpoints'
6506   // lines.
6507   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script),
6508                       &origin)->Run();
6509
6510   // If the script is compiled successfully there is exactly one after compile
6511   // event. In case of an exception in debugger code after compile event is not
6512   // sent.
6513   CHECK_EQ(1, after_compile_message_count);
6514
6515   ClearBreakPointFromJS(env->GetIsolate(), sbp1);
6516   ClearBreakPointFromJS(env->GetIsolate(), sbp2);
6517   v8::Debug::SetMessageHandler(NULL);
6518 }
6519
6520
6521 static void BreakMessageHandler(const v8::Debug::Message& message) {
6522   i::Isolate* isolate = CcTest::i_isolate();
6523   if (message.IsEvent() && message.GetEvent() == v8::Break) {
6524     // Count the number of breaks.
6525     break_point_hit_count++;
6526
6527     i::HandleScope scope(isolate);
6528     message.GetJSON();
6529
6530     SendContinueCommand();
6531   } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
6532     i::HandleScope scope(isolate);
6533
6534     int current_count = break_point_hit_count;
6535
6536     // Force serialization to trigger some internal JS execution.
6537     message.GetJSON();
6538
6539     CHECK_EQ(current_count, break_point_hit_count);
6540   }
6541 }
6542
6543
6544 // Test that if DebugBreak is forced it is ignored when code from
6545 // debug-delay.js is executed.
6546 TEST(NoDebugBreakInAfterCompileMessageHandler) {
6547   DebugLocalContext env;
6548   v8::HandleScope scope(env->GetIsolate());
6549
6550   // Register a debug event listener which sets the break flag and counts.
6551   v8::Debug::SetMessageHandler(BreakMessageHandler);
6552
6553   // Set the debug break flag.
6554   v8::Debug::DebugBreak(env->GetIsolate());
6555
6556   // Create a function for testing stepping.
6557   const char* src = "function f() { eval('var x = 10;'); } ";
6558   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
6559
6560   // There should be only one break event.
6561   CHECK_EQ(1, break_point_hit_count);
6562
6563   // Set the debug break flag again.
6564   v8::Debug::DebugBreak(env->GetIsolate());
6565   f->Call(env->Global(), 0, NULL);
6566   // There should be one more break event when the script is evaluated in 'f'.
6567   CHECK_EQ(2, break_point_hit_count);
6568
6569   // Get rid of the debug message handler.
6570   v8::Debug::SetMessageHandler(NULL);
6571   CheckDebuggerUnloaded();
6572 }
6573
6574
6575 static int counting_message_handler_counter;
6576
6577 static void CountingMessageHandler(const v8::Debug::Message& message) {
6578   if (message.IsResponse()) counting_message_handler_counter++;
6579 }
6580
6581
6582 // Test that debug messages get processed when ProcessDebugMessages is called.
6583 TEST(ProcessDebugMessages) {
6584   DebugLocalContext env;
6585   v8::Isolate* isolate = env->GetIsolate();
6586   v8::HandleScope scope(isolate);
6587
6588   counting_message_handler_counter = 0;
6589
6590   v8::Debug::SetMessageHandler(CountingMessageHandler);
6591
6592   const int kBufferSize = 1000;
6593   uint16_t buffer[kBufferSize];
6594   const char* scripts_command =
6595     "{\"seq\":0,"
6596      "\"type\":\"request\","
6597      "\"command\":\"scripts\"}";
6598
6599   // Send scripts command.
6600   v8::Debug::SendCommand(
6601       isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6602
6603   CHECK_EQ(0, counting_message_handler_counter);
6604   v8::Debug::ProcessDebugMessages();
6605   // At least one message should come
6606   CHECK_GE(counting_message_handler_counter, 1);
6607
6608   counting_message_handler_counter = 0;
6609
6610   v8::Debug::SendCommand(
6611       isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6612   v8::Debug::SendCommand(
6613       isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6614   CHECK_EQ(0, counting_message_handler_counter);
6615   v8::Debug::ProcessDebugMessages();
6616   // At least two messages should come
6617   CHECK_GE(counting_message_handler_counter, 2);
6618
6619   // Get rid of the debug message handler.
6620   v8::Debug::SetMessageHandler(NULL);
6621   CheckDebuggerUnloaded();
6622 }
6623
6624
6625 class SendCommandThread;
6626 static SendCommandThread* send_command_thread_ = NULL;
6627
6628
6629 class SendCommandThread : public v8::base::Thread {
6630  public:
6631   explicit SendCommandThread(v8::Isolate* isolate)
6632       : Thread(Options("SendCommandThread")),
6633         semaphore_(0),
6634         isolate_(isolate) {}
6635
6636   static void CountingAndSignallingMessageHandler(
6637       const v8::Debug::Message& message) {
6638     if (message.IsResponse()) {
6639       counting_message_handler_counter++;
6640       send_command_thread_->semaphore_.Signal();
6641     }
6642   }
6643
6644   virtual void Run() {
6645     semaphore_.Wait();
6646     const int kBufferSize = 1000;
6647     uint16_t buffer[kBufferSize];
6648     const char* scripts_command =
6649       "{\"seq\":0,"
6650        "\"type\":\"request\","
6651        "\"command\":\"scripts\"}";
6652     int length = AsciiToUtf16(scripts_command, buffer);
6653     // Send scripts command.
6654
6655     for (int i = 0; i < 20; i++) {
6656       v8::base::ElapsedTimer timer;
6657       timer.Start();
6658       CHECK_EQ(i, counting_message_handler_counter);
6659       // Queue debug message.
6660       v8::Debug::SendCommand(isolate_, buffer, length);
6661       // Wait for the message handler to pick up the response.
6662       semaphore_.Wait();
6663       i::PrintF("iteration %d took %f ms\n", i,
6664                 timer.Elapsed().InMillisecondsF());
6665     }
6666
6667     v8::V8::TerminateExecution(isolate_);
6668   }
6669
6670   void StartSending() { semaphore_.Signal(); }
6671
6672  private:
6673   v8::base::Semaphore semaphore_;
6674   v8::Isolate* isolate_;
6675 };
6676
6677
6678 static void StartSendingCommands(
6679     const v8::FunctionCallbackInfo<v8::Value>& info) {
6680   send_command_thread_->StartSending();
6681 }
6682
6683
6684 TEST(ProcessDebugMessagesThreaded) {
6685   DebugLocalContext env;
6686   v8::Isolate* isolate = env->GetIsolate();
6687   v8::HandleScope scope(isolate);
6688
6689   counting_message_handler_counter = 0;
6690
6691   v8::Debug::SetMessageHandler(
6692       SendCommandThread::CountingAndSignallingMessageHandler);
6693   send_command_thread_ = new SendCommandThread(isolate);
6694   send_command_thread_->Start();
6695
6696   v8::Handle<v8::FunctionTemplate> start =
6697       v8::FunctionTemplate::New(isolate, StartSendingCommands);
6698   env->Global()->Set(v8_str("start"), start->GetFunction());
6699
6700   i::FLAG_turbo_osr = false;  // TODO(titzer): interrupts in TF loops.
6701   CompileRun("start(); while (true) { }");
6702
6703   CHECK_EQ(20, counting_message_handler_counter);
6704
6705   v8::Debug::SetMessageHandler(NULL);
6706   CheckDebuggerUnloaded();
6707 }
6708
6709
6710 struct BacktraceData {
6711   static int frame_counter;
6712   static void MessageHandler(const v8::Debug::Message& message) {
6713     char print_buffer[1000];
6714     v8::String::Value json(message.GetJSON());
6715     Utf16ToAscii(*json, json.length(), print_buffer, 1000);
6716
6717     if (strstr(print_buffer, "backtrace") == NULL) {
6718       return;
6719     }
6720     frame_counter = GetTotalFramesInt(print_buffer);
6721   }
6722 };
6723
6724 int BacktraceData::frame_counter;
6725
6726
6727 // Test that debug messages get processed when ProcessDebugMessages is called.
6728 TEST(Backtrace) {
6729   DebugLocalContext env;
6730   v8::Isolate* isolate = env->GetIsolate();
6731   v8::HandleScope scope(isolate);
6732
6733   v8::Debug::SetMessageHandler(BacktraceData::MessageHandler);
6734
6735   const int kBufferSize = 1000;
6736   uint16_t buffer[kBufferSize];
6737   const char* scripts_command =
6738     "{\"seq\":0,"
6739      "\"type\":\"request\","
6740      "\"command\":\"backtrace\"}";
6741
6742   // Check backtrace from ProcessDebugMessages.
6743   BacktraceData::frame_counter = -10;
6744   v8::Debug::SendCommand(
6745       isolate,
6746       buffer,
6747       AsciiToUtf16(scripts_command, buffer),
6748       NULL);
6749   v8::Debug::ProcessDebugMessages();
6750   CHECK_EQ(BacktraceData::frame_counter, 0);
6751
6752   v8::Handle<v8::String> void0 =
6753       v8::String::NewFromUtf8(env->GetIsolate(), "void(0)");
6754   v8::Handle<v8::Script> script = CompileWithOrigin(void0, void0);
6755
6756   // Check backtrace from "void(0)" script.
6757   BacktraceData::frame_counter = -10;
6758   v8::Debug::SendCommand(
6759       isolate,
6760       buffer,
6761       AsciiToUtf16(scripts_command, buffer),
6762       NULL);
6763   script->Run();
6764   CHECK_EQ(BacktraceData::frame_counter, 1);
6765
6766   // Get rid of the debug message handler.
6767   v8::Debug::SetMessageHandler(NULL);
6768   CheckDebuggerUnloaded();
6769 }
6770
6771
6772 TEST(GetMirror) {
6773   DebugLocalContext env;
6774   v8::Isolate* isolate = env->GetIsolate();
6775   v8::HandleScope scope(isolate);
6776   v8::Handle<v8::Value> obj =
6777       v8::Debug::GetMirror(v8::String::NewFromUtf8(isolate, "hodja"));
6778   v8::ScriptCompiler::Source source(v8_str(
6779       "function runTest(mirror) {"
6780       "  return mirror.isString() && (mirror.length() == 5);"
6781       "}"
6782       ""
6783       "runTest;"));
6784   v8::Handle<v8::Function> run_test = v8::Handle<v8::Function>::Cast(
6785       v8::ScriptCompiler::CompileUnbound(isolate, &source)
6786           ->BindToCurrentContext()
6787           ->Run());
6788   v8::Handle<v8::Value> result = run_test->Call(env->Global(), 1, &obj);
6789   CHECK(result->IsTrue());
6790 }
6791
6792
6793 // Test that the debug break flag works with function.apply.
6794 TEST(DebugBreakFunctionApply) {
6795   DebugLocalContext env;
6796   v8::HandleScope scope(env->GetIsolate());
6797
6798   // Create a function for testing breaking in apply.
6799   v8::Local<v8::Function> foo = CompileFunction(
6800       &env,
6801       "function baz(x) { }"
6802       "function bar(x) { baz(); }"
6803       "function foo(){ bar.apply(this, [1]); }",
6804       "foo");
6805
6806   // Register a debug event listener which steps and counts.
6807   v8::Debug::SetDebugEventListener(DebugEventBreakMax);
6808
6809   // Set the debug break flag before calling the code using function.apply.
6810   v8::Debug::DebugBreak(env->GetIsolate());
6811
6812   // Limit the number of debug breaks. This is a regression test for issue 493
6813   // where this test would enter an infinite loop.
6814   break_point_hit_count = 0;
6815   max_break_point_hit_count = 10000;  // 10000 => infinite loop.
6816   foo->Call(env->Global(), 0, NULL);
6817
6818   // When keeping the debug break several break will happen.
6819   CHECK_GT(break_point_hit_count, 1);
6820
6821   v8::Debug::SetDebugEventListener(NULL);
6822   CheckDebuggerUnloaded();
6823 }
6824
6825
6826 v8::Handle<v8::Context> debugee_context;
6827 v8::Handle<v8::Context> debugger_context;
6828
6829
6830 // Property getter that checks that current and calling contexts
6831 // are both the debugee contexts.
6832 static void NamedGetterWithCallingContextCheck(
6833     v8::Local<v8::String> name,
6834     const v8::PropertyCallbackInfo<v8::Value>& info) {
6835   CHECK_EQ(0, strcmp(*v8::String::Utf8Value(name), "a"));
6836   v8::Handle<v8::Context> current = info.GetIsolate()->GetCurrentContext();
6837   CHECK(current == debugee_context);
6838   CHECK(current != debugger_context);
6839   v8::Handle<v8::Context> calling = info.GetIsolate()->GetCallingContext();
6840   CHECK(calling == debugee_context);
6841   CHECK(calling != debugger_context);
6842   info.GetReturnValue().Set(1);
6843 }
6844
6845
6846 // Debug event listener that checks if the first argument of a function is
6847 // an object with property 'a' == 1. If the property has custom accessor
6848 // this handler will eventually invoke it.
6849 static void DebugEventGetAtgumentPropertyValue(
6850     const v8::Debug::EventDetails& event_details) {
6851   v8::DebugEvent event = event_details.GetEvent();
6852   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
6853   if (event == v8::Break) {
6854     break_point_hit_count++;
6855     CHECK(debugger_context == CcTest::isolate()->GetCurrentContext());
6856     v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(CompileRun(
6857         "(function(exec_state) {\n"
6858         "    return (exec_state.frame(0).argumentValue(0).property('a').\n"
6859         "            value().value() == 1);\n"
6860         "})"));
6861     const int argc = 1;
6862     v8::Handle<v8::Value> argv[argc] = { exec_state };
6863     v8::Handle<v8::Value> result = func->Call(exec_state, argc, argv);
6864     CHECK(result->IsTrue());
6865   }
6866 }
6867
6868
6869 TEST(CallingContextIsNotDebugContext) {
6870   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
6871   // Create and enter a debugee context.
6872   DebugLocalContext env;
6873   v8::Isolate* isolate = env->GetIsolate();
6874   v8::HandleScope scope(isolate);
6875   env.ExposeDebug();
6876
6877   // Save handles to the debugger and debugee contexts to be used in
6878   // NamedGetterWithCallingContextCheck.
6879   debugee_context = env.context();
6880   debugger_context = v8::Utils::ToLocal(debug->debug_context());
6881
6882   // Create object with 'a' property accessor.
6883   v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New(isolate);
6884   named->SetAccessor(v8::String::NewFromUtf8(isolate, "a"),
6885                      NamedGetterWithCallingContextCheck);
6886   env->Global()->Set(v8::String::NewFromUtf8(isolate, "obj"),
6887                      named->NewInstance());
6888
6889   // Register the debug event listener
6890   v8::Debug::SetDebugEventListener(DebugEventGetAtgumentPropertyValue);
6891
6892   // Create a function that invokes debugger.
6893   v8::Local<v8::Function> foo = CompileFunction(
6894       &env,
6895       "function bar(x) { debugger; }"
6896       "function foo(){ bar(obj); }",
6897       "foo");
6898
6899   break_point_hit_count = 0;
6900   foo->Call(env->Global(), 0, NULL);
6901   CHECK_EQ(1, break_point_hit_count);
6902
6903   v8::Debug::SetDebugEventListener(NULL);
6904   debugee_context = v8::Handle<v8::Context>();
6905   debugger_context = v8::Handle<v8::Context>();
6906   CheckDebuggerUnloaded();
6907 }
6908
6909
6910 TEST(DebugContextIsPreservedBetweenAccesses) {
6911   v8::HandleScope scope(CcTest::isolate());
6912   v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
6913   v8::Local<v8::Context> context1 = v8::Debug::GetDebugContext();
6914   v8::Local<v8::Context> context2 = v8::Debug::GetDebugContext();
6915   CHECK(v8::Utils::OpenHandle(*context1).is_identical_to(
6916             v8::Utils::OpenHandle(*context2)));
6917   v8::Debug::SetDebugEventListener(NULL);
6918 }
6919
6920
6921 static v8::Handle<v8::Value> expected_callback_data;
6922 static void DebugEventContextChecker(const v8::Debug::EventDetails& details) {
6923   CHECK(details.GetEventContext() == expected_context);
6924   CHECK(expected_callback_data->Equals(details.GetCallbackData()));
6925 }
6926
6927
6928 // Check that event details contain context where debug event occured.
6929 TEST(DebugEventContext) {
6930   v8::Isolate* isolate = CcTest::isolate();
6931   v8::HandleScope scope(isolate);
6932   expected_context = v8::Context::New(isolate);
6933   expected_callback_data = v8::Int32::New(isolate, 2010);
6934   v8::Debug::SetDebugEventListener(DebugEventContextChecker,
6935                                     expected_callback_data);
6936   v8::Context::Scope context_scope(expected_context);
6937   v8::Script::Compile(
6938       v8::String::NewFromUtf8(isolate, "(function(){debugger;})();"))->Run();
6939   expected_context.Clear();
6940   v8::Debug::SetDebugEventListener(NULL);
6941   expected_context_data = v8::Handle<v8::Value>();
6942   CheckDebuggerUnloaded();
6943 }
6944
6945
6946 static void* expected_break_data;
6947 static bool was_debug_break_called;
6948 static bool was_debug_event_called;
6949 static void DebugEventBreakDataChecker(const v8::Debug::EventDetails& details) {
6950   if (details.GetEvent() == v8::BreakForCommand) {
6951     CHECK_EQ(expected_break_data, details.GetClientData());
6952     was_debug_event_called = true;
6953   } else if (details.GetEvent() == v8::Break) {
6954     was_debug_break_called = true;
6955   }
6956 }
6957
6958
6959 // Check that event details contain context where debug event occured.
6960 TEST(DebugEventBreakData) {
6961   DebugLocalContext env;
6962   v8::Isolate* isolate = env->GetIsolate();
6963   v8::HandleScope scope(isolate);
6964   v8::Debug::SetDebugEventListener(DebugEventBreakDataChecker);
6965
6966   TestClientData::constructor_call_counter = 0;
6967   TestClientData::destructor_call_counter = 0;
6968
6969   expected_break_data = NULL;
6970   was_debug_event_called = false;
6971   was_debug_break_called = false;
6972   v8::Debug::DebugBreakForCommand(isolate, NULL);
6973   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
6974                                               "(function(x){return x;})(1);"))
6975       ->Run();
6976   CHECK(was_debug_event_called);
6977   CHECK(!was_debug_break_called);
6978
6979   TestClientData* data1 = new TestClientData();
6980   expected_break_data = data1;
6981   was_debug_event_called = false;
6982   was_debug_break_called = false;
6983   v8::Debug::DebugBreakForCommand(isolate, data1);
6984   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
6985                                               "(function(x){return x+1;})(1);"))
6986       ->Run();
6987   CHECK(was_debug_event_called);
6988   CHECK(!was_debug_break_called);
6989
6990   expected_break_data = NULL;
6991   was_debug_event_called = false;
6992   was_debug_break_called = false;
6993   v8::Debug::DebugBreak(isolate);
6994   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
6995                                               "(function(x){return x+2;})(1);"))
6996       ->Run();
6997   CHECK(!was_debug_event_called);
6998   CHECK(was_debug_break_called);
6999
7000   TestClientData* data2 = new TestClientData();
7001   expected_break_data = data2;
7002   was_debug_event_called = false;
7003   was_debug_break_called = false;
7004   v8::Debug::DebugBreak(isolate);
7005   v8::Debug::DebugBreakForCommand(isolate, data2);
7006   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
7007                                               "(function(x){return x+3;})(1);"))
7008       ->Run();
7009   CHECK(was_debug_event_called);
7010   CHECK(was_debug_break_called);
7011
7012   CHECK_EQ(2, TestClientData::constructor_call_counter);
7013   CHECK_EQ(TestClientData::constructor_call_counter,
7014            TestClientData::destructor_call_counter);
7015
7016   v8::Debug::SetDebugEventListener(NULL);
7017   CheckDebuggerUnloaded();
7018 }
7019
7020 static bool debug_event_break_deoptimize_done = false;
7021
7022 static void DebugEventBreakDeoptimize(
7023     const v8::Debug::EventDetails& event_details) {
7024   v8::DebugEvent event = event_details.GetEvent();
7025   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7026   if (event == v8::Break) {
7027     if (!frame_function_name.IsEmpty()) {
7028       // Get the name of the function.
7029       const int argc = 2;
7030       v8::Handle<v8::Value> argv[argc] = {
7031         exec_state, v8::Integer::New(CcTest::isolate(), 0)
7032       };
7033       v8::Handle<v8::Value> result =
7034           frame_function_name->Call(exec_state, argc, argv);
7035       if (!result->IsUndefined()) {
7036         char fn[80];
7037         CHECK(result->IsString());
7038         v8::Handle<v8::String> function_name(
7039             result->ToString(CcTest::isolate()));
7040         function_name->WriteUtf8(fn);
7041         if (strcmp(fn, "bar") == 0) {
7042           i::Deoptimizer::DeoptimizeAll(CcTest::i_isolate());
7043           debug_event_break_deoptimize_done = true;
7044         }
7045       }
7046     }
7047
7048     v8::Debug::DebugBreak(CcTest::isolate());
7049   }
7050 }
7051
7052
7053 // Test deoptimization when execution is broken using the debug break stack
7054 // check interrupt.
7055 TEST(DeoptimizeDuringDebugBreak) {
7056   DebugLocalContext env;
7057   v8::HandleScope scope(env->GetIsolate());
7058   env.ExposeDebug();
7059
7060   // Create a function for checking the function when hitting a break point.
7061   frame_function_name = CompileFunction(&env,
7062                                         frame_function_name_source,
7063                                         "frame_function_name");
7064
7065
7066   // Set a debug event listener which will keep interrupting execution until
7067   // debug break. When inside function bar it will deoptimize all functions.
7068   // This tests lazy deoptimization bailout for the stack check, as the first
7069   // time in function bar when using debug break and no break points will be at
7070   // the initial stack check.
7071   v8::Debug::SetDebugEventListener(DebugEventBreakDeoptimize);
7072
7073   // Compile and run function bar which will optimize it for some flag settings.
7074   v8::Script::Compile(v8::String::NewFromUtf8(
7075                           env->GetIsolate(), "function bar(){}; bar()"))->Run();
7076
7077   // Set debug break and call bar again.
7078   v8::Debug::DebugBreak(env->GetIsolate());
7079   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "bar()"))
7080       ->Run();
7081
7082   CHECK(debug_event_break_deoptimize_done);
7083
7084   v8::Debug::SetDebugEventListener(NULL);
7085 }
7086
7087
7088 static void DebugEventBreakWithOptimizedStack(
7089     const v8::Debug::EventDetails& event_details) {
7090   v8::Isolate* isolate = event_details.GetEventContext()->GetIsolate();
7091   v8::DebugEvent event = event_details.GetEvent();
7092   v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7093   if (event == v8::Break) {
7094     if (!frame_function_name.IsEmpty()) {
7095       for (int i = 0; i < 2; i++) {
7096         const int argc = 2;
7097         v8::Handle<v8::Value> argv[argc] = {
7098           exec_state, v8::Integer::New(isolate, i)
7099         };
7100         // Get the name of the function in frame i.
7101         v8::Handle<v8::Value> result =
7102             frame_function_name->Call(exec_state, argc, argv);
7103         CHECK(result->IsString());
7104         v8::Handle<v8::String> function_name(result->ToString(isolate));
7105         CHECK(function_name->Equals(v8::String::NewFromUtf8(isolate, "loop")));
7106         // Get the name of the first argument in frame i.
7107         result = frame_argument_name->Call(exec_state, argc, argv);
7108         CHECK(result->IsString());
7109         v8::Handle<v8::String> argument_name(result->ToString(isolate));
7110         CHECK(argument_name->Equals(v8::String::NewFromUtf8(isolate, "count")));
7111         // Get the value of the first argument in frame i. If the
7112         // funtion is optimized the value will be undefined, otherwise
7113         // the value will be '1 - i'.
7114         //
7115         // TODO(3141533): We should be able to get the real value for
7116         // optimized frames.
7117         result = frame_argument_value->Call(exec_state, argc, argv);
7118         CHECK(result->IsUndefined() || (result->Int32Value() == 1 - i));
7119         // Get the name of the first local variable.
7120         result = frame_local_name->Call(exec_state, argc, argv);
7121         CHECK(result->IsString());
7122         v8::Handle<v8::String> local_name(result->ToString(isolate));
7123         CHECK(local_name->Equals(v8::String::NewFromUtf8(isolate, "local")));
7124         // Get the value of the first local variable. If the function
7125         // is optimized the value will be undefined, otherwise it will
7126         // be 42.
7127         //
7128         // TODO(3141533): We should be able to get the real value for
7129         // optimized frames.
7130         result = frame_local_value->Call(exec_state, argc, argv);
7131         CHECK(result->IsUndefined() || (result->Int32Value() == 42));
7132       }
7133     }
7134   }
7135 }
7136
7137
7138 static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
7139   v8::Debug::SetDebugEventListener(DebugEventBreakWithOptimizedStack);
7140   v8::Debug::DebugBreak(args.GetIsolate());
7141 }
7142
7143
7144 TEST(DebugBreakStackInspection) {
7145   DebugLocalContext env;
7146   v8::HandleScope scope(env->GetIsolate());
7147
7148   frame_function_name =
7149       CompileFunction(&env, frame_function_name_source, "frame_function_name");
7150   frame_argument_name =
7151       CompileFunction(&env, frame_argument_name_source, "frame_argument_name");
7152   frame_argument_value = CompileFunction(&env,
7153                                          frame_argument_value_source,
7154                                          "frame_argument_value");
7155   frame_local_name =
7156       CompileFunction(&env, frame_local_name_source, "frame_local_name");
7157   frame_local_value =
7158       CompileFunction(&env, frame_local_value_source, "frame_local_value");
7159
7160   v8::Handle<v8::FunctionTemplate> schedule_break_template =
7161       v8::FunctionTemplate::New(env->GetIsolate(), ScheduleBreak);
7162   v8::Handle<v8::Function> schedule_break =
7163       schedule_break_template->GetFunction();
7164   env->Global()->Set(v8_str("scheduleBreak"), schedule_break);
7165
7166   const char* src =
7167       "function loop(count) {"
7168       "  var local = 42;"
7169       "  if (count < 1) { scheduleBreak(); loop(count + 1); }"
7170       "}"
7171       "loop(0);";
7172   v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), src))->Run();
7173 }
7174
7175
7176 // Test that setting the terminate execution flag during debug break processing.
7177 static void TestDebugBreakInLoop(const char* loop_head,
7178                                  const char** loop_bodies,
7179                                  const char* loop_tail) {
7180   // Receive 100 breaks for each test and then terminate JavaScript execution.
7181   static const int kBreaksPerTest = 100;
7182
7183   for (int i = 0; loop_bodies[i] != NULL; i++) {
7184     // Perform a lazy deoptimization after various numbers of breaks
7185     // have been hit.
7186     for (int j = 0; j < 7; j++) {
7187       break_point_hit_count_deoptimize = j;
7188       if (j == 6) {
7189         break_point_hit_count_deoptimize = kBreaksPerTest;
7190       }
7191
7192       break_point_hit_count = 0;
7193       max_break_point_hit_count = kBreaksPerTest;
7194       terminate_after_max_break_point_hit = true;
7195
7196       EmbeddedVector<char, 1024> buffer;
7197       SNPrintF(buffer,
7198                "function f() {%s%s%s}",
7199                loop_head, loop_bodies[i], loop_tail);
7200
7201       // Function with infinite loop.
7202       CompileRun(buffer.start());
7203
7204       // Set the debug break to enter the debugger as soon as possible.
7205       v8::Debug::DebugBreak(CcTest::isolate());
7206
7207       // Call function with infinite loop.
7208       CompileRun("f();");
7209       CHECK_EQ(kBreaksPerTest, break_point_hit_count);
7210
7211       CHECK(!v8::V8::IsExecutionTerminating());
7212     }
7213   }
7214 }
7215
7216
7217 TEST(DebugBreakLoop) {
7218   DebugLocalContext env;
7219   v8::HandleScope scope(env->GetIsolate());
7220
7221   // Register a debug event listener which sets the break flag and counts.
7222   v8::Debug::SetDebugEventListener(DebugEventBreakMax);
7223
7224   // Create a function for getting the frame count when hitting the break.
7225   frame_count = CompileFunction(&env, frame_count_source, "frame_count");
7226
7227   CompileRun("var a = 1;");
7228   CompileRun("function g() { }");
7229   CompileRun("function h() { }");
7230
7231   const char* loop_bodies[] = {
7232       "",
7233       "g()",
7234       "if (a == 0) { g() }",
7235       "if (a == 1) { g() }",
7236       "if (a == 0) { g() } else { h() }",
7237       "if (a == 0) { continue }",
7238       "if (a == 1) { continue }",
7239       "switch (a) { case 1: g(); }",
7240       "switch (a) { case 1: continue; }",
7241       "switch (a) { case 1: g(); break; default: h() }",
7242       "switch (a) { case 1: continue; break; default: h() }",
7243       NULL
7244   };
7245
7246   TestDebugBreakInLoop("while (true) {", loop_bodies, "}");
7247   TestDebugBreakInLoop("while (a == 1) {", loop_bodies, "}");
7248
7249   TestDebugBreakInLoop("do {", loop_bodies, "} while (true)");
7250   TestDebugBreakInLoop("do {", loop_bodies, "} while (a == 1)");
7251
7252   TestDebugBreakInLoop("for (;;) {", loop_bodies, "}");
7253   TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}");
7254
7255   // Get rid of the debug event listener.
7256   v8::Debug::SetDebugEventListener(NULL);
7257   CheckDebuggerUnloaded();
7258 }
7259
7260
7261 v8::Local<v8::Script> inline_script;
7262
7263 static void DebugBreakInlineListener(
7264     const v8::Debug::EventDetails& event_details) {
7265   v8::DebugEvent event = event_details.GetEvent();
7266   if (event != v8::Break) return;
7267
7268   int expected_frame_count = 4;
7269   int expected_line_number[] = {1, 4, 7, 12};
7270
7271   i::Handle<i::Object> compiled_script = v8::Utils::OpenHandle(*inline_script);
7272   i::Handle<i::Script> source_script = i::Handle<i::Script>(i::Script::cast(
7273       i::JSFunction::cast(*compiled_script)->shared()->script()));
7274
7275   int break_id = CcTest::i_isolate()->debug()->break_id();
7276   char script[128];
7277   i::Vector<char> script_vector(script, sizeof(script));
7278   SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
7279   v8::Local<v8::Value> result = CompileRun(script);
7280
7281   int frame_count = result->Int32Value();
7282   CHECK_EQ(expected_frame_count, frame_count);
7283
7284   for (int i = 0; i < frame_count; i++) {
7285     // The 5. element in the returned array of GetFrameDetails contains the
7286     // source position of that frame.
7287     SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
7288     v8::Local<v8::Value> result = CompileRun(script);
7289     CHECK_EQ(expected_line_number[i],
7290              i::Script::GetLineNumber(source_script, result->Int32Value()));
7291   }
7292   v8::Debug::SetDebugEventListener(NULL);
7293   v8::V8::TerminateExecution(CcTest::isolate());
7294 }
7295
7296
7297 TEST(DebugBreakInline) {
7298   i::FLAG_allow_natives_syntax = true;
7299   DebugLocalContext env;
7300   v8::HandleScope scope(env->GetIsolate());
7301   const char* source =
7302       "function debug(b) {             \n"
7303       "  if (b) debugger;              \n"
7304       "}                               \n"
7305       "function f(b) {                 \n"
7306       "  debug(b)                      \n"
7307       "};                              \n"
7308       "function g(b) {                 \n"
7309       "  f(b);                         \n"
7310       "};                              \n"
7311       "g(false);                       \n"
7312       "g(false);                       \n"
7313       "%OptimizeFunctionOnNextCall(g); \n"
7314       "g(true);";
7315   v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
7316   inline_script =
7317       v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source));
7318   inline_script->Run();
7319 }
7320
7321
7322 static void DebugEventStepNext(
7323     const v8::Debug::EventDetails& event_details) {
7324   v8::DebugEvent event = event_details.GetEvent();
7325   if (event == v8::Break) {
7326     PrepareStep(StepNext);
7327   }
7328 }
7329
7330
7331 static void RunScriptInANewCFrame(const char* source) {
7332   v8::TryCatch try_catch;
7333   CompileRun(source);
7334   CHECK(try_catch.HasCaught());
7335 }
7336
7337
7338 TEST(Regress131642) {
7339   // Bug description:
7340   // When doing StepNext through the first script, the debugger is not reset
7341   // after exiting through exception.  A flawed implementation enabling the
7342   // debugger to step into Array.prototype.forEach breaks inside the callback
7343   // for forEach in the second script under the assumption that we are in a
7344   // recursive call.  In an attempt to step out, we crawl the stack using the
7345   // recorded frame pointer from the first script and fail when not finding it
7346   // on the stack.
7347   DebugLocalContext env;
7348   v8::HandleScope scope(env->GetIsolate());
7349   v8::Debug::SetDebugEventListener(DebugEventStepNext);
7350
7351   // We step through the first script.  It exits through an exception.  We run
7352   // this inside a new frame to record a different FP than the second script
7353   // would expect.
7354   const char* script_1 = "debugger; throw new Error();";
7355   RunScriptInANewCFrame(script_1);
7356
7357   // The second script uses forEach.
7358   const char* script_2 = "[0].forEach(function() { });";
7359   CompileRun(script_2);
7360
7361   v8::Debug::SetDebugEventListener(NULL);
7362 }
7363
7364
7365 // Import from test-heap.cc
7366 int CountNativeContexts();
7367
7368
7369 static void NopListener(const v8::Debug::EventDetails& event_details) {
7370 }
7371
7372
7373 TEST(DebuggerCreatesContextIffActive) {
7374   DebugLocalContext env;
7375   v8::HandleScope scope(env->GetIsolate());
7376   CHECK_EQ(1, CountNativeContexts());
7377
7378   v8::Debug::SetDebugEventListener(NULL);
7379   CompileRun("debugger;");
7380   CHECK_EQ(1, CountNativeContexts());
7381
7382   v8::Debug::SetDebugEventListener(NopListener);
7383   CompileRun("debugger;");
7384   CHECK_EQ(2, CountNativeContexts());
7385
7386   v8::Debug::SetDebugEventListener(NULL);
7387 }
7388
7389
7390 TEST(LiveEditEnabled) {
7391   v8::internal::FLAG_allow_natives_syntax = true;
7392   LocalContext env;
7393   v8::HandleScope scope(env->GetIsolate());
7394   v8::Debug::SetLiveEditEnabled(env->GetIsolate(), true);
7395   CompileRun("%LiveEditCompareStrings('', '')");
7396 }
7397
7398
7399 TEST(LiveEditDisabled) {
7400   v8::internal::FLAG_allow_natives_syntax = true;
7401   LocalContext env;
7402   v8::HandleScope scope(env->GetIsolate());
7403   v8::Debug::SetLiveEditEnabled(env->GetIsolate(), false);
7404   CompileRun("%LiveEditCompareStrings('', '')");
7405 }
7406
7407
7408 TEST(PrecompiledFunction) {
7409   // Regression test for crbug.com/346207. If we have preparse data, parsing the
7410   // function in the presence of the debugger (and breakpoints) should still
7411   // succeed. The bug was that preparsing was done lazily and parsing was done
7412   // eagerly, so, the symbol streams didn't match.
7413   DebugLocalContext env;
7414   v8::HandleScope scope(env->GetIsolate());
7415   env.ExposeDebug();
7416   v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
7417
7418   v8::Local<v8::Function> break_here =
7419       CompileFunction(&env, "function break_here(){}", "break_here");
7420   SetBreakPoint(break_here, 0);
7421
7422   const char* source =
7423       "var a = b = c = 1;              \n"
7424       "function this_is_lazy() {       \n"
7425       // This symbol won't appear in the preparse data.
7426       "  var a;                        \n"
7427       "}                               \n"
7428       "function bar() {                \n"
7429       "  return \"bar\";               \n"
7430       "};                              \n"
7431       "a = b = c = 2;                  \n"
7432       "bar();                          \n";
7433   v8::Local<v8::Value> result = ParserCacheCompileRun(source);
7434   CHECK(result->IsString());
7435   v8::String::Utf8Value utf8(result);
7436   CHECK_EQ(0, strcmp("bar", *utf8));
7437
7438   v8::Debug::SetDebugEventListener(NULL);
7439   CheckDebuggerUnloaded();
7440 }
7441
7442
7443 static void DebugBreakStackTraceListener(
7444     const v8::Debug::EventDetails& event_details) {
7445   v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
7446 }
7447
7448
7449 static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
7450   v8::Debug::DebugBreak(args.GetIsolate());
7451 }
7452
7453
7454 TEST(DebugBreakStackTrace) {
7455   DebugLocalContext env;
7456   v8::HandleScope scope(env->GetIsolate());
7457   v8::Debug::SetDebugEventListener(DebugBreakStackTraceListener);
7458   v8::Handle<v8::FunctionTemplate> add_debug_break_template =
7459       v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
7460   v8::Handle<v8::Function> add_debug_break =
7461       add_debug_break_template->GetFunction();
7462   env->Global()->Set(v8_str("add_debug_break"), add_debug_break);
7463
7464   CompileRun("(function loop() {"
7465              "  for (var j = 0; j < 1000; j++) {"
7466              "    for (var i = 0; i < 1000; i++) {"
7467              "      if (i == 999) add_debug_break();"
7468              "    }"
7469              "  }"
7470              "})()");
7471 }
7472
7473
7474 v8::base::Semaphore terminate_requested_semaphore(0);
7475 v8::base::Semaphore terminate_fired_semaphore(0);
7476 bool terminate_already_fired = false;
7477
7478
7479 static void DebugBreakTriggerTerminate(
7480     const v8::Debug::EventDetails& event_details) {
7481   if (event_details.GetEvent() != v8::Break || terminate_already_fired) return;
7482   terminate_requested_semaphore.Signal();
7483   // Wait for at most 2 seconds for the terminate request.
7484   CHECK(terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
7485   terminate_already_fired = true;
7486 }
7487
7488
7489 class TerminationThread : public v8::base::Thread {
7490  public:
7491   explicit TerminationThread(v8::Isolate* isolate)
7492       : Thread(Options("terminator")), isolate_(isolate) {}
7493
7494   virtual void Run() {
7495     terminate_requested_semaphore.Wait();
7496     v8::V8::TerminateExecution(isolate_);
7497     terminate_fired_semaphore.Signal();
7498   }
7499
7500  private:
7501   v8::Isolate* isolate_;
7502 };
7503
7504
7505 TEST(DebugBreakOffThreadTerminate) {
7506   DebugLocalContext env;
7507   v8::Isolate* isolate = env->GetIsolate();
7508   v8::HandleScope scope(isolate);
7509   v8::Debug::SetDebugEventListener(DebugBreakTriggerTerminate);
7510   TerminationThread terminator(isolate);
7511   terminator.Start();
7512   v8::TryCatch try_catch;
7513   v8::Debug::DebugBreak(isolate);
7514   CompileRun("while (true);");
7515   CHECK(try_catch.HasTerminated());
7516 }
7517
7518
7519 static void DebugEventExpectNoException(
7520     const v8::Debug::EventDetails& event_details) {
7521   v8::DebugEvent event = event_details.GetEvent();
7522   CHECK_NE(v8::Exception, event);
7523 }
7524
7525
7526 static void TryCatchWrappedThrowCallback(
7527     const v8::FunctionCallbackInfo<v8::Value>& args) {
7528   v8::TryCatch try_catch;
7529   CompileRun("throw 'rejection';");
7530   CHECK(try_catch.HasCaught());
7531 }
7532
7533
7534 TEST(DebugPromiseInterceptedByTryCatch) {
7535   DebugLocalContext env;
7536   v8::Isolate* isolate = env->GetIsolate();
7537   v8::HandleScope scope(isolate);
7538   v8::Debug::SetDebugEventListener(&DebugEventExpectNoException);
7539   ChangeBreakOnException(false, true);
7540
7541   v8::Handle<v8::FunctionTemplate> fun =
7542       v8::FunctionTemplate::New(isolate, TryCatchWrappedThrowCallback);
7543   env->Global()->Set(v8_str("fun"), fun->GetFunction());
7544
7545   CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
7546   CompileRun(
7547       "var r;"
7548       "p.chain(function() { r = 'resolved'; },"
7549       "        function() { r = 'rejected'; });");
7550   CHECK(CompileRun("r")->Equals(v8_str("resolved")));
7551 }
7552
7553
7554 static int exception_event_counter = 0;
7555
7556
7557 static void DebugEventCountException(
7558     const v8::Debug::EventDetails& event_details) {
7559   v8::DebugEvent event = event_details.GetEvent();
7560   if (event == v8::Exception) exception_event_counter++;
7561 }
7562
7563
7564 static void ThrowCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7565   CompileRun("throw 'rejection';");
7566 }
7567
7568
7569 TEST(DebugPromiseRejectedByCallback) {
7570   DebugLocalContext env;
7571   v8::Isolate* isolate = env->GetIsolate();
7572   v8::HandleScope scope(isolate);
7573   v8::Debug::SetDebugEventListener(&DebugEventCountException);
7574   ChangeBreakOnException(false, true);
7575   exception_event_counter = 0;
7576
7577   v8::Handle<v8::FunctionTemplate> fun =
7578       v8::FunctionTemplate::New(isolate, ThrowCallback);
7579   env->Global()->Set(v8_str("fun"), fun->GetFunction());
7580
7581   CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
7582   CompileRun(
7583       "var r;"
7584       "p.chain(function() { r = 'resolved'; },"
7585       "        function(e) { r = 'rejected' + e; });");
7586   CHECK(CompileRun("r")->Equals(v8_str("rejectedrejection")));
7587   CHECK_EQ(1, exception_event_counter);
7588 }
7589
7590
7591 TEST(DebugBreakOnExceptionInObserveCallback) {
7592   DebugLocalContext env;
7593   v8::Isolate* isolate = env->GetIsolate();
7594   v8::HandleScope scope(isolate);
7595   v8::Debug::SetDebugEventListener(&DebugEventCountException);
7596   // Break on uncaught exception
7597   ChangeBreakOnException(false, true);
7598   exception_event_counter = 0;
7599
7600   v8::Handle<v8::FunctionTemplate> fun =
7601       v8::FunctionTemplate::New(isolate, ThrowCallback);
7602   env->Global()->Set(v8_str("fun"), fun->GetFunction());
7603
7604   CompileRun(
7605       "var obj = {};"
7606       "var callbackRan = false;"
7607       "Object.observe(obj, function() {"
7608       "   callbackRan = true;"
7609       "   throw Error('foo');"
7610       "});"
7611       "obj.prop = 1");
7612   CHECK(CompileRun("callbackRan")->BooleanValue());
7613   CHECK_EQ(1, exception_event_counter);
7614 }
7615
7616
7617 static void DebugHarmonyScopingListener(
7618     const v8::Debug::EventDetails& event_details) {
7619   v8::DebugEvent event = event_details.GetEvent();
7620   if (event != v8::Break) return;
7621
7622   int break_id = CcTest::i_isolate()->debug()->break_id();
7623
7624   char script[128];
7625   i::Vector<char> script_vector(script, sizeof(script));
7626   SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
7627   ExpectInt32(script, 1);
7628
7629   SNPrintF(script_vector, "var frame = new FrameMirror(%d, 0);", break_id);
7630   CompileRun(script);
7631   ExpectInt32("frame.evaluate('x').value_", 1);
7632   ExpectInt32("frame.evaluate('y').value_", 2);
7633
7634   CompileRun("var allScopes = frame.allScopes()");
7635   ExpectInt32("allScopes.length", 2);
7636
7637   ExpectBoolean("allScopes[0].scopeType() === ScopeType.Script", true);
7638
7639   ExpectInt32("allScopes[0].scopeObject().value_.x", 1);
7640
7641   ExpectInt32("allScopes[0].scopeObject().value_.y", 2);
7642
7643   CompileRun("allScopes[0].setVariableValue('x', 5);");
7644   CompileRun("allScopes[0].setVariableValue('y', 6);");
7645   ExpectInt32("frame.evaluate('x + y').value_", 11);
7646 }
7647
7648
7649 TEST(DebugBreakInLexicalScopes) {
7650   i::FLAG_allow_natives_syntax = true;
7651
7652   DebugLocalContext env;
7653   v8::Isolate* isolate = env->GetIsolate();
7654   v8::HandleScope scope(isolate);
7655   v8::Debug::SetDebugEventListener(DebugHarmonyScopingListener);
7656
7657   CompileRun(
7658       "'use strict';            \n"
7659       "let x = 1;               \n");
7660   ExpectInt32(
7661       "'use strict';            \n"
7662       "let y = 2;               \n"
7663       "debugger;                \n"
7664       "x * y",
7665       30);
7666   ExpectInt32(
7667       "x = 1; y = 2; \n"
7668       "debugger;"
7669       "x * y",
7670       30);
7671 }