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