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