The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-debug.cc @ 40c0f755

History | View | Annotate | Download (141 KB)

1
// Copyright 2007-2008 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include <stdlib.h>
29

    
30
#include "v8.h"
31

    
32
#include "api.h"
33
#include "debug.h"
34
#include "platform.h"
35
#include "stub-cache.h"
36
#include "cctest.h"
37

    
38

    
39
using ::v8::internal::EmbeddedVector;
40
using ::v8::internal::Object;
41
using ::v8::internal::OS;
42
using ::v8::internal::Handle;
43
using ::v8::internal::Heap;
44
using ::v8::internal::JSGlobalProxy;
45
using ::v8::internal::Code;
46
using ::v8::internal::Debug;
47
using ::v8::internal::Debugger;
48
using ::v8::internal::StepAction;
49
using ::v8::internal::StepIn;  // From StepAction enum
50
using ::v8::internal::StepNext;  // From StepAction enum
51
using ::v8::internal::StepOut;  // From StepAction enum
52

    
53

    
54
// Size of temp buffer for formatting small strings.
55
#define SMALL_STRING_BUFFER_SIZE 80
56

    
57
// --- A d d i t i o n a l   C h e c k   H e l p e r s
58

    
59

    
60
// Helper function used by the CHECK_EQ function when given Address
61
// arguments.  Should not be called directly.
62
static inline void CheckEqualsHelper(const char* file, int line,
63
                                     const char* expected_source,
64
                                     ::v8::internal::Address expected,
65
                                     const char* value_source,
66
                                     ::v8::internal::Address value) {
67
  if (expected != value) {
68
    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n#   "
69
                         "Expected: %i\n#   Found: %i",
70
             expected_source, value_source, expected, value);
71
  }
72
}
73

    
74

    
75
// Helper function used by the CHECK_NE function when given Address
76
// arguments.  Should not be called directly.
77
static inline void CheckNonEqualsHelper(const char* file, int line,
78
                                        const char* unexpected_source,
79
                                        ::v8::internal::Address unexpected,
80
                                        const char* value_source,
81
                                        ::v8::internal::Address value) {
82
  if (unexpected == value) {
83
    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",
84
             unexpected_source, value_source, value);
85
  }
86
}
87

    
88

    
89
// Helper function used by the CHECK function when given code
90
// arguments.  Should not be called directly.
91
static inline void CheckEqualsHelper(const char* file, int line,
92
                                     const char* expected_source,
93
                                     const Code* expected,
94
                                     const char* value_source,
95
                                     const Code* value) {
96
  if (expected != value) {
97
    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n#   "
98
                         "Expected: %p\n#   Found: %p",
99
             expected_source, value_source, expected, value);
100
  }
101
}
102

    
103

    
104
static inline void CheckNonEqualsHelper(const char* file, int line,
105
                                        const char* expected_source,
106
                                        const Code* expected,
107
                                        const char* value_source,
108
                                        const Code* value) {
109
  if (expected == value) {
110
    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
111
             expected_source, value_source, value);
112
  }
113
}
114

    
115

    
116
// --- H e l p e r   C l a s s e s
117

    
118

    
119
// Helper class for creating a V8 enviromnent for running tests
120
class DebugLocalContext {
121
 public:
122
  inline DebugLocalContext(
123
      v8::ExtensionConfiguration* extensions = 0,
124
      v8::Handle<v8::ObjectTemplate> global_template =
125
          v8::Handle<v8::ObjectTemplate>(),
126
      v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
127
      : context_(v8::Context::New(extensions, global_template, global_object)) {
128
    context_->Enter();
129
  }
130
  inline ~DebugLocalContext() {
131
    context_->Exit();
132
    context_.Dispose();
133
  }
134
  inline v8::Context* operator->() { return *context_; }
135
  inline v8::Context* operator*() { return *context_; }
136
  inline bool IsReady() { return !context_.IsEmpty(); }
137
  void ExposeDebug() {
138
    // Expose the debug context global object in the global object for testing.
139
    Debug::Load();
140
    Debug::debug_context()->set_security_token(
141
        v8::Utils::OpenHandle(*context_)->security_token());
142

    
143
    Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
144
        v8::Utils::OpenHandle(*context_->Global())));
145
    Handle<v8::internal::String> debug_string =
146
        v8::internal::Factory::LookupAsciiSymbol("debug");
147
    SetProperty(global, debug_string,
148
        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
149
  }
150
 private:
151
  v8::Persistent<v8::Context> context_;
152
};
153

    
154

    
155
// --- H e l p e r   F u n c t i o n s
156

    
157

    
158
// Compile and run the supplied source and return the fequested function.
159
static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
160
                                               const char* source,
161
                                               const char* function_name) {
162
  v8::Script::Compile(v8::String::New(source))->Run();
163
  return v8::Local<v8::Function>::Cast(
164
      (*env)->Global()->Get(v8::String::New(function_name)));
165
}
166

    
167
// Helper function that compiles and runs the source.
168
static v8::Local<v8::Value> CompileRun(const char* source) {
169
  return v8::Script::Compile(v8::String::New(source))->Run();
170
}
171

    
172
// Is there any debug info for the function?
173
static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
174
  Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
175
  Handle<v8::internal::SharedFunctionInfo> shared(f->shared());
176
  return Debug::HasDebugInfo(shared);
177
}
178

    
179

    
180
// Set a break point in a function and return the associated break point
181
// number.
182
static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
183
  static int break_point = 0;
184
  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
185
  Debug::SetBreakPoint(
186
      shared, position,
187
      Handle<Object>(v8::internal::Smi::FromInt(++break_point)));
188
  return break_point;
189
}
190

    
191

    
192
// Set a break point in a function and return the associated break point
193
// number.
194
static int SetBreakPoint(v8::Handle<v8::Function> fun, int position) {
195
  return SetBreakPoint(v8::Utils::OpenHandle(*fun), position);
196
}
197

    
198

    
199
// Set a break point in a function using the Debug object and return the
200
// associated break point number.
201
static int SetBreakPointFromJS(const char* function_name,
202
                               int line, int position) {
203
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
204
  OS::SNPrintF(buffer,
205
               "debug.Debug.setBreakPoint(%s,%d,%d)",
206
               function_name, line, position);
207
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
208
  v8::Handle<v8::String> str = v8::String::New(buffer.start());
209
  return v8::Script::Compile(str)->Run()->Int32Value();
210
}
211

    
212

    
213
// Set a break point in a script identified by id using the global Debug object.
214
static int SetScriptBreakPointByIdFromJS(int script_id, int line, int column) {
215
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
216
  if (column >= 0) {
217
    // Column specified set script break point on precise location.
218
    OS::SNPrintF(buffer,
219
                 "debug.Debug.setScriptBreakPointById(%d,%d,%d)",
220
                 script_id, line, column);
221
  } else {
222
    // Column not specified set script break point on line.
223
    OS::SNPrintF(buffer,
224
                 "debug.Debug.setScriptBreakPointById(%d,%d)",
225
                 script_id, line);
226
  }
227
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
228
  {
229
    v8::TryCatch try_catch;
230
    v8::Handle<v8::String> str = v8::String::New(buffer.start());
231
    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
232
    ASSERT(!try_catch.HasCaught());
233
    return value->Int32Value();
234
  }
235
}
236

    
237

    
238
// Set a break point in a script identified by name using the global Debug
239
// object.
240
static int SetScriptBreakPointByNameFromJS(const char* script_name,
241
                                           int line, int column) {
242
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
243
  if (column >= 0) {
244
    // Column specified set script break point on precise location.
245
    OS::SNPrintF(buffer,
246
                 "debug.Debug.setScriptBreakPointByName(\"%s\",%d,%d)",
247
                 script_name, line, column);
248
  } else {
249
    // Column not specified set script break point on line.
250
    OS::SNPrintF(buffer,
251
                 "debug.Debug.setScriptBreakPointByName(\"%s\",%d)",
252
                 script_name, line);
253
  }
254
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
255
  {
256
    v8::TryCatch try_catch;
257
    v8::Handle<v8::String> str = v8::String::New(buffer.start());
258
    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
259
    ASSERT(!try_catch.HasCaught());
260
    return value->Int32Value();
261
  }
262
}
263

    
264

    
265
// Clear a break point.
266
static void ClearBreakPoint(int break_point) {
267
  Debug::ClearBreakPoint(
268
      Handle<Object>(v8::internal::Smi::FromInt(break_point)));
269
}
270

    
271

    
272
// Clear a break point using the global Debug object.
273
static void ClearBreakPointFromJS(int break_point_number) {
274
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
275
  OS::SNPrintF(buffer,
276
               "debug.Debug.clearBreakPoint(%d)",
277
               break_point_number);
278
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
279
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
280
}
281

    
282

    
283
static void EnableScriptBreakPointFromJS(int break_point_number) {
284
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
285
  OS::SNPrintF(buffer,
286
               "debug.Debug.enableScriptBreakPoint(%d)",
287
               break_point_number);
288
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
289
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
290
}
291

    
292

    
293
static void DisableScriptBreakPointFromJS(int break_point_number) {
294
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
295
  OS::SNPrintF(buffer,
296
               "debug.Debug.disableScriptBreakPoint(%d)",
297
               break_point_number);
298
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
299
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
300
}
301

    
302

    
303
static void ChangeScriptBreakPointConditionFromJS(int break_point_number,
304
                                                  const char* condition) {
305
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
306
  OS::SNPrintF(buffer,
307
               "debug.Debug.changeScriptBreakPointCondition(%d, \"%s\")",
308
               break_point_number, condition);
309
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
310
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
311
}
312

    
313

    
314
static void ChangeScriptBreakPointIgnoreCountFromJS(int break_point_number,
315
                                                    int ignoreCount) {
316
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
317
  OS::SNPrintF(buffer,
318
               "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
319
               break_point_number, ignoreCount);
320
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
321
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
322
}
323

    
324

    
325
// Change break on exception.
326
static void ChangeBreakOnException(bool caught, bool uncaught) {
327
  Debug::ChangeBreakOnException(v8::internal::BreakException, caught);
328
  Debug::ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
329
}
330

    
331

    
332
// Change break on exception using the global Debug object.
333
static void ChangeBreakOnExceptionFromJS(bool caught, bool uncaught) {
334
  if (caught) {
335
    v8::Script::Compile(
336
        v8::String::New("debug.Debug.setBreakOnException()"))->Run();
337
  } else {
338
    v8::Script::Compile(
339
        v8::String::New("debug.Debug.clearBreakOnException()"))->Run();
340
  }
341
  if (uncaught) {
342
    v8::Script::Compile(
343
        v8::String::New("debug.Debug.setBreakOnUncaughtException()"))->Run();
344
  } else {
345
    v8::Script::Compile(
346
        v8::String::New("debug.Debug.clearBreakOnUncaughtException()"))->Run();
347
  }
348
}
349

    
350

    
351
// Prepare to step to next break location.
352
static void PrepareStep(StepAction step_action) {
353
  Debug::PrepareStep(step_action, 1);
354
}
355

    
356

    
357
// This function is in namespace v8::internal to be friend with class
358
// v8::internal::Debug.
359
namespace v8 { namespace internal {  // NOLINT
360

    
361
// Collect the currently debugged functions.
362
Handle<FixedArray> GetDebuggedFunctions() {
363
  v8::internal::DebugInfoListNode* node = Debug::debug_info_list_;
364

    
365
  // Find the number of debugged functions.
366
  int count = 0;
367
  while (node) {
368
    count++;
369
    node = node->next();
370
  }
371

    
372
  // Allocate array for the debugged functions
373
  Handle<FixedArray> debugged_functions =
374
      v8::internal::Factory::NewFixedArray(count);
375

    
376
  // Run through the debug info objects and collect all functions.
377
  count = 0;
378
  while (node) {
379
    debugged_functions->set(count++, *node->debug_info());
380
    node = node->next();
381
  }
382

    
383
  return debugged_functions;
384
}
385

    
386

    
387
static Handle<Code> ComputeCallDebugBreak(int argc) {
388
  CALL_HEAP_FUNCTION(v8::internal::StubCache::ComputeCallDebugBreak(argc),
389
                     Code);
390
}
391

    
392

    
393
// Check that the debugger has been fully unloaded.
394
void CheckDebuggerUnloaded(bool check_functions) {
395
  // Check that the debugger context is cleared and that there is no debug
396
  // information stored for the debugger.
397
  CHECK(Debug::debug_context().is_null());
398
  CHECK_EQ(NULL, Debug::debug_info_list_);
399

    
400
  // Collect garbage to ensure weak handles are cleared.
401
  Heap::CollectAllGarbage();
402
  Heap::CollectAllGarbage();
403

    
404
  // Iterate the head and check that there are no debugger related objects left.
405
  HeapIterator iterator;
406
  while (iterator.has_next()) {
407
    HeapObject* obj = iterator.next();
408
    CHECK(obj != NULL);
409
    CHECK(!obj->IsDebugInfo());
410
    CHECK(!obj->IsBreakPointInfo());
411

    
412
    // If deep check of functions is requested check that no debug break code
413
    // is left in all functions.
414
    if (check_functions) {
415
      if (obj->IsJSFunction()) {
416
        JSFunction* fun = JSFunction::cast(obj);
417
        for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) {
418
          RelocInfo::Mode rmode = it.rinfo()->rmode();
419
          if (RelocInfo::IsCodeTarget(rmode)) {
420
            CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
421
          } else if (RelocInfo::IsJSReturn(rmode)) {
422
            CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
423
          }
424
        }
425
      }
426
    }
427
  }
428
}
429

    
430

    
431
} }  // namespace v8::internal
432

    
433

    
434
// Check that the debugger has been fully unloaded.
435
static void CheckDebuggerUnloaded(bool check_functions = false) {
436
  v8::internal::CheckDebuggerUnloaded(check_functions);
437
}
438

    
439

    
440
// Inherit from BreakLocationIterator to get access to protected parts for
441
// testing.
442
class TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
443
 public:
444
  explicit TestBreakLocationIterator(Handle<v8::internal::DebugInfo> debug_info)
445
    : BreakLocationIterator(debug_info, v8::internal::SOURCE_BREAK_LOCATIONS) {}
446
  v8::internal::RelocIterator* it() { return reloc_iterator_; }
447
  v8::internal::RelocIterator* it_original() {
448
    return reloc_iterator_original_;
449
  }
450
};
451

    
452

    
453
// Compile a function, set a break point and check that the call at the break
454
// location in the code is the expected debug_break function.
455
void CheckDebugBreakFunction(DebugLocalContext* env,
456
                             const char* source, const char* name,
457
                             int position, v8::internal::RelocInfo::Mode mode,
458
                             Code* debug_break) {
459
  // Create function and set the break point.
460
  Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
461
      *CompileFunction(env, source, name));
462
  int bp = SetBreakPoint(fun, position);
463

    
464
  // Check that the debug break function is as expected.
465
  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
466
  CHECK(Debug::HasDebugInfo(shared));
467
  TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
468
  it1.FindBreakLocationFromPosition(position);
469
  CHECK_EQ(mode, it1.it()->rinfo()->rmode());
470
  if (mode != v8::internal::RelocInfo::JS_RETURN) {
471
    CHECK_EQ(debug_break,
472
        Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
473
  } else {
474
    // TODO(1240753): Make the test architecture independent or split
475
    // parts of the debugger into architecture dependent files.
476
    CHECK_EQ(0xE8, *(it1.rinfo()->pc()));
477
  }
478

    
479
  // Clear the break point and check that the debug break function is no longer
480
  // there
481
  ClearBreakPoint(bp);
482
  CHECK(!Debug::HasDebugInfo(shared));
483
  CHECK(Debug::EnsureDebugInfo(shared));
484
  TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
485
  it2.FindBreakLocationFromPosition(position);
486
  CHECK_EQ(mode, it2.it()->rinfo()->rmode());
487
  if (mode == v8::internal::RelocInfo::JS_RETURN) {
488
    // TODO(1240753): Make the test architecture independent or split
489
    // parts of the debugger into architecture dependent files.
490
    CHECK_NE(0xE8, *(it2.rinfo()->pc()));
491
  }
492
}
493

    
494

    
495
// --- D e b u g   E v e n t   H a n d l e r s
496
// ---
497
// --- The different tests uses a number of debug event handlers.
498
// ---
499

    
500

    
501
// Source for The JavaScript function which picks out the function name of the
502
// top frame.
503
const char* frame_function_name_source =
504
    "function frame_function_name(exec_state) {"
505
    "  return exec_state.frame(0).func().name();"
506
    "}";
507
v8::Local<v8::Function> frame_function_name;
508

    
509

    
510
// Source for The JavaScript function which picks out the source line for the
511
// top frame.
512
const char* frame_source_line_source =
513
    "function frame_source_line(exec_state) {"
514
    "  return exec_state.frame(0).sourceLine();"
515
    "}";
516
v8::Local<v8::Function> frame_source_line;
517

    
518

    
519
// Source for The JavaScript function which picks out the source column for the
520
// top frame.
521
const char* frame_source_column_source =
522
    "function frame_source_column(exec_state) {"
523
    "  return exec_state.frame(0).sourceColumn();"
524
    "}";
525
v8::Local<v8::Function> frame_source_column;
526

    
527

    
528
// Source for The JavaScript function which returns the number of frames.
529
static const char* frame_count_source =
530
    "function frame_count(exec_state) {"
531
    "  return exec_state.frameCount();"
532
    "}";
533
v8::Handle<v8::Function> frame_count;
534

    
535

    
536
// Global variable to store the last function hit - used by some tests.
537
char last_function_hit[80];
538

    
539
// Global variables to store the last source position - used by some tests.
540
int last_source_line = -1;
541
int last_source_column = -1;
542

    
543
// Debug event handler which counts the break points which have been hit.
544
int break_point_hit_count = 0;
545
static void DebugEventBreakPointHitCount(v8::DebugEvent event,
546
                                         v8::Handle<v8::Object> exec_state,
547
                                         v8::Handle<v8::Object> event_data,
548
                                         v8::Handle<v8::Value> data) {
549
  // When hitting a debug event listener there must be a break set.
550
  CHECK_NE(v8::internal::Debug::break_id(), 0);
551

    
552
  // Count the number of breaks.
553
  if (event == v8::Break) {
554
    break_point_hit_count++;
555
    if (!frame_function_name.IsEmpty()) {
556
      // Get the name of the function.
557
      const int argc = 1;
558
      v8::Handle<v8::Value> argv[argc] = { exec_state };
559
      v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
560
                                                               argc, argv);
561
      if (result->IsUndefined()) {
562
        last_function_hit[0] = '\0';
563
      } else {
564
        CHECK(result->IsString());
565
        v8::Handle<v8::String> function_name(result->ToString());
566
        function_name->WriteAscii(last_function_hit);
567
      }
568
    }
569

    
570
    if (!frame_source_line.IsEmpty()) {
571
      // Get the source line.
572
      const int argc = 1;
573
      v8::Handle<v8::Value> argv[argc] = { exec_state };
574
      v8::Handle<v8::Value> result = frame_source_line->Call(exec_state,
575
                                                             argc, argv);
576
      CHECK(result->IsNumber());
577
      last_source_line = result->Int32Value();
578
    }
579

    
580
    if (!frame_source_column.IsEmpty()) {
581
      // Get the source column.
582
      const int argc = 1;
583
      v8::Handle<v8::Value> argv[argc] = { exec_state };
584
      v8::Handle<v8::Value> result = frame_source_column->Call(exec_state,
585
                                                               argc, argv);
586
      CHECK(result->IsNumber());
587
      last_source_column = result->Int32Value();
588
    }
589
  }
590
}
591

    
592

    
593
// Debug event handler which counts a number of events and collects the stack
594
// height if there is a function compiled for that.
595
int exception_hit_count = 0;
596
int uncaught_exception_hit_count = 0;
597
int last_js_stack_height = -1;
598

    
599
static void DebugEventCounterClear() {
600
  break_point_hit_count = 0;
601
  exception_hit_count = 0;
602
  uncaught_exception_hit_count = 0;
603
}
604

    
605
static void DebugEventCounter(v8::DebugEvent event,
606
                              v8::Handle<v8::Object> exec_state,
607
                              v8::Handle<v8::Object> event_data,
608
                              v8::Handle<v8::Value> data) {
609
  // When hitting a debug event listener there must be a break set.
610
  CHECK_NE(v8::internal::Debug::break_id(), 0);
611

    
612
  // Count the number of breaks.
613
  if (event == v8::Break) {
614
    break_point_hit_count++;
615
  } else if (event == v8::Exception) {
616
    exception_hit_count++;
617

    
618
    // Check whether the exception was uncaught.
619
    v8::Local<v8::String> fun_name = v8::String::New("uncaught");
620
    v8::Local<v8::Function> fun =
621
        v8::Function::Cast(*event_data->Get(fun_name));
622
    v8::Local<v8::Value> result = *fun->Call(event_data, 0, NULL);
623
    if (result->IsTrue()) {
624
      uncaught_exception_hit_count++;
625
    }
626
  }
627

    
628
  // Collect the JavsScript stack height if the function frame_count is
629
  // compiled.
630
  if (!frame_count.IsEmpty()) {
631
    static const int kArgc = 1;
632
    v8::Handle<v8::Value> argv[kArgc] = { exec_state };
633
    // Using exec_state as receiver is just to have a receiver.
634
    v8::Handle<v8::Value> result =  frame_count->Call(exec_state, kArgc, argv);
635
    last_js_stack_height = result->Int32Value();
636
  }
637
}
638

    
639

    
640
// Debug event handler which evaluates a number of expressions when a break
641
// point is hit. Each evaluated expression is compared with an expected value.
642
// For this debug event handler to work the following two global varaibles
643
// must be initialized.
644
//   checks: An array of expressions and expected results
645
//   evaluate_check_function: A JavaScript function (see below)
646

    
647
// Structure for holding checks to do.
648
struct EvaluateCheck {
649
  const char* expr;  // An expression to evaluate when a break point is hit.
650
  v8::Handle<v8::Value> expected;  // The expected result.
651
};
652
// Array of checks to do.
653
struct EvaluateCheck* checks = NULL;
654
// Source for The JavaScript function which can do the evaluation when a break
655
// point is hit.
656
const char* evaluate_check_source =
657
    "function evaluate_check(exec_state, expr, expected) {"
658
    "  return exec_state.frame(0).evaluate(expr).value() === expected;"
659
    "}";
660
v8::Local<v8::Function> evaluate_check_function;
661

    
662
// The actual debug event described by the longer comment above.
663
static void DebugEventEvaluate(v8::DebugEvent event,
664
                               v8::Handle<v8::Object> exec_state,
665
                               v8::Handle<v8::Object> event_data,
666
                               v8::Handle<v8::Value> data) {
667
  // When hitting a debug event listener there must be a break set.
668
  CHECK_NE(v8::internal::Debug::break_id(), 0);
669

    
670
  if (event == v8::Break) {
671
    for (int i = 0; checks[i].expr != NULL; i++) {
672
      const int argc = 3;
673
      v8::Handle<v8::Value> argv[argc] = { exec_state,
674
                                           v8::String::New(checks[i].expr),
675
                                           checks[i].expected };
676
      v8::Handle<v8::Value> result =
677
          evaluate_check_function->Call(exec_state, argc, argv);
678
      if (!result->IsTrue()) {
679
        v8::String::AsciiValue ascii(checks[i].expected->ToString());
680
        V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *ascii);
681
      }
682
    }
683
  }
684
}
685

    
686

    
687
// This debug event listener removes a breakpoint in a function
688
int debug_event_remove_break_point = 0;
689
static void DebugEventRemoveBreakPoint(v8::DebugEvent event,
690
                                       v8::Handle<v8::Object> exec_state,
691
                                       v8::Handle<v8::Object> event_data,
692
                                       v8::Handle<v8::Value> data) {
693
  // When hitting a debug event listener there must be a break set.
694
  CHECK_NE(v8::internal::Debug::break_id(), 0);
695

    
696
  if (event == v8::Break) {
697
    break_point_hit_count++;
698
    v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(data);
699
    ClearBreakPoint(debug_event_remove_break_point);
700
  }
701
}
702

    
703

    
704
// Debug event handler which counts break points hit and performs a step
705
// afterwards.
706
StepAction step_action = StepIn;  // Step action to perform when stepping.
707
static void DebugEventStep(v8::DebugEvent event,
708
                           v8::Handle<v8::Object> exec_state,
709
                           v8::Handle<v8::Object> event_data,
710
                           v8::Handle<v8::Value> data) {
711
  // When hitting a debug event listener there must be a break set.
712
  CHECK_NE(v8::internal::Debug::break_id(), 0);
713

    
714
  if (event == v8::Break) {
715
    break_point_hit_count++;
716
    PrepareStep(step_action);
717
  }
718
}
719

    
720

    
721
// Debug event handler which counts break points hit and performs a step
722
// afterwards. For each call the expected function is checked.
723
// For this debug event handler to work the following two global varaibles
724
// must be initialized.
725
//   expected_step_sequence: An array of the expected function call sequence.
726
//   frame_function_name: A JavaScript function (see below).
727

    
728
// String containing the expected function call sequence. Note: this only works
729
// if functions have name length of one.
730
const char* expected_step_sequence = NULL;
731

    
732
// The actual debug event described by the longer comment above.
733
static void DebugEventStepSequence(v8::DebugEvent event,
734
                                   v8::Handle<v8::Object> exec_state,
735
                                   v8::Handle<v8::Object> event_data,
736
                                   v8::Handle<v8::Value> data) {
737
  // When hitting a debug event listener there must be a break set.
738
  CHECK_NE(v8::internal::Debug::break_id(), 0);
739

    
740
  if (event == v8::Break || event == v8::Exception) {
741
    // Check that the current function is the expected.
742
    CHECK(break_point_hit_count <
743
          static_cast<int>(strlen(expected_step_sequence)));
744
    const int argc = 1;
745
    v8::Handle<v8::Value> argv[argc] = { exec_state };
746
    v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
747
                                                             argc, argv);
748
    CHECK(result->IsString());
749
    v8::String::AsciiValue function_name(result->ToString());
750
    CHECK_EQ(1, strlen(*function_name));
751
    CHECK_EQ((*function_name)[0],
752
              expected_step_sequence[break_point_hit_count]);
753

    
754
    // Perform step.
755
    break_point_hit_count++;
756
    PrepareStep(step_action);
757
  }
758
}
759

    
760

    
761
// Debug event handler which performs a garbage collection.
762
static void DebugEventBreakPointCollectGarbage(
763
    v8::DebugEvent event,
764
    v8::Handle<v8::Object> exec_state,
765
    v8::Handle<v8::Object> event_data,
766
    v8::Handle<v8::Value> data) {
767
  // When hitting a debug event listener there must be a break set.
768
  CHECK_NE(v8::internal::Debug::break_id(), 0);
769

    
770
  // Perform a garbage collection when break point is hit and continue. Based
771
  // on the number of break points hit either scavenge or mark compact
772
  // collector is used.
773
  if (event == v8::Break) {
774
    break_point_hit_count++;
775
    if (break_point_hit_count % 2 == 0) {
776
      // Scavenge.
777
      Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
778
    } else {
779
      // Mark sweep (and perhaps compact).
780
      Heap::CollectAllGarbage();
781
    }
782
  }
783
}
784

    
785

    
786
// Debug event handler which re-issues a debug break and calls the garbage
787
// collector to have the heap verified.
788
static void DebugEventBreak(v8::DebugEvent event,
789
                            v8::Handle<v8::Object> exec_state,
790
                            v8::Handle<v8::Object> event_data,
791
                            v8::Handle<v8::Value> data) {
792
  // When hitting a debug event listener there must be a break set.
793
  CHECK_NE(v8::internal::Debug::break_id(), 0);
794

    
795
  if (event == v8::Break) {
796
    // Count the number of breaks.
797
    break_point_hit_count++;
798

    
799
    // Run the garbage collector to enforce heap verification if option
800
    // --verify-heap is set.
801
    Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
802

    
803
    // Set the break flag again to come back here as soon as possible.
804
    v8::Debug::DebugBreak();
805
  }
806
}
807

    
808

    
809
// --- M e s s a g e   C a l l b a c k
810

    
811

    
812
// Message callback which counts the number of messages.
813
int message_callback_count = 0;
814

    
815
static void MessageCallbackCountClear() {
816
  message_callback_count = 0;
817
}
818

    
819
static void MessageCallbackCount(v8::Handle<v8::Message> message,
820
                                 v8::Handle<v8::Value> data) {
821
  message_callback_count++;
822
}
823

    
824

    
825
// --- T h e   A c t u a l   T e s t s
826

    
827

    
828
// Test that the debug break function is the expected one for different kinds
829
// of break locations.
830
TEST(DebugStub) {
831
  using ::v8::internal::Builtins;
832
  v8::HandleScope scope;
833
  DebugLocalContext env;
834

    
835
  CheckDebugBreakFunction(&env,
836
                          "function f1(){}", "f1",
837
                          0,
838
                          v8::internal::RelocInfo::JS_RETURN,
839
                          NULL);
840
  CheckDebugBreakFunction(&env,
841
                          "function f2(){x=1;}", "f2",
842
                          0,
843
                          v8::internal::RelocInfo::CODE_TARGET,
844
                          Builtins::builtin(Builtins::StoreIC_DebugBreak));
845
  CheckDebugBreakFunction(&env,
846
                          "function f3(){var a=x;}", "f3",
847
                          0,
848
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
849
                          Builtins::builtin(Builtins::LoadIC_DebugBreak));
850

    
851
// TODO(1240753): Make the test architecture independent or split
852
// parts of the debugger into architecture dependent files. This
853
// part currently disabled as it is not portable between IA32/ARM.
854
// Currently on ICs for keyed store/load on ARM.
855
#if !defined (__arm__) && !defined(__thumb__)
856
  CheckDebugBreakFunction(
857
      &env,
858
      "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
859
      "f4",
860
      0,
861
      v8::internal::RelocInfo::CODE_TARGET,
862
      Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
863
  CheckDebugBreakFunction(
864
      &env,
865
      "function f5(){var index='propertyName'; var a={}; return a[index];}",
866
      "f5",
867
      0,
868
      v8::internal::RelocInfo::CODE_TARGET,
869
      Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
870
#endif
871

    
872
  // Check the debug break code stubs for call ICs with different number of
873
  // parameters.
874
  Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
875
  Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
876
  Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
877

    
878
  CheckDebugBreakFunction(&env,
879
                          "function f4_0(){x();}", "f4_0",
880
                          0,
881
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
882
                          *debug_break_0);
883

    
884
  CheckDebugBreakFunction(&env,
885
                          "function f4_1(){x(1);}", "f4_1",
886
                          0,
887
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
888
                          *debug_break_1);
889

    
890
  CheckDebugBreakFunction(&env,
891
                          "function f4_4(){x(1,2,3,4);}", "f4_4",
892
                          0,
893
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
894
                          *debug_break_4);
895
}
896

    
897

    
898
// Test that the debug info in the VM is in sync with the functions being
899
// debugged.
900
TEST(DebugInfo) {
901
  v8::HandleScope scope;
902
  DebugLocalContext env;
903
  // Create a couple of functions for the test.
904
  v8::Local<v8::Function> foo =
905
      CompileFunction(&env, "function foo(){}", "foo");
906
  v8::Local<v8::Function> bar =
907
      CompileFunction(&env, "function bar(){}", "bar");
908
  // Initially no functions are debugged.
909
  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
910
  CHECK(!HasDebugInfo(foo));
911
  CHECK(!HasDebugInfo(bar));
912
  // One function (foo) is debugged.
913
  int bp1 = SetBreakPoint(foo, 0);
914
  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
915
  CHECK(HasDebugInfo(foo));
916
  CHECK(!HasDebugInfo(bar));
917
  // Two functions are debugged.
918
  int bp2 = SetBreakPoint(bar, 0);
919
  CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
920
  CHECK(HasDebugInfo(foo));
921
  CHECK(HasDebugInfo(bar));
922
  // One function (bar) is debugged.
923
  ClearBreakPoint(bp1);
924
  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
925
  CHECK(!HasDebugInfo(foo));
926
  CHECK(HasDebugInfo(bar));
927
  // No functions are debugged.
928
  ClearBreakPoint(bp2);
929
  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
930
  CHECK(!HasDebugInfo(foo));
931
  CHECK(!HasDebugInfo(bar));
932
}
933

    
934

    
935
// Test that a break point can be set at an IC store location.
936
TEST(BreakPointICStore) {
937
  break_point_hit_count = 0;
938
  v8::HandleScope scope;
939
  DebugLocalContext env;
940

    
941
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
942
                                   v8::Undefined());
943
  v8::Script::Compile(v8::String::New("function foo(){bar=0;}"))->Run();
944
  v8::Local<v8::Function> foo =
945
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
946

    
947
  // Run without breakpoints.
948
  foo->Call(env->Global(), 0, NULL);
949
  CHECK_EQ(0, break_point_hit_count);
950

    
951
  // Run with breakpoint
952
  int bp = SetBreakPoint(foo, 0);
953
  foo->Call(env->Global(), 0, NULL);
954
  CHECK_EQ(1, break_point_hit_count);
955
  foo->Call(env->Global(), 0, NULL);
956
  CHECK_EQ(2, break_point_hit_count);
957

    
958
  // Run without breakpoints.
959
  ClearBreakPoint(bp);
960
  foo->Call(env->Global(), 0, NULL);
961
  CHECK_EQ(2, break_point_hit_count);
962

    
963
  v8::Debug::SetDebugEventListener(NULL);
964
  CheckDebuggerUnloaded();
965
}
966

    
967

    
968
// Test that a break point can be set at an IC load location.
969
TEST(BreakPointICLoad) {
970
  break_point_hit_count = 0;
971
  v8::HandleScope scope;
972
  DebugLocalContext env;
973
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
974
                                   v8::Undefined());
975
  v8::Script::Compile(v8::String::New("bar=1"))->Run();
976
  v8::Script::Compile(v8::String::New("function foo(){var x=bar;}"))->Run();
977
  v8::Local<v8::Function> foo =
978
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
979

    
980
  // Run without breakpoints.
981
  foo->Call(env->Global(), 0, NULL);
982
  CHECK_EQ(0, break_point_hit_count);
983

    
984
  // Run with breakpoint
985
  int bp = SetBreakPoint(foo, 0);
986
  foo->Call(env->Global(), 0, NULL);
987
  CHECK_EQ(1, break_point_hit_count);
988
  foo->Call(env->Global(), 0, NULL);
989
  CHECK_EQ(2, break_point_hit_count);
990

    
991
  // Run without breakpoints.
992
  ClearBreakPoint(bp);
993
  foo->Call(env->Global(), 0, NULL);
994
  CHECK_EQ(2, break_point_hit_count);
995

    
996
  v8::Debug::SetDebugEventListener(NULL);
997
  CheckDebuggerUnloaded();
998
}
999

    
1000

    
1001
// Test that a break point can be set at an IC call location.
1002
TEST(BreakPointICCall) {
1003
  break_point_hit_count = 0;
1004
  v8::HandleScope scope;
1005
  DebugLocalContext env;
1006
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1007
                                   v8::Undefined());
1008
  v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
1009
  v8::Script::Compile(v8::String::New("function foo(){bar();}"))->Run();
1010
  v8::Local<v8::Function> foo =
1011
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1012

    
1013
  // Run without breakpoints.
1014
  foo->Call(env->Global(), 0, NULL);
1015
  CHECK_EQ(0, break_point_hit_count);
1016

    
1017
  // Run with breakpoint
1018
  int bp = SetBreakPoint(foo, 0);
1019
  foo->Call(env->Global(), 0, NULL);
1020
  CHECK_EQ(1, break_point_hit_count);
1021
  foo->Call(env->Global(), 0, NULL);
1022
  CHECK_EQ(2, break_point_hit_count);
1023

    
1024
  // Run without breakpoints.
1025
  ClearBreakPoint(bp);
1026
  foo->Call(env->Global(), 0, NULL);
1027
  CHECK_EQ(2, break_point_hit_count);
1028

    
1029
  v8::Debug::SetDebugEventListener(NULL);
1030
  CheckDebuggerUnloaded();
1031
}
1032

    
1033

    
1034
// Test that a break point can be set at a return store location.
1035
TEST(BreakPointReturn) {
1036
  break_point_hit_count = 0;
1037
  v8::HandleScope scope;
1038
  DebugLocalContext env;
1039

    
1040
  // Create a functions for checking the source line and column when hitting
1041
  // a break point.
1042
  frame_source_line = CompileFunction(&env,
1043
                                      frame_source_line_source,
1044
                                      "frame_source_line");
1045
  frame_source_column = CompileFunction(&env,
1046
                                        frame_source_column_source,
1047
                                        "frame_source_column");
1048

    
1049

    
1050
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1051
                                   v8::Undefined());
1052
  v8::Script::Compile(v8::String::New("function foo(){}"))->Run();
1053
  v8::Local<v8::Function> foo =
1054
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1055

    
1056
  // Run without breakpoints.
1057
  foo->Call(env->Global(), 0, NULL);
1058
  CHECK_EQ(0, break_point_hit_count);
1059

    
1060
  // Run with breakpoint
1061
  int bp = SetBreakPoint(foo, 0);
1062
  foo->Call(env->Global(), 0, NULL);
1063
  CHECK_EQ(1, break_point_hit_count);
1064
  CHECK_EQ(0, last_source_line);
1065
  CHECK_EQ(16, last_source_column);
1066
  foo->Call(env->Global(), 0, NULL);
1067
  CHECK_EQ(2, break_point_hit_count);
1068
  CHECK_EQ(0, last_source_line);
1069
  CHECK_EQ(16, last_source_column);
1070

    
1071
  // Run without breakpoints.
1072
  ClearBreakPoint(bp);
1073
  foo->Call(env->Global(), 0, NULL);
1074
  CHECK_EQ(2, break_point_hit_count);
1075

    
1076
  v8::Debug::SetDebugEventListener(NULL);
1077
  CheckDebuggerUnloaded();
1078
}
1079

    
1080

    
1081
static void CallWithBreakPoints(v8::Local<v8::Object> recv,
1082
                                v8::Local<v8::Function> f,
1083
                                int break_point_count,
1084
                                int call_count) {
1085
  break_point_hit_count = 0;
1086
  for (int i = 0; i < call_count; i++) {
1087
    f->Call(recv, 0, NULL);
1088
    CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
1089
  }
1090
}
1091

    
1092
// Test GC during break point processing.
1093
TEST(GCDuringBreakPointProcessing) {
1094
  break_point_hit_count = 0;
1095
  v8::HandleScope scope;
1096
  DebugLocalContext env;
1097

    
1098
  v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage,
1099
                                   v8::Undefined());
1100
  v8::Local<v8::Function> foo;
1101

    
1102
  // Test IC store break point with garbage collection.
1103
  foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1104
  SetBreakPoint(foo, 0);
1105
  CallWithBreakPoints(env->Global(), foo, 1, 10);
1106

    
1107
  // Test IC load break point with garbage collection.
1108
  foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1109
  SetBreakPoint(foo, 0);
1110
  CallWithBreakPoints(env->Global(), foo, 1, 10);
1111

    
1112
  // Test IC call break point with garbage collection.
1113
  foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
1114
  SetBreakPoint(foo, 0);
1115
  CallWithBreakPoints(env->Global(), foo, 1, 10);
1116

    
1117
  // Test return break point with garbage collection.
1118
  foo = CompileFunction(&env, "function foo(){}", "foo");
1119
  SetBreakPoint(foo, 0);
1120
  CallWithBreakPoints(env->Global(), foo, 1, 25);
1121

    
1122
  v8::Debug::SetDebugEventListener(NULL);
1123
  CheckDebuggerUnloaded();
1124
}
1125

    
1126

    
1127
// Call the function three times with different garbage collections in between
1128
// and make sure that the break point survives.
1129
static void CallAndGC(v8::Local<v8::Object> recv, v8::Local<v8::Function> f) {
1130
  break_point_hit_count = 0;
1131

    
1132
  for (int i = 0; i < 3; i++) {
1133
    // Call function.
1134
    f->Call(recv, 0, NULL);
1135
    CHECK_EQ(1 + i * 3, break_point_hit_count);
1136

    
1137
    // Scavenge and call function.
1138
    Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
1139
    f->Call(recv, 0, NULL);
1140
    CHECK_EQ(2 + i * 3, break_point_hit_count);
1141

    
1142
    // Mark sweep (and perhaps compact) and call function.
1143
    Heap::CollectAllGarbage();
1144
    f->Call(recv, 0, NULL);
1145
    CHECK_EQ(3 + i * 3, break_point_hit_count);
1146
  }
1147
}
1148

    
1149

    
1150
// Test that a break point can be set at a return store location.
1151
TEST(BreakPointSurviveGC) {
1152
  break_point_hit_count = 0;
1153
  v8::HandleScope scope;
1154
  DebugLocalContext env;
1155

    
1156
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1157
                                   v8::Undefined());
1158
  v8::Local<v8::Function> foo;
1159

    
1160
  // Test IC store break point with garbage collection.
1161
  foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1162
  SetBreakPoint(foo, 0);
1163
  CallAndGC(env->Global(), foo);
1164

    
1165
  // Test IC load break point with garbage collection.
1166
  foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1167
  SetBreakPoint(foo, 0);
1168
  CallAndGC(env->Global(), foo);
1169

    
1170
  // Test IC call break point with garbage collection.
1171
  foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
1172
  SetBreakPoint(foo, 0);
1173
  CallAndGC(env->Global(), foo);
1174

    
1175
  // Test return break point with garbage collection.
1176
  foo = CompileFunction(&env, "function foo(){}", "foo");
1177
  SetBreakPoint(foo, 0);
1178
  CallAndGC(env->Global(), foo);
1179

    
1180
  v8::Debug::SetDebugEventListener(NULL);
1181
  CheckDebuggerUnloaded();
1182
}
1183

    
1184

    
1185
// Test that break points can be set using the global Debug object.
1186
TEST(BreakPointThroughJavaScript) {
1187
  break_point_hit_count = 0;
1188
  v8::HandleScope scope;
1189
  DebugLocalContext env;
1190
  env.ExposeDebug();
1191

    
1192
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1193
                                   v8::Undefined());
1194
  v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
1195
  v8::Script::Compile(v8::String::New("function foo(){bar();bar();}"))->Run();
1196
  //                                               012345678901234567890
1197
  //                                                         1         2
1198
  // Break points are set at position 3 and 9
1199
  v8::Local<v8::Script> foo = v8::Script::Compile(v8::String::New("foo()"));
1200

    
1201
  // Run without breakpoints.
1202
  foo->Run();
1203
  CHECK_EQ(0, break_point_hit_count);
1204

    
1205
  // Run with one breakpoint
1206
  int bp1 = SetBreakPointFromJS("foo", 0, 3);
1207
  foo->Run();
1208
  CHECK_EQ(1, break_point_hit_count);
1209
  foo->Run();
1210
  CHECK_EQ(2, break_point_hit_count);
1211

    
1212
  // Run with two breakpoints
1213
  int bp2 = SetBreakPointFromJS("foo", 0, 9);
1214
  foo->Run();
1215
  CHECK_EQ(4, break_point_hit_count);
1216
  foo->Run();
1217
  CHECK_EQ(6, break_point_hit_count);
1218

    
1219
  // Run with one breakpoint
1220
  ClearBreakPointFromJS(bp2);
1221
  foo->Run();
1222
  CHECK_EQ(7, break_point_hit_count);
1223
  foo->Run();
1224
  CHECK_EQ(8, break_point_hit_count);
1225

    
1226
  // Run without breakpoints.
1227
  ClearBreakPointFromJS(bp1);
1228
  foo->Run();
1229
  CHECK_EQ(8, break_point_hit_count);
1230

    
1231
  v8::Debug::SetDebugEventListener(NULL);
1232
  CheckDebuggerUnloaded();
1233

    
1234
  // Make sure that the break point numbers are consecutive.
1235
  CHECK_EQ(1, bp1);
1236
  CHECK_EQ(2, bp2);
1237
}
1238

    
1239

    
1240
// Test that break points on scripts identified by name can be set using the
1241
// global Debug object.
1242
TEST(ScriptBreakPointByNameThroughJavaScript) {
1243
  break_point_hit_count = 0;
1244
  v8::HandleScope scope;
1245
  DebugLocalContext env;
1246
  env.ExposeDebug();
1247

    
1248
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1249
                                   v8::Undefined());
1250

    
1251
  v8::Local<v8::String> script = v8::String::New(
1252
    "function f() {\n"
1253
    "  function h() {\n"
1254
    "    a = 0;  // line 2\n"
1255
    "  }\n"
1256
    "  b = 1;  // line 4\n"
1257
    "  return h();\n"
1258
    "}\n"
1259
    "\n"
1260
    "function g() {\n"
1261
    "  function h() {\n"
1262
    "    a = 0;\n"
1263
    "  }\n"
1264
    "  b = 2;  // line 12\n"
1265
    "  h();\n"
1266
    "  b = 3;  // line 14\n"
1267
    "  f();    // line 15\n"
1268
    "}");
1269

    
1270
  // Compile the script and get the two functions.
1271
  v8::ScriptOrigin origin =
1272
      v8::ScriptOrigin(v8::String::New("test"));
1273
  v8::Script::Compile(script, &origin)->Run();
1274
  v8::Local<v8::Function> f =
1275
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1276
  v8::Local<v8::Function> g =
1277
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
1278

    
1279
  // Call f and g without break points.
1280
  break_point_hit_count = 0;
1281
  f->Call(env->Global(), 0, NULL);
1282
  CHECK_EQ(0, break_point_hit_count);
1283
  g->Call(env->Global(), 0, NULL);
1284
  CHECK_EQ(0, break_point_hit_count);
1285

    
1286
  // Call f and g with break point on line 12.
1287
  int sbp1 = SetScriptBreakPointByNameFromJS("test", 12, 0);
1288
  break_point_hit_count = 0;
1289
  f->Call(env->Global(), 0, NULL);
1290
  CHECK_EQ(0, break_point_hit_count);
1291
  g->Call(env->Global(), 0, NULL);
1292
  CHECK_EQ(1, break_point_hit_count);
1293

    
1294
  // Remove the break point again.
1295
  break_point_hit_count = 0;
1296
  ClearBreakPointFromJS(sbp1);
1297
  f->Call(env->Global(), 0, NULL);
1298
  CHECK_EQ(0, break_point_hit_count);
1299
  g->Call(env->Global(), 0, NULL);
1300
  CHECK_EQ(0, break_point_hit_count);
1301

    
1302
  // Call f and g with break point on line 2.
1303
  int sbp2 = SetScriptBreakPointByNameFromJS("test", 2, 0);
1304
  break_point_hit_count = 0;
1305
  f->Call(env->Global(), 0, NULL);
1306
  CHECK_EQ(1, break_point_hit_count);
1307
  g->Call(env->Global(), 0, NULL);
1308
  CHECK_EQ(2, break_point_hit_count);
1309

    
1310
  // Call f and g with break point on line 2, 4, 12, 14 and 15.
1311
  int sbp3 = SetScriptBreakPointByNameFromJS("test", 4, 0);
1312
  int sbp4 = SetScriptBreakPointByNameFromJS("test", 12, 0);
1313
  int sbp5 = SetScriptBreakPointByNameFromJS("test", 14, 0);
1314
  int sbp6 = SetScriptBreakPointByNameFromJS("test", 15, 0);
1315
  break_point_hit_count = 0;
1316
  f->Call(env->Global(), 0, NULL);
1317
  CHECK_EQ(2, break_point_hit_count);
1318
  g->Call(env->Global(), 0, NULL);
1319
  CHECK_EQ(7, break_point_hit_count);
1320

    
1321
  // Remove all the break points again.
1322
  break_point_hit_count = 0;
1323
  ClearBreakPointFromJS(sbp2);
1324
  ClearBreakPointFromJS(sbp3);
1325
  ClearBreakPointFromJS(sbp4);
1326
  ClearBreakPointFromJS(sbp5);
1327
  ClearBreakPointFromJS(sbp6);
1328
  f->Call(env->Global(), 0, NULL);
1329
  CHECK_EQ(0, break_point_hit_count);
1330
  g->Call(env->Global(), 0, NULL);
1331
  CHECK_EQ(0, break_point_hit_count);
1332

    
1333
  v8::Debug::SetDebugEventListener(NULL);
1334
  CheckDebuggerUnloaded();
1335

    
1336
  // Make sure that the break point numbers are consecutive.
1337
  CHECK_EQ(1, sbp1);
1338
  CHECK_EQ(2, sbp2);
1339
  CHECK_EQ(3, sbp3);
1340
  CHECK_EQ(4, sbp4);
1341
  CHECK_EQ(5, sbp5);
1342
  CHECK_EQ(6, sbp6);
1343
}
1344

    
1345

    
1346
TEST(ScriptBreakPointByIdThroughJavaScript) {
1347
  break_point_hit_count = 0;
1348
  v8::HandleScope scope;
1349
  DebugLocalContext env;
1350
  env.ExposeDebug();
1351

    
1352
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1353
                                   v8::Undefined());
1354

    
1355
  v8::Local<v8::String> source = v8::String::New(
1356
    "function f() {\n"
1357
    "  function h() {\n"
1358
    "    a = 0;  // line 2\n"
1359
    "  }\n"
1360
    "  b = 1;  // line 4\n"
1361
    "  return h();\n"
1362
    "}\n"
1363
    "\n"
1364
    "function g() {\n"
1365
    "  function h() {\n"
1366
    "    a = 0;\n"
1367
    "  }\n"
1368
    "  b = 2;  // line 12\n"
1369
    "  h();\n"
1370
    "  b = 3;  // line 14\n"
1371
    "  f();    // line 15\n"
1372
    "}");
1373

    
1374
  // Compile the script and get the two functions.
1375
  v8::ScriptOrigin origin =
1376
      v8::ScriptOrigin(v8::String::New("test"));
1377
  v8::Local<v8::Script> script = v8::Script::Compile(source, &origin);
1378
  script->Run();
1379
  v8::Local<v8::Function> f =
1380
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1381
  v8::Local<v8::Function> g =
1382
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
1383

    
1384
  // Get the script id knowing that internally it is a 32 integer.
1385
  uint32_t script_id = script->Id()->Uint32Value();
1386

    
1387
  // Call f and g without break points.
1388
  break_point_hit_count = 0;
1389
  f->Call(env->Global(), 0, NULL);
1390
  CHECK_EQ(0, break_point_hit_count);
1391
  g->Call(env->Global(), 0, NULL);
1392
  CHECK_EQ(0, break_point_hit_count);
1393

    
1394
  // Call f and g with break point on line 12.
1395
  int sbp1 = SetScriptBreakPointByIdFromJS(script_id, 12, 0);
1396
  break_point_hit_count = 0;
1397
  f->Call(env->Global(), 0, NULL);
1398
  CHECK_EQ(0, break_point_hit_count);
1399
  g->Call(env->Global(), 0, NULL);
1400
  CHECK_EQ(1, break_point_hit_count);
1401

    
1402
  // Remove the break point again.
1403
  break_point_hit_count = 0;
1404
  ClearBreakPointFromJS(sbp1);
1405
  f->Call(env->Global(), 0, NULL);
1406
  CHECK_EQ(0, break_point_hit_count);
1407
  g->Call(env->Global(), 0, NULL);
1408
  CHECK_EQ(0, break_point_hit_count);
1409

    
1410
  // Call f and g with break point on line 2.
1411
  int sbp2 = SetScriptBreakPointByIdFromJS(script_id, 2, 0);
1412
  break_point_hit_count = 0;
1413
  f->Call(env->Global(), 0, NULL);
1414
  CHECK_EQ(1, break_point_hit_count);
1415
  g->Call(env->Global(), 0, NULL);
1416
  CHECK_EQ(2, break_point_hit_count);
1417

    
1418
  // Call f and g with break point on line 2, 4, 12, 14 and 15.
1419
  int sbp3 = SetScriptBreakPointByIdFromJS(script_id, 4, 0);
1420
  int sbp4 = SetScriptBreakPointByIdFromJS(script_id, 12, 0);
1421
  int sbp5 = SetScriptBreakPointByIdFromJS(script_id, 14, 0);
1422
  int sbp6 = SetScriptBreakPointByIdFromJS(script_id, 15, 0);
1423
  break_point_hit_count = 0;
1424
  f->Call(env->Global(), 0, NULL);
1425
  CHECK_EQ(2, break_point_hit_count);
1426
  g->Call(env->Global(), 0, NULL);
1427
  CHECK_EQ(7, break_point_hit_count);
1428

    
1429
  // Remove all the break points again.
1430
  break_point_hit_count = 0;
1431
  ClearBreakPointFromJS(sbp2);
1432
  ClearBreakPointFromJS(sbp3);
1433
  ClearBreakPointFromJS(sbp4);
1434
  ClearBreakPointFromJS(sbp5);
1435
  ClearBreakPointFromJS(sbp6);
1436
  f->Call(env->Global(), 0, NULL);
1437
  CHECK_EQ(0, break_point_hit_count);
1438
  g->Call(env->Global(), 0, NULL);
1439
  CHECK_EQ(0, break_point_hit_count);
1440

    
1441
  v8::Debug::SetDebugEventListener(NULL);
1442
  CheckDebuggerUnloaded();
1443

    
1444
  // Make sure that the break point numbers are consecutive.
1445
  CHECK_EQ(1, sbp1);
1446
  CHECK_EQ(2, sbp2);
1447
  CHECK_EQ(3, sbp3);
1448
  CHECK_EQ(4, sbp4);
1449
  CHECK_EQ(5, sbp5);
1450
  CHECK_EQ(6, sbp6);
1451
}
1452

    
1453

    
1454
// Test conditional script break points.
1455
TEST(EnableDisableScriptBreakPoint) {
1456
  break_point_hit_count = 0;
1457
  v8::HandleScope scope;
1458
  DebugLocalContext env;
1459
  env.ExposeDebug();
1460

    
1461
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1462
                                   v8::Undefined());
1463

    
1464
  v8::Local<v8::String> script = v8::String::New(
1465
    "function f() {\n"
1466
    "  a = 0;  // line 1\n"
1467
    "};");
1468

    
1469
  // Compile the script and get function f.
1470
  v8::ScriptOrigin origin =
1471
      v8::ScriptOrigin(v8::String::New("test"));
1472
  v8::Script::Compile(script, &origin)->Run();
1473
  v8::Local<v8::Function> f =
1474
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1475

    
1476
  // Set script break point on line 1 (in function f).
1477
  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
1478

    
1479
  // Call f while enabeling and disabling the script break point.
1480
  break_point_hit_count = 0;
1481
  f->Call(env->Global(), 0, NULL);
1482
  CHECK_EQ(1, break_point_hit_count);
1483

    
1484
  DisableScriptBreakPointFromJS(sbp);
1485
  f->Call(env->Global(), 0, NULL);
1486
  CHECK_EQ(1, break_point_hit_count);
1487

    
1488
  EnableScriptBreakPointFromJS(sbp);
1489
  f->Call(env->Global(), 0, NULL);
1490
  CHECK_EQ(2, break_point_hit_count);
1491

    
1492
  DisableScriptBreakPointFromJS(sbp);
1493
  f->Call(env->Global(), 0, NULL);
1494
  CHECK_EQ(2, break_point_hit_count);
1495

    
1496
  // Reload the script and get f again checking that the disabeling survives.
1497
  v8::Script::Compile(script, &origin)->Run();
1498
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1499
  f->Call(env->Global(), 0, NULL);
1500
  CHECK_EQ(2, break_point_hit_count);
1501

    
1502
  EnableScriptBreakPointFromJS(sbp);
1503
  f->Call(env->Global(), 0, NULL);
1504
  CHECK_EQ(3, break_point_hit_count);
1505

    
1506
  v8::Debug::SetDebugEventListener(NULL);
1507
  CheckDebuggerUnloaded();
1508
}
1509

    
1510

    
1511
// Test conditional script break points.
1512
TEST(ConditionalScriptBreakPoint) {
1513
  break_point_hit_count = 0;
1514
  v8::HandleScope scope;
1515
  DebugLocalContext env;
1516
  env.ExposeDebug();
1517

    
1518
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1519
                                   v8::Undefined());
1520

    
1521
  v8::Local<v8::String> script = v8::String::New(
1522
    "count = 0;\n"
1523
    "function f() {\n"
1524
    "  g(count++);  // line 2\n"
1525
    "};\n"
1526
    "function g(x) {\n"
1527
    "  var a=x;  // line 5\n"
1528
    "};");
1529

    
1530
  // Compile the script and get function f.
1531
  v8::ScriptOrigin origin =
1532
      v8::ScriptOrigin(v8::String::New("test"));
1533
  v8::Script::Compile(script, &origin)->Run();
1534
  v8::Local<v8::Function> f =
1535
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1536

    
1537
  // Set script break point on line 5 (in function g).
1538
  int sbp1 = SetScriptBreakPointByNameFromJS("test", 5, 0);
1539

    
1540
  // Call f with different conditions on the script break point.
1541
  break_point_hit_count = 0;
1542
  ChangeScriptBreakPointConditionFromJS(sbp1, "false");
1543
  f->Call(env->Global(), 0, NULL);
1544
  CHECK_EQ(0, break_point_hit_count);
1545

    
1546
  ChangeScriptBreakPointConditionFromJS(sbp1, "true");
1547
  break_point_hit_count = 0;
1548
  f->Call(env->Global(), 0, NULL);
1549
  CHECK_EQ(1, break_point_hit_count);
1550

    
1551
  ChangeScriptBreakPointConditionFromJS(sbp1, "a % 2 == 0");
1552
  break_point_hit_count = 0;
1553
  for (int i = 0; i < 10; i++) {
1554
    f->Call(env->Global(), 0, NULL);
1555
  }
1556
  CHECK_EQ(5, break_point_hit_count);
1557

    
1558
  // Reload the script and get f again checking that the condition survives.
1559
  v8::Script::Compile(script, &origin)->Run();
1560
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1561

    
1562
  break_point_hit_count = 0;
1563
  for (int i = 0; i < 10; i++) {
1564
    f->Call(env->Global(), 0, NULL);
1565
  }
1566
  CHECK_EQ(5, break_point_hit_count);
1567

    
1568
  v8::Debug::SetDebugEventListener(NULL);
1569
  CheckDebuggerUnloaded();
1570
}
1571

    
1572

    
1573
// Test ignore count on script break points.
1574
TEST(ScriptBreakPointIgnoreCount) {
1575
  break_point_hit_count = 0;
1576
  v8::HandleScope scope;
1577
  DebugLocalContext env;
1578
  env.ExposeDebug();
1579

    
1580
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1581
                                   v8::Undefined());
1582

    
1583
  v8::Local<v8::String> script = v8::String::New(
1584
    "function f() {\n"
1585
    "  a = 0;  // line 1\n"
1586
    "};");
1587

    
1588
  // Compile the script and get function f.
1589
  v8::ScriptOrigin origin =
1590
      v8::ScriptOrigin(v8::String::New("test"));
1591
  v8::Script::Compile(script, &origin)->Run();
1592
  v8::Local<v8::Function> f =
1593
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1594

    
1595
  // Set script break point on line 1 (in function f).
1596
  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
1597

    
1598
  // Call f with different ignores on the script break point.
1599
  break_point_hit_count = 0;
1600
  ChangeScriptBreakPointIgnoreCountFromJS(sbp, 1);
1601
  f->Call(env->Global(), 0, NULL);
1602
  CHECK_EQ(0, break_point_hit_count);
1603
  f->Call(env->Global(), 0, NULL);
1604
  CHECK_EQ(1, break_point_hit_count);
1605

    
1606
  ChangeScriptBreakPointIgnoreCountFromJS(sbp, 5);
1607
  break_point_hit_count = 0;
1608
  for (int i = 0; i < 10; i++) {
1609
    f->Call(env->Global(), 0, NULL);
1610
  }
1611
  CHECK_EQ(5, break_point_hit_count);
1612

    
1613
  // Reload the script and get f again checking that the ignore survives.
1614
  v8::Script::Compile(script, &origin)->Run();
1615
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1616

    
1617
  break_point_hit_count = 0;
1618
  for (int i = 0; i < 10; i++) {
1619
    f->Call(env->Global(), 0, NULL);
1620
  }
1621
  CHECK_EQ(5, break_point_hit_count);
1622

    
1623
  v8::Debug::SetDebugEventListener(NULL);
1624
  CheckDebuggerUnloaded();
1625
}
1626

    
1627

    
1628
// Test that script break points survive when a script is reloaded.
1629
TEST(ScriptBreakPointReload) {
1630
  break_point_hit_count = 0;
1631
  v8::HandleScope scope;
1632
  DebugLocalContext env;
1633
  env.ExposeDebug();
1634

    
1635
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1636
                                   v8::Undefined());
1637

    
1638
  v8::Local<v8::Function> f;
1639
  v8::Local<v8::String> script = v8::String::New(
1640
    "function f() {\n"
1641
    "  function h() {\n"
1642
    "    a = 0;  // line 2\n"
1643
    "  }\n"
1644
    "  b = 1;  // line 4\n"
1645
    "  return h();\n"
1646
    "}");
1647

    
1648
  v8::ScriptOrigin origin_1 = v8::ScriptOrigin(v8::String::New("1"));
1649
  v8::ScriptOrigin origin_2 = v8::ScriptOrigin(v8::String::New("2"));
1650

    
1651
  // Set a script break point before the script is loaded.
1652
  SetScriptBreakPointByNameFromJS("1", 2, 0);
1653

    
1654
  // Compile the script and get the function.
1655
  v8::Script::Compile(script, &origin_1)->Run();
1656
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1657

    
1658
  // Call f and check that the script break point is active.
1659
  break_point_hit_count = 0;
1660
  f->Call(env->Global(), 0, NULL);
1661
  CHECK_EQ(1, break_point_hit_count);
1662

    
1663
  // Compile the script again with a different script data and get the
1664
  // function.
1665
  v8::Script::Compile(script, &origin_2)->Run();
1666
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1667

    
1668
  // Call f and check that no break points are set.
1669
  break_point_hit_count = 0;
1670
  f->Call(env->Global(), 0, NULL);
1671
  CHECK_EQ(0, break_point_hit_count);
1672

    
1673
  // Compile the script again and get the function.
1674
  v8::Script::Compile(script, &origin_1)->Run();
1675
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1676

    
1677
  // Call f and check that the script break point is active.
1678
  break_point_hit_count = 0;
1679
  f->Call(env->Global(), 0, NULL);
1680
  CHECK_EQ(1, break_point_hit_count);
1681

    
1682
  v8::Debug::SetDebugEventListener(NULL);
1683
  CheckDebuggerUnloaded();
1684
}
1685

    
1686

    
1687
// Test when several scripts has the same script data
1688
TEST(ScriptBreakPointMultiple) {
1689
  break_point_hit_count = 0;
1690
  v8::HandleScope scope;
1691
  DebugLocalContext env;
1692
  env.ExposeDebug();
1693

    
1694
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1695
                                   v8::Undefined());
1696

    
1697
  v8::Local<v8::Function> f;
1698
  v8::Local<v8::String> script_f = v8::String::New(
1699
    "function f() {\n"
1700
    "  a = 0;  // line 1\n"
1701
    "}");
1702

    
1703
  v8::Local<v8::Function> g;
1704
  v8::Local<v8::String> script_g = v8::String::New(
1705
    "function g() {\n"
1706
    "  b = 0;  // line 1\n"
1707
    "}");
1708

    
1709
  v8::ScriptOrigin origin =
1710
      v8::ScriptOrigin(v8::String::New("test"));
1711

    
1712
  // Set a script break point before the scripts are loaded.
1713
  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
1714

    
1715
  // Compile the scripts with same script data and get the functions.
1716
  v8::Script::Compile(script_f, &origin)->Run();
1717
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1718
  v8::Script::Compile(script_g, &origin)->Run();
1719
  g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
1720

    
1721
  // Call f and g and check that the script break point is active.
1722
  break_point_hit_count = 0;
1723
  f->Call(env->Global(), 0, NULL);
1724
  CHECK_EQ(1, break_point_hit_count);
1725
  g->Call(env->Global(), 0, NULL);
1726
  CHECK_EQ(2, break_point_hit_count);
1727

    
1728
  // Clear the script break point.
1729
  ClearBreakPointFromJS(sbp);
1730

    
1731
  // Call f and g and check that the script break point is no longer active.
1732
  break_point_hit_count = 0;
1733
  f->Call(env->Global(), 0, NULL);
1734
  CHECK_EQ(0, break_point_hit_count);
1735
  g->Call(env->Global(), 0, NULL);
1736
  CHECK_EQ(0, break_point_hit_count);
1737

    
1738
  // Set script break point with the scripts loaded.
1739
  sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
1740

    
1741
  // Call f and g and check that the script break point is active.
1742
  break_point_hit_count = 0;
1743
  f->Call(env->Global(), 0, NULL);
1744
  CHECK_EQ(1, break_point_hit_count);
1745
  g->Call(env->Global(), 0, NULL);
1746
  CHECK_EQ(2, break_point_hit_count);
1747

    
1748
  v8::Debug::SetDebugEventListener(NULL);
1749
  CheckDebuggerUnloaded();
1750
}
1751

    
1752

    
1753
// Test the script origin which has both name and line offset.
1754
TEST(ScriptBreakPointLineOffset) {
1755
  break_point_hit_count = 0;
1756
  v8::HandleScope scope;
1757
  DebugLocalContext env;
1758
  env.ExposeDebug();
1759

    
1760
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1761
                                   v8::Undefined());
1762

    
1763
  v8::Local<v8::Function> f;
1764
  v8::Local<v8::String> script = v8::String::New(
1765
    "function f() {\n"
1766
    "  a = 0;  // line 8 as this script has line offset 7\n"
1767
    "  b = 0;  // line 9 as this script has line offset 7\n"
1768
    "}");
1769

    
1770
  // Create script origin both name and line offset.
1771
  v8::ScriptOrigin origin(v8::String::New("test.html"),
1772
                          v8::Integer::New(7));
1773

    
1774
  // Set two script break points before the script is loaded.
1775
  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 8, 0);
1776
  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 9, 0);
1777

    
1778
  // Compile the script and get the function.
1779
  v8::Script::Compile(script, &origin)->Run();
1780
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1781

    
1782
  // Call f and check that the script break point is active.
1783
  break_point_hit_count = 0;
1784
  f->Call(env->Global(), 0, NULL);
1785
  CHECK_EQ(2, break_point_hit_count);
1786

    
1787
  // Clear the script break points.
1788
  ClearBreakPointFromJS(sbp1);
1789
  ClearBreakPointFromJS(sbp2);
1790

    
1791
  // Call f and check that no script break points are active.
1792
  break_point_hit_count = 0;
1793
  f->Call(env->Global(), 0, NULL);
1794
  CHECK_EQ(0, break_point_hit_count);
1795

    
1796
  // Set a script break point with the script loaded.
1797
  sbp1 = SetScriptBreakPointByNameFromJS("test.html", 9, 0);
1798

    
1799
  // Call f and check that the script break point is active.
1800
  break_point_hit_count = 0;
1801
  f->Call(env->Global(), 0, NULL);
1802
  CHECK_EQ(1, break_point_hit_count);
1803

    
1804
  v8::Debug::SetDebugEventListener(NULL);
1805
  CheckDebuggerUnloaded();
1806
}
1807

    
1808

    
1809
// Test script break points set on lines.
1810
TEST(ScriptBreakPointLine) {
1811
  v8::HandleScope scope;
1812
  DebugLocalContext env;
1813
  env.ExposeDebug();
1814

    
1815
  // Create a function for checking the function when hitting a break point.
1816
  frame_function_name = CompileFunction(&env,
1817
                                        frame_function_name_source,
1818
                                        "frame_function_name");
1819

    
1820
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1821
                                   v8::Undefined());
1822

    
1823
  v8::Local<v8::Function> f;
1824
  v8::Local<v8::Function> g;
1825
  v8::Local<v8::String> script = v8::String::New(
1826
    "a = 0                      // line 0\n"
1827
    "function f() {\n"
1828
    "  a = 1;                   // line 2\n"
1829
    "}\n"
1830
    " a = 2;                    // line 4\n"
1831
    "  /* xx */ function g() {  // line 5\n"
1832
    "    function h() {         // line 6\n"
1833
    "      a = 3;               // line 7\n"
1834
    "    }\n"
1835
    "    h();                   // line 9\n"
1836
    "    a = 4;                 // line 10\n"
1837
    "  }\n"
1838
    " a=5;                      // line 12");
1839

    
1840
  // Set a couple script break point before the script is loaded.
1841
  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 0, -1);
1842
  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 1, -1);
1843
  int sbp3 = SetScriptBreakPointByNameFromJS("test.html", 5, -1);
1844

    
1845
  // Compile the script and get the function.
1846
  break_point_hit_count = 0;
1847
  v8::ScriptOrigin origin(v8::String::New("test.html"), v8::Integer::New(0));
1848
  v8::Script::Compile(script, &origin)->Run();
1849
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1850
  g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
1851

    
1852
  // Chesk that a break point was hit when the script was run.
1853
  CHECK_EQ(1, break_point_hit_count);
1854
  CHECK_EQ(0, strlen(last_function_hit));
1855

    
1856
  // Call f and check that the script break point.
1857
  f->Call(env->Global(), 0, NULL);
1858
  CHECK_EQ(2, break_point_hit_count);
1859
  CHECK_EQ("f", last_function_hit);
1860

    
1861
  // Call g and check that the script break point.
1862
  g->Call(env->Global(), 0, NULL);
1863
  CHECK_EQ(3, break_point_hit_count);
1864
  CHECK_EQ("g", last_function_hit);
1865

    
1866
  // Clear the script break point on g and set one on h.
1867
  ClearBreakPointFromJS(sbp3);
1868
  int sbp4 = SetScriptBreakPointByNameFromJS("test.html", 6, -1);
1869

    
1870
  // Call g and check that the script break point in h is hit.
1871
  g->Call(env->Global(), 0, NULL);
1872
  CHECK_EQ(4, break_point_hit_count);
1873
  CHECK_EQ("h", last_function_hit);
1874

    
1875
  // Clear break points in f and h. Set a new one in the script between
1876
  // functions f and g and test that there is no break points in f and g any
1877
  // more.
1878
  ClearBreakPointFromJS(sbp2);
1879
  ClearBreakPointFromJS(sbp4);
1880
  int sbp5 = SetScriptBreakPointByNameFromJS("test.html", 4, -1);
1881
  break_point_hit_count = 0;
1882
  f->Call(env->Global(), 0, NULL);
1883
  g->Call(env->Global(), 0, NULL);
1884
  CHECK_EQ(0, break_point_hit_count);
1885

    
1886
  // Reload the script which should hit two break points.
1887
  break_point_hit_count = 0;
1888
  v8::Script::Compile(script, &origin)->Run();
1889
  CHECK_EQ(2, break_point_hit_count);
1890
  CHECK_EQ(0, strlen(last_function_hit));
1891

    
1892
  // Set a break point in the code after the last function decleration.
1893
  int sbp6 = SetScriptBreakPointByNameFromJS("test.html", 12, -1);
1894

    
1895
  // Reload the script which should hit three break points.
1896
  break_point_hit_count = 0;
1897
  v8::Script::Compile(script, &origin)->Run();
1898
  CHECK_EQ(3, break_point_hit_count);
1899
  CHECK_EQ(0, strlen(last_function_hit));
1900

    
1901
  // Clear the last break points, and reload the script which should not hit any
1902
  // break points.
1903
  ClearBreakPointFromJS(sbp1);
1904
  ClearBreakPointFromJS(sbp5);
1905
  ClearBreakPointFromJS(sbp6);
1906
  break_point_hit_count = 0;
1907
  v8::Script::Compile(script, &origin)->Run();
1908
  CHECK_EQ(0, break_point_hit_count);
1909

    
1910
  v8::Debug::SetDebugEventListener(NULL);
1911
  CheckDebuggerUnloaded();
1912
}
1913

    
1914

    
1915
// Test that it is possible to remove the last break point for a function
1916
// inside the break handling of that break point.
1917
TEST(RemoveBreakPointInBreak) {
1918
  v8::HandleScope scope;
1919
  DebugLocalContext env;
1920

    
1921
  v8::Local<v8::Function> foo =
1922
      CompileFunction(&env, "function foo(){a=1;}", "foo");
1923
  debug_event_remove_break_point = SetBreakPoint(foo, 0);
1924

    
1925
  // Register the debug event listener pasing the function
1926
  v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo);
1927

    
1928
  break_point_hit_count = 0;
1929
  foo->Call(env->Global(), 0, NULL);
1930
  CHECK_EQ(1, break_point_hit_count);
1931

    
1932
  break_point_hit_count = 0;
1933
  foo->Call(env->Global(), 0, NULL);
1934
  CHECK_EQ(0, break_point_hit_count);
1935

    
1936
  v8::Debug::SetDebugEventListener(NULL);
1937
  CheckDebuggerUnloaded();
1938
}
1939

    
1940

    
1941
// Test that the debugger statement causes a break.
1942
TEST(DebuggerStatement) {
1943
  break_point_hit_count = 0;
1944
  v8::HandleScope scope;
1945
  DebugLocalContext env;
1946
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
1947
                                   v8::Undefined());
1948
  v8::Script::Compile(v8::String::New("function bar(){debugger}"))->Run();
1949
  v8::Script::Compile(v8::String::New(
1950
      "function foo(){debugger;debugger;}"))->Run();
1951
  v8::Local<v8::Function> foo =
1952
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1953
  v8::Local<v8::Function> bar =
1954
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("bar")));
1955

    
1956
  // Run function with debugger statement
1957
  bar->Call(env->Global(), 0, NULL);
1958
  CHECK_EQ(1, break_point_hit_count);
1959

    
1960
  // Run function with two debugger statement
1961
  foo->Call(env->Global(), 0, NULL);
1962
  CHECK_EQ(3, break_point_hit_count);
1963

    
1964
  v8::Debug::SetDebugEventListener(NULL);
1965
  CheckDebuggerUnloaded();
1966
}
1967

    
1968

    
1969
// Thest that the evaluation of expressions when a break point is hit generates
1970
// the correct results.
1971
TEST(DebugEvaluate) {
1972
  v8::HandleScope scope;
1973
  DebugLocalContext env;
1974
  env.ExposeDebug();
1975

    
1976
  // Create a function for checking the evaluation when hitting a break point.
1977
  evaluate_check_function = CompileFunction(&env,
1978
                                            evaluate_check_source,
1979
                                            "evaluate_check");
1980
  // Register the debug event listener
1981
  v8::Debug::SetDebugEventListener(DebugEventEvaluate);
1982

    
1983
  // Different expected vaules of x and a when in a break point (u = undefined,
1984
  // d = Hello, world!).
1985
  struct EvaluateCheck checks_uu[] = {
1986
    {"x", v8::Undefined()},
1987
    {"a", v8::Undefined()},
1988
    {NULL, v8::Handle<v8::Value>()}
1989
  };
1990
  struct EvaluateCheck checks_hu[] = {
1991
    {"x", v8::String::New("Hello, world!")},
1992
    {"a", v8::Undefined()},
1993
    {NULL, v8::Handle<v8::Value>()}
1994
  };
1995
  struct EvaluateCheck checks_hh[] = {
1996
    {"x", v8::String::New("Hello, world!")},
1997
    {"a", v8::String::New("Hello, world!")},
1998
    {NULL, v8::Handle<v8::Value>()}
1999
  };
2000

    
2001
  // Simple test function. The "y=0" is in the function foo to provide a break
2002
  // location. For "y=0" the "y" is at position 15 in the barbar function
2003
  // therefore setting breakpoint at position 15 will break at "y=0" and
2004
  // setting it higher will break after.
2005
  v8::Local<v8::Function> foo = CompileFunction(&env,
2006
    "function foo(x) {"
2007
    "  var a;"
2008
    "  y=0; /* To ensure break location.*/"
2009
    "  a=x;"
2010
    "}",
2011
    "foo");
2012
  const int foo_break_position = 15;
2013

    
2014
  // Arguments with one parameter "Hello, world!"
2015
  v8::Handle<v8::Value> argv_foo[1] = { v8::String::New("Hello, world!") };
2016

    
2017
  // Call foo with breakpoint set before a=x and undefined as parameter.
2018
  int bp = SetBreakPoint(foo, foo_break_position);
2019
  checks = checks_uu;
2020
  foo->Call(env->Global(), 0, NULL);
2021

    
2022
  // Call foo with breakpoint set before a=x and parameter "Hello, world!".
2023
  checks = checks_hu;
2024
  foo->Call(env->Global(), 1, argv_foo);
2025

    
2026
  // Call foo with breakpoint set after a=x and parameter "Hello, world!".
2027
  ClearBreakPoint(bp);
2028
  SetBreakPoint(foo, foo_break_position + 1);
2029
  checks = checks_hh;
2030
  foo->Call(env->Global(), 1, argv_foo);
2031

    
2032
  // Test function with an inner function. The "y=0" is in function barbar
2033
  // to provide a break location. For "y=0" the "y" is at position 8 in the
2034
  // barbar function therefore setting breakpoint at position 8 will break at
2035
  // "y=0" and setting it higher will break after.
2036
  v8::Local<v8::Function> bar = CompileFunction(&env,
2037
    "y = 0;"
2038
    "x = 'Goodbye, world!';"
2039
    "function bar(x, b) {"
2040
    "  var a;"
2041
    "  function barbar() {"
2042
    "    y=0; /* To ensure break location.*/"
2043
    "    a=x;"
2044
    "  };"
2045
    "  debug.Debug.clearAllBreakPoints();"
2046
    "  barbar();"
2047
    "  y=0;a=x;"
2048
    "}",
2049
    "bar");
2050
  const int barbar_break_position = 8;
2051

    
2052
  // Call bar setting breakpoint before a=x in barbar and undefined as
2053
  // parameter.
2054
  checks = checks_uu;
2055
  v8::Handle<v8::Value> argv_bar_1[2] = {
2056
    v8::Undefined(),
2057
    v8::Number::New(barbar_break_position)
2058
  };
2059
  bar->Call(env->Global(), 2, argv_bar_1);
2060

    
2061
  // Call bar setting breakpoint before a=x in barbar and parameter
2062
  // "Hello, world!".
2063
  checks = checks_hu;
2064
  v8::Handle<v8::Value> argv_bar_2[2] = {
2065
    v8::String::New("Hello, world!"),
2066
    v8::Number::New(barbar_break_position)
2067
  };
2068
  bar->Call(env->Global(), 2, argv_bar_2);
2069

    
2070
  // Call bar setting breakpoint after a=x in barbar and parameter
2071
  // "Hello, world!".
2072
  checks = checks_hh;
2073
  v8::Handle<v8::Value> argv_bar_3[2] = {
2074
    v8::String::New("Hello, world!"),
2075
    v8::Number::New(barbar_break_position + 1)
2076
  };
2077
  bar->Call(env->Global(), 2, argv_bar_3);
2078

    
2079
  v8::Debug::SetDebugEventListener(NULL);
2080
  CheckDebuggerUnloaded();
2081
}
2082

    
2083

    
2084
// Simple test of the stepping mechanism using only store ICs.
2085
TEST(DebugStepLinear) {
2086
  v8::HandleScope scope;
2087
  DebugLocalContext env;
2088

    
2089
  // Create a function for testing stepping.
2090
  v8::Local<v8::Function> foo = CompileFunction(&env,
2091
                                                "function foo(){a=1;b=1;c=1;}",
2092
                                                "foo");
2093
  SetBreakPoint(foo, 3);
2094

    
2095
  // Register a debug event listener which steps and counts.
2096
  v8::Debug::SetDebugEventListener(DebugEventStep);
2097

    
2098
  step_action = StepIn;
2099
  break_point_hit_count = 0;
2100
  foo->Call(env->Global(), 0, NULL);
2101

    
2102
  // With stepping all break locations are hit.
2103
  CHECK_EQ(4, break_point_hit_count);
2104

    
2105
  v8::Debug::SetDebugEventListener(NULL);
2106
  CheckDebuggerUnloaded();
2107

    
2108
  // Register a debug event listener which just counts.
2109
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2110

    
2111
  SetBreakPoint(foo, 3);
2112
  break_point_hit_count = 0;
2113
  foo->Call(env->Global(), 0, NULL);
2114

    
2115
  // Without stepping only active break points are hit.
2116
  CHECK_EQ(1, break_point_hit_count);
2117

    
2118
  v8::Debug::SetDebugEventListener(NULL);
2119
  CheckDebuggerUnloaded();
2120
}
2121

    
2122

    
2123
// Test the stepping mechanism with different ICs.
2124
TEST(DebugStepLinearMixedICs) {
2125
  v8::HandleScope scope;
2126
  DebugLocalContext env;
2127

    
2128
  // Create a function for testing stepping.
2129
  v8::Local<v8::Function> foo = CompileFunction(&env,
2130
      "function bar() {};"
2131
      "function foo() {"
2132
      "  var x;"
2133
      "  var index='name';"
2134
      "  var y = {};"
2135
      "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
2136
  SetBreakPoint(foo, 0);
2137

    
2138
  // Register a debug event listener which steps and counts.
2139
  v8::Debug::SetDebugEventListener(DebugEventStep);
2140

    
2141
  step_action = StepIn;
2142
  break_point_hit_count = 0;
2143
  foo->Call(env->Global(), 0, NULL);
2144

    
2145
  // With stepping all break locations are hit. For ARM the keyed load/store
2146
  // is not hit as they are not implemented as ICs.
2147
#if defined (__arm__) || defined(__thumb__)
2148
  CHECK_EQ(6, break_point_hit_count);
2149
#else
2150
  CHECK_EQ(8, break_point_hit_count);
2151
#endif
2152

    
2153
  v8::Debug::SetDebugEventListener(NULL);
2154
  CheckDebuggerUnloaded();
2155

    
2156
  // Register a debug event listener which just counts.
2157
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2158

    
2159
  SetBreakPoint(foo, 0);
2160
  break_point_hit_count = 0;
2161
  foo->Call(env->Global(), 0, NULL);
2162

    
2163
  // Without stepping only active break points are hit.
2164
  CHECK_EQ(1, break_point_hit_count);
2165

    
2166
  v8::Debug::SetDebugEventListener(NULL);
2167
  CheckDebuggerUnloaded();
2168
}
2169

    
2170

    
2171
TEST(DebugStepIf) {
2172
  v8::HandleScope scope;
2173
  DebugLocalContext env;
2174

    
2175
  // Register a debug event listener which steps and counts.
2176
  v8::Debug::SetDebugEventListener(DebugEventStep);
2177

    
2178
  // Create a function for testing stepping.
2179
  const int argc = 1;
2180
  const char* src = "function foo(x) { "
2181
                    "  a = 1;"
2182
                    "  if (x) {"
2183
                    "    b = 1;"
2184
                    "  } else {"
2185
                    "    c = 1;"
2186
                    "    d = 1;"
2187
                    "  }"
2188
                    "}";
2189
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
2190
  SetBreakPoint(foo, 0);
2191

    
2192
  // Stepping through the true part.
2193
  step_action = StepIn;
2194
  break_point_hit_count = 0;
2195
  v8::Handle<v8::Value> argv_true[argc] = { v8::True() };
2196
  foo->Call(env->Global(), argc, argv_true);
2197
  CHECK_EQ(3, break_point_hit_count);
2198

    
2199
  // Stepping through the false part.
2200
  step_action = StepIn;
2201
  break_point_hit_count = 0;
2202
  v8::Handle<v8::Value> argv_false[argc] = { v8::False() };
2203
  foo->Call(env->Global(), argc, argv_false);
2204
  CHECK_EQ(4, break_point_hit_count);
2205

    
2206
  // Get rid of the debug event listener.
2207
  v8::Debug::SetDebugEventListener(NULL);
2208
  CheckDebuggerUnloaded();
2209
}
2210

    
2211

    
2212
TEST(DebugStepSwitch) {
2213
  v8::HandleScope scope;
2214
  DebugLocalContext env;
2215

    
2216
  // Register a debug event listener which steps and counts.
2217
  v8::Debug::SetDebugEventListener(DebugEventStep);
2218

    
2219
  // Create a function for testing stepping.
2220
  const int argc = 1;
2221
  const char* src = "function foo(x) { "
2222
                    "  a = 1;"
2223
                    "  switch (x) {"
2224
                    "    case 1:"
2225
                    "      b = 1;"
2226
                    "    case 2:"
2227
                    "      c = 1;"
2228
                    "      break;"
2229
                    "    case 3:"
2230
                    "      d = 1;"
2231
                    "      e = 1;"
2232
                    "      break;"
2233
                    "  }"
2234
                    "}";
2235
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
2236
  SetBreakPoint(foo, 0);
2237

    
2238
  // One case with fall-through.
2239
  step_action = StepIn;
2240
  break_point_hit_count = 0;
2241
  v8::Handle<v8::Value> argv_1[argc] = { v8::Number::New(1) };
2242
  foo->Call(env->Global(), argc, argv_1);
2243
  CHECK_EQ(4, break_point_hit_count);
2244

    
2245
  // Another case.
2246
  step_action = StepIn;
2247
  break_point_hit_count = 0;
2248
  v8::Handle<v8::Value> argv_2[argc] = { v8::Number::New(2) };
2249
  foo->Call(env->Global(), argc, argv_2);
2250
  CHECK_EQ(3, break_point_hit_count);
2251

    
2252
  // Last case.
2253
  step_action = StepIn;
2254
  break_point_hit_count = 0;
2255
  v8::Handle<v8::Value> argv_3[argc] = { v8::Number::New(3) };
2256
  foo->Call(env->Global(), argc, argv_3);
2257
  CHECK_EQ(4, break_point_hit_count);
2258

    
2259
  // Get rid of the debug event listener.
2260
  v8::Debug::SetDebugEventListener(NULL);
2261
  CheckDebuggerUnloaded();
2262
}
2263

    
2264

    
2265
TEST(DebugStepFor) {
2266
  v8::HandleScope scope;
2267
  DebugLocalContext env;
2268

    
2269
  // Register a debug event listener which steps and counts.
2270
  v8::Debug::SetDebugEventListener(DebugEventStep);
2271

    
2272
  // Create a function for testing stepping.
2273
  const int argc = 1;
2274
  const char* src = "function foo(x) { "
2275
                    "  a = 1;"
2276
                    "  for (i = 0; i < x; i++) {"
2277
                    "    b = 1;"
2278
                    "  }"
2279
                    "}";
2280
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
2281
  SetBreakPoint(foo, 8);  // "a = 1;"
2282

    
2283
  // Looping 10 times.
2284
  step_action = StepIn;
2285
  break_point_hit_count = 0;
2286
  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
2287
  foo->Call(env->Global(), argc, argv_10);
2288
  CHECK_EQ(23, break_point_hit_count);
2289

    
2290
  // Looping 100 times.
2291
  step_action = StepIn;
2292
  break_point_hit_count = 0;
2293
  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
2294
  foo->Call(env->Global(), argc, argv_100);
2295
  CHECK_EQ(203, break_point_hit_count);
2296

    
2297
  // Get rid of the debug event listener.
2298
  v8::Debug::SetDebugEventListener(NULL);
2299
  CheckDebuggerUnloaded();
2300
}
2301

    
2302

    
2303
TEST(StepInOutSimple) {
2304
  v8::HandleScope scope;
2305
  DebugLocalContext env;
2306

    
2307
  // Create a function for checking the function when hitting a break point.
2308
  frame_function_name = CompileFunction(&env,
2309
                                        frame_function_name_source,
2310
                                        "frame_function_name");
2311

    
2312
  // Register a debug event listener which steps and counts.
2313
  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
2314

    
2315
  // Create functions for testing stepping.
2316
  const char* src = "function a() {b();c();}; "
2317
                    "function b() {c();}; "
2318
                    "function c() {}; ";
2319
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
2320
  SetBreakPoint(a, 0);
2321

    
2322
  // Step through invocation of a with step in.
2323
  step_action = StepIn;
2324
  break_point_hit_count = 0;
2325
  expected_step_sequence = "abcbaca";
2326
  a->Call(env->Global(), 0, NULL);
2327
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2328

    
2329
  // Step through invocation of a with step next.
2330
  step_action = StepNext;
2331
  break_point_hit_count = 0;
2332
  expected_step_sequence = "aaa";
2333
  a->Call(env->Global(), 0, NULL);
2334
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2335

    
2336
  // Step through invocation of a with step out.
2337
  step_action = StepOut;
2338
  break_point_hit_count = 0;
2339
  expected_step_sequence = "a";
2340
  a->Call(env->Global(), 0, NULL);
2341
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2342

    
2343
  // Get rid of the debug event listener.
2344
  v8::Debug::SetDebugEventListener(NULL);
2345
  CheckDebuggerUnloaded();
2346
}
2347

    
2348

    
2349
TEST(StepInOutTree) {
2350
  v8::HandleScope scope;
2351
  DebugLocalContext env;
2352

    
2353
  // Create a function for checking the function when hitting a break point.
2354
  frame_function_name = CompileFunction(&env,
2355
                                        frame_function_name_source,
2356
                                        "frame_function_name");
2357

    
2358
  // Register a debug event listener which steps and counts.
2359
  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
2360

    
2361
  // Create functions for testing stepping.
2362
  const char* src = "function a() {b(c(d()),d());c(d());d()}; "
2363
                    "function b(x,y) {c();}; "
2364
                    "function c(x) {}; "
2365
                    "function d() {}; ";
2366
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
2367
  SetBreakPoint(a, 0);
2368

    
2369
  // Step through invocation of a with step in.
2370
  step_action = StepIn;
2371
  break_point_hit_count = 0;
2372
  expected_step_sequence = "adacadabcbadacada";
2373
  a->Call(env->Global(), 0, NULL);
2374
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2375

    
2376
  // Step through invocation of a with step next.
2377
  step_action = StepNext;
2378
  break_point_hit_count = 0;
2379
  expected_step_sequence = "aaaa";
2380
  a->Call(env->Global(), 0, NULL);
2381
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2382

    
2383
  // Step through invocation of a with step out.
2384
  step_action = StepOut;
2385
  break_point_hit_count = 0;
2386
  expected_step_sequence = "a";
2387
  a->Call(env->Global(), 0, NULL);
2388
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2389

    
2390
  // Get rid of the debug event listener.
2391
  v8::Debug::SetDebugEventListener(NULL);
2392
  CheckDebuggerUnloaded(true);
2393
}
2394

    
2395

    
2396
TEST(StepInOutBranch) {
2397
  v8::HandleScope scope;
2398
  DebugLocalContext env;
2399

    
2400
  // Create a function for checking the function when hitting a break point.
2401
  frame_function_name = CompileFunction(&env,
2402
                                        frame_function_name_source,
2403
                                        "frame_function_name");
2404

    
2405
  // Register a debug event listener which steps and counts.
2406
  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
2407

    
2408
  // Create functions for testing stepping.
2409
  const char* src = "function a() {b(false);c();}; "
2410
                    "function b(x) {if(x){c();};}; "
2411
                    "function c() {}; ";
2412
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
2413
  SetBreakPoint(a, 0);
2414

    
2415
  // Step through invocation of a.
2416
  step_action = StepIn;
2417
  break_point_hit_count = 0;
2418
  expected_step_sequence = "abaca";
2419
  a->Call(env->Global(), 0, NULL);
2420
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2421

    
2422
  // Get rid of the debug event listener.
2423
  v8::Debug::SetDebugEventListener(NULL);
2424
  CheckDebuggerUnloaded();
2425
}
2426

    
2427

    
2428
// Test that step in does not step into native functions.
2429
TEST(DebugStepNatives) {
2430
  v8::HandleScope scope;
2431
  DebugLocalContext env;
2432

    
2433
  // Create a function for testing stepping.
2434
  v8::Local<v8::Function> foo = CompileFunction(
2435
      &env,
2436
      "function foo(){debugger;Math.sin(1);}",
2437
      "foo");
2438

    
2439
  // Register a debug event listener which steps and counts.
2440
  v8::Debug::SetDebugEventListener(DebugEventStep);
2441

    
2442
  step_action = StepIn;
2443
  break_point_hit_count = 0;
2444
  foo->Call(env->Global(), 0, NULL);
2445

    
2446
  // With stepping all break locations are hit.
2447
  CHECK_EQ(3, break_point_hit_count);
2448

    
2449
  v8::Debug::SetDebugEventListener(NULL);
2450
  CheckDebuggerUnloaded();
2451

    
2452
  // Register a debug event listener which just counts.
2453
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2454

    
2455
  break_point_hit_count = 0;
2456
  foo->Call(env->Global(), 0, NULL);
2457

    
2458
  // Without stepping only active break points are hit.
2459
  CHECK_EQ(1, break_point_hit_count);
2460

    
2461
  v8::Debug::SetDebugEventListener(NULL);
2462
  CheckDebuggerUnloaded();
2463
}
2464

    
2465

    
2466
// Test that step in works with function.apply.
2467
TEST(DebugStepFunctionApply) {
2468
  v8::HandleScope scope;
2469
  DebugLocalContext env;
2470

    
2471
  // Create a function for testing stepping.
2472
  v8::Local<v8::Function> foo = CompileFunction(
2473
      &env,
2474
      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
2475
      "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
2476
      "foo");
2477

    
2478
  // Register a debug event listener which steps and counts.
2479
  v8::Debug::SetDebugEventListener(DebugEventStep);
2480

    
2481
  step_action = StepIn;
2482
  break_point_hit_count = 0;
2483
  foo->Call(env->Global(), 0, NULL);
2484

    
2485
  // With stepping all break locations are hit.
2486
  CHECK_EQ(6, break_point_hit_count);
2487

    
2488
  v8::Debug::SetDebugEventListener(NULL);
2489
  CheckDebuggerUnloaded();
2490

    
2491
  // Register a debug event listener which just counts.
2492
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2493

    
2494
  break_point_hit_count = 0;
2495
  foo->Call(env->Global(), 0, NULL);
2496

    
2497
  // Without stepping only the debugger statement is hit.
2498
  CHECK_EQ(1, break_point_hit_count);
2499

    
2500
  v8::Debug::SetDebugEventListener(NULL);
2501
  CheckDebuggerUnloaded();
2502
}
2503

    
2504

    
2505
// Test that step in works with function.call.
2506
TEST(DebugStepFunctionCall) {
2507
  v8::HandleScope scope;
2508
  DebugLocalContext env;
2509

    
2510
  // Create a function for testing stepping.
2511
  v8::Local<v8::Function> foo = CompileFunction(
2512
      &env,
2513
      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
2514
      "function foo(a){ debugger;"
2515
      "                 if (a) {"
2516
      "                   bar.call(this, 1, 2, 3);"
2517
      "                 } else {"
2518
      "                   bar.call(this, 0);"
2519
      "                 }"
2520
      "}",
2521
      "foo");
2522

    
2523
  // Register a debug event listener which steps and counts.
2524
  v8::Debug::SetDebugEventListener(DebugEventStep);
2525
  step_action = StepIn;
2526

    
2527
  // Check stepping where the if condition in bar is false.
2528
  break_point_hit_count = 0;
2529
  foo->Call(env->Global(), 0, NULL);
2530
  CHECK_EQ(4, break_point_hit_count);
2531

    
2532
  // Check stepping where the if condition in bar is true.
2533
  break_point_hit_count = 0;
2534
  const int argc = 1;
2535
  v8::Handle<v8::Value> argv[argc] = { v8::True() };
2536
  foo->Call(env->Global(), argc, argv);
2537
  CHECK_EQ(6, break_point_hit_count);
2538

    
2539
  v8::Debug::SetDebugEventListener(NULL);
2540
  CheckDebuggerUnloaded();
2541

    
2542
  // Register a debug event listener which just counts.
2543
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
2544

    
2545
  break_point_hit_count = 0;
2546
  foo->Call(env->Global(), 0, NULL);
2547

    
2548
  // Without stepping only the debugger statement is hit.
2549
  CHECK_EQ(1, break_point_hit_count);
2550

    
2551
  v8::Debug::SetDebugEventListener(NULL);
2552
  CheckDebuggerUnloaded();
2553
}
2554

    
2555

    
2556
// Test break on exceptions. For each exception break combination the number
2557
// of debug event exception callbacks and message callbacks are collected. The
2558
// number of debug event exception callbacks are used to check that the
2559
// debugger is called correctly and the number of message callbacks is used to
2560
// check that uncaught exceptions are still returned even if there is a break
2561
// for them.
2562
TEST(BreakOnException) {
2563
  v8::HandleScope scope;
2564
  DebugLocalContext env;
2565
  env.ExposeDebug();
2566

    
2567
  v8::internal::Top::TraceException(false);
2568

    
2569
  // Create functions for testing break on exception.
2570
  v8::Local<v8::Function> throws =
2571
      CompileFunction(&env, "function throws(){throw 1;}", "throws");
2572
  v8::Local<v8::Function> caught =
2573
      CompileFunction(&env,
2574
                      "function caught(){try {throws();} catch(e) {};}",
2575
                      "caught");
2576
  v8::Local<v8::Function> notCaught =
2577
      CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
2578

    
2579
  v8::V8::AddMessageListener(MessageCallbackCount);
2580
  v8::Debug::SetDebugEventListener(DebugEventCounter);
2581

    
2582
  // Initial state should be break on uncaught exception.
2583
  DebugEventCounterClear();
2584
  MessageCallbackCountClear();
2585
  caught->Call(env->Global(), 0, NULL);
2586
  CHECK_EQ(0, exception_hit_count);
2587
  CHECK_EQ(0, uncaught_exception_hit_count);
2588
  CHECK_EQ(0, message_callback_count);
2589
  notCaught->Call(env->Global(), 0, NULL);
2590
  CHECK_EQ(1, exception_hit_count);
2591
  CHECK_EQ(1, uncaught_exception_hit_count);
2592
  CHECK_EQ(1, message_callback_count);
2593

    
2594
  // No break on exception
2595
  DebugEventCounterClear();
2596
  MessageCallbackCountClear();
2597
  ChangeBreakOnException(false, false);
2598
  caught->Call(env->Global(), 0, NULL);
2599
  CHECK_EQ(0, exception_hit_count);
2600
  CHECK_EQ(0, uncaught_exception_hit_count);
2601
  CHECK_EQ(0, message_callback_count);
2602
  notCaught->Call(env->Global(), 0, NULL);
2603
  CHECK_EQ(0, exception_hit_count);
2604
  CHECK_EQ(0, uncaught_exception_hit_count);
2605
  CHECK_EQ(1, message_callback_count);
2606

    
2607
  // Break on uncaught exception
2608
  DebugEventCounterClear();
2609
  MessageCallbackCountClear();
2610
  ChangeBreakOnException(false, true);
2611
  caught->Call(env->Global(), 0, NULL);
2612
  CHECK_EQ(0, exception_hit_count);
2613
  CHECK_EQ(0, uncaught_exception_hit_count);
2614
  CHECK_EQ(0, message_callback_count);
2615
  notCaught->Call(env->Global(), 0, NULL);
2616
  CHECK_EQ(1, exception_hit_count);
2617
  CHECK_EQ(1, uncaught_exception_hit_count);
2618
  CHECK_EQ(1, message_callback_count);
2619

    
2620
  // Break on exception and uncaught exception
2621
  DebugEventCounterClear();
2622
  MessageCallbackCountClear();
2623
  ChangeBreakOnException(true, true);
2624
  caught->Call(env->Global(), 0, NULL);
2625
  CHECK_EQ(1, exception_hit_count);
2626
  CHECK_EQ(0, uncaught_exception_hit_count);
2627
  CHECK_EQ(0, message_callback_count);
2628
  notCaught->Call(env->Global(), 0, NULL);
2629
  CHECK_EQ(2, exception_hit_count);
2630
  CHECK_EQ(1, uncaught_exception_hit_count);
2631
  CHECK_EQ(1, message_callback_count);
2632

    
2633
  // Break on exception
2634
  DebugEventCounterClear();
2635
  MessageCallbackCountClear();
2636
  ChangeBreakOnException(true, false);
2637
  caught->Call(env->Global(), 0, NULL);
2638
  CHECK_EQ(1, exception_hit_count);
2639
  CHECK_EQ(0, uncaught_exception_hit_count);
2640
  CHECK_EQ(0, message_callback_count);
2641
  notCaught->Call(env->Global(), 0, NULL);
2642
  CHECK_EQ(2, exception_hit_count);
2643
  CHECK_EQ(1, uncaught_exception_hit_count);
2644
  CHECK_EQ(1, message_callback_count);
2645

    
2646
  // No break on exception using JavaScript
2647
  DebugEventCounterClear();
2648
  MessageCallbackCountClear();
2649
  ChangeBreakOnExceptionFromJS(false, false);
2650
  caught->Call(env->Global(), 0, NULL);
2651
  CHECK_EQ(0, exception_hit_count);
2652
  CHECK_EQ(0, uncaught_exception_hit_count);
2653
  CHECK_EQ(0, message_callback_count);
2654
  notCaught->Call(env->Global(), 0, NULL);
2655
  CHECK_EQ(0, exception_hit_count);
2656
  CHECK_EQ(0, uncaught_exception_hit_count);
2657
  CHECK_EQ(1, message_callback_count);
2658

    
2659
  // Break on uncaught exception using JavaScript
2660
  DebugEventCounterClear();
2661
  MessageCallbackCountClear();
2662
  ChangeBreakOnExceptionFromJS(false, true);
2663
  caught->Call(env->Global(), 0, NULL);
2664
  CHECK_EQ(0, exception_hit_count);
2665
  CHECK_EQ(0, uncaught_exception_hit_count);
2666
  CHECK_EQ(0, message_callback_count);
2667
  notCaught->Call(env->Global(), 0, NULL);
2668
  CHECK_EQ(1, exception_hit_count);
2669
  CHECK_EQ(1, uncaught_exception_hit_count);
2670
  CHECK_EQ(1, message_callback_count);
2671

    
2672
  // Break on exception and uncaught exception using JavaScript
2673
  DebugEventCounterClear();
2674
  MessageCallbackCountClear();
2675
  ChangeBreakOnExceptionFromJS(true, true);
2676
  caught->Call(env->Global(), 0, NULL);
2677
  CHECK_EQ(1, exception_hit_count);
2678
  CHECK_EQ(0, message_callback_count);
2679
  CHECK_EQ(0, uncaught_exception_hit_count);
2680
  notCaught->Call(env->Global(), 0, NULL);
2681
  CHECK_EQ(2, exception_hit_count);
2682
  CHECK_EQ(1, uncaught_exception_hit_count);
2683
  CHECK_EQ(1, message_callback_count);
2684

    
2685
  // Break on exception using JavaScript
2686
  DebugEventCounterClear();
2687
  MessageCallbackCountClear();
2688
  ChangeBreakOnExceptionFromJS(true, false);
2689
  caught->Call(env->Global(), 0, NULL);
2690
  CHECK_EQ(1, exception_hit_count);
2691
  CHECK_EQ(0, uncaught_exception_hit_count);
2692
  CHECK_EQ(0, message_callback_count);
2693
  notCaught->Call(env->Global(), 0, NULL);
2694
  CHECK_EQ(2, exception_hit_count);
2695
  CHECK_EQ(1, uncaught_exception_hit_count);
2696
  CHECK_EQ(1, message_callback_count);
2697

    
2698
  v8::Debug::SetDebugEventListener(NULL);
2699
  CheckDebuggerUnloaded();
2700
  v8::V8::RemoveMessageListeners(MessageCallbackCount);
2701
}
2702

    
2703

    
2704
// Test break on exception from compiler errors. When compiling using
2705
// v8::Script::Compile there is no JavaScript stack whereas when compiling using
2706
// eval there are JavaScript frames.
2707
TEST(BreakOnCompileException) {
2708
  v8::HandleScope scope;
2709
  DebugLocalContext env;
2710

    
2711
  v8::internal::Top::TraceException(false);
2712

    
2713
  // Create a function for checking the function when hitting a break point.
2714
  frame_count = CompileFunction(&env, frame_count_source, "frame_count");
2715

    
2716
  v8::V8::AddMessageListener(MessageCallbackCount);
2717
  v8::Debug::SetDebugEventListener(DebugEventCounter);
2718

    
2719
  DebugEventCounterClear();
2720
  MessageCallbackCountClear();
2721

    
2722
  // Check initial state.
2723
  CHECK_EQ(0, exception_hit_count);
2724
  CHECK_EQ(0, uncaught_exception_hit_count);
2725
  CHECK_EQ(0, message_callback_count);
2726
  CHECK_EQ(-1, last_js_stack_height);
2727

    
2728
  // Throws SyntaxError: Unexpected end of input
2729
  v8::Script::Compile(v8::String::New("+++"));
2730
  CHECK_EQ(1, exception_hit_count);
2731
  CHECK_EQ(1, uncaught_exception_hit_count);
2732
  CHECK_EQ(1, message_callback_count);
2733
  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
2734

    
2735
  // Throws SyntaxError: Unexpected identifier
2736
  v8::Script::Compile(v8::String::New("x x"));
2737
  CHECK_EQ(2, exception_hit_count);
2738
  CHECK_EQ(2, uncaught_exception_hit_count);
2739
  CHECK_EQ(2, message_callback_count);
2740
  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
2741

    
2742
  // Throws SyntaxError: Unexpected end of input
2743
  v8::Script::Compile(v8::String::New("eval('+++')"))->Run();
2744
  CHECK_EQ(3, exception_hit_count);
2745
  CHECK_EQ(3, uncaught_exception_hit_count);
2746
  CHECK_EQ(3, message_callback_count);
2747
  CHECK_EQ(1, last_js_stack_height);
2748

    
2749
  // Throws SyntaxError: Unexpected identifier
2750
  v8::Script::Compile(v8::String::New("eval('x x')"))->Run();
2751
  CHECK_EQ(4, exception_hit_count);
2752
  CHECK_EQ(4, uncaught_exception_hit_count);
2753
  CHECK_EQ(4, message_callback_count);
2754
  CHECK_EQ(1, last_js_stack_height);
2755
}
2756

    
2757

    
2758
TEST(StepWithException) {
2759
  v8::HandleScope scope;
2760
  DebugLocalContext env;
2761

    
2762
  // Create a function for checking the function when hitting a break point.
2763
  frame_function_name = CompileFunction(&env,
2764
                                        frame_function_name_source,
2765
                                        "frame_function_name");
2766

    
2767
  // Register a debug event listener which steps and counts.
2768
  v8::Debug::SetDebugEventListener(DebugEventStepSequence);
2769

    
2770
  // Create functions for testing stepping.
2771
  const char* src = "function a() { n(); }; "
2772
                    "function b() { c(); }; "
2773
                    "function c() { n(); }; "
2774
                    "function d() { x = 1; try { e(); } catch(x) { x = 2; } }; "
2775
                    "function e() { n(); }; "
2776
                    "function f() { x = 1; try { g(); } catch(x) { x = 2; } }; "
2777
                    "function g() { h(); }; "
2778
                    "function h() { x = 1; throw 1; }; ";
2779

    
2780
  // Step through invocation of a.
2781
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
2782
  SetBreakPoint(a, 0);
2783
  step_action = StepIn;
2784
  break_point_hit_count = 0;
2785
  expected_step_sequence = "aa";
2786
  a->Call(env->Global(), 0, NULL);
2787
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2788

    
2789
  // Step through invocation of b + c.
2790
  v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
2791
  SetBreakPoint(b, 0);
2792
  step_action = StepIn;
2793
  break_point_hit_count = 0;
2794
  expected_step_sequence = "bcc";
2795
  b->Call(env->Global(), 0, NULL);
2796
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2797

    
2798
  // Step through invocation of d + e.
2799
  v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
2800
  SetBreakPoint(d, 0);
2801
  ChangeBreakOnException(false, true);
2802
  step_action = StepIn;
2803
  break_point_hit_count = 0;
2804
  expected_step_sequence = "dded";
2805
  d->Call(env->Global(), 0, NULL);
2806
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2807

    
2808
  // Step through invocation of d + e now with break on caught exceptions.
2809
  ChangeBreakOnException(true, true);
2810
  step_action = StepIn;
2811
  break_point_hit_count = 0;
2812
  expected_step_sequence = "ddeed";
2813
  d->Call(env->Global(), 0, NULL);
2814
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2815

    
2816
  // Step through invocation of f + g + h.
2817
  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
2818
  SetBreakPoint(f, 0);
2819
  ChangeBreakOnException(false, true);
2820
  step_action = StepIn;
2821
  break_point_hit_count = 0;
2822
  expected_step_sequence = "ffghf";
2823
  f->Call(env->Global(), 0, NULL);
2824
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2825

    
2826
  // Step through invocation of f + g + h now with break on caught exceptions.
2827
  ChangeBreakOnException(true, true);
2828
  step_action = StepIn;
2829
  break_point_hit_count = 0;
2830
  expected_step_sequence = "ffghhf";
2831
  f->Call(env->Global(), 0, NULL);
2832
  CHECK_EQ(strlen(expected_step_sequence), break_point_hit_count);
2833

    
2834
  // Get rid of the debug event listener.
2835
  v8::Debug::SetDebugEventListener(NULL);
2836
  CheckDebuggerUnloaded();
2837
}
2838

    
2839

    
2840
TEST(DebugBreak) {
2841
  v8::HandleScope scope;
2842
  DebugLocalContext env;
2843

    
2844
  // This test should be run with option --verify-heap. This is an ASSERT and
2845
  // not a CHECK as --verify-heap is only available in debug mode.
2846
  ASSERT(v8::internal::FLAG_verify_heap);
2847

    
2848
  // Register a debug event listener which sets the break flag and counts.
2849
  v8::Debug::SetDebugEventListener(DebugEventBreak);
2850

    
2851
  // Create a function for testing stepping.
2852
  const char* src = "function f0() {}"
2853
                    "function f1(x1) {}"
2854
                    "function f2(x1,x2) {}"
2855
                    "function f3(x1,x2,x3) {}";
2856
  v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
2857
  v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
2858
  v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
2859
  v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
2860

    
2861
  // Call the function to make sure it is compiled.
2862
  v8::Handle<v8::Value> argv[] = { v8::Number::New(1),
2863
                                   v8::Number::New(1),
2864
                                   v8::Number::New(1),
2865
                                   v8::Number::New(1) };
2866

    
2867
  // Call all functions to make sure that they are compiled.
2868
  f0->Call(env->Global(), 0, NULL);
2869
  f1->Call(env->Global(), 0, NULL);
2870
  f2->Call(env->Global(), 0, NULL);
2871
  f3->Call(env->Global(), 0, NULL);
2872

    
2873
  // Set the debug break flag.
2874
  v8::Debug::DebugBreak();
2875

    
2876
  // Call all functions with different argument count.
2877
  break_point_hit_count = 0;
2878
  for (unsigned int i = 0; i < ARRAY_SIZE(argv); i++) {
2879
    f0->Call(env->Global(), i, argv);
2880
    f1->Call(env->Global(), i, argv);
2881
    f2->Call(env->Global(), i, argv);
2882
    f3->Call(env->Global(), i, argv);
2883
  }
2884

    
2885
  // One break for each function called.
2886
  CHECK_EQ(4 * ARRAY_SIZE(argv), break_point_hit_count);
2887

    
2888
  // Get rid of the debug event listener.
2889
  v8::Debug::SetDebugEventListener(NULL);
2890
  CheckDebuggerUnloaded();
2891
}
2892

    
2893

    
2894
// Test to ensure that JavaScript code keeps running while the debug break
2895
// through the stack limit flag is set but breaks are disabled.
2896
TEST(DisableBreak) {
2897
  v8::HandleScope scope;
2898
  DebugLocalContext env;
2899

    
2900
  // Register a debug event listener which sets the break flag and counts.
2901
  v8::Debug::SetDebugEventListener(DebugEventCounter);
2902

    
2903
  // Create a function for testing stepping.
2904
  const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
2905
  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
2906

    
2907
  // Set the debug break flag.
2908
  v8::Debug::DebugBreak();
2909

    
2910
  // Call all functions with different argument count.
2911
  break_point_hit_count = 0;
2912
  f->Call(env->Global(), 0, NULL);
2913
  CHECK_EQ(1, break_point_hit_count);
2914

    
2915
  {
2916
    v8::Debug::DebugBreak();
2917
    v8::internal::DisableBreak disable_break(true);
2918
    f->Call(env->Global(), 0, NULL);
2919
    CHECK_EQ(1, break_point_hit_count);
2920
  }
2921

    
2922
  f->Call(env->Global(), 0, NULL);
2923
  CHECK_EQ(2, break_point_hit_count);
2924

    
2925
  // Get rid of the debug event listener.
2926
  v8::Debug::SetDebugEventListener(NULL);
2927
  CheckDebuggerUnloaded();
2928
}
2929

    
2930

    
2931
static v8::Handle<v8::Array> NamedEnum(const v8::AccessorInfo&) {
2932
  v8::Handle<v8::Array> result = v8::Array::New(3);
2933
  result->Set(v8::Integer::New(0), v8::String::New("a"));
2934
  result->Set(v8::Integer::New(1), v8::String::New("b"));
2935
  result->Set(v8::Integer::New(2), v8::String::New("c"));
2936
  return result;
2937
}
2938

    
2939

    
2940
static v8::Handle<v8::Array> IndexedEnum(const v8::AccessorInfo&) {
2941
  v8::Handle<v8::Array> result = v8::Array::New(2);
2942
  result->Set(v8::Integer::New(0), v8::Number::New(1));
2943
  result->Set(v8::Integer::New(1), v8::Number::New(10));
2944
  return result;
2945
}
2946

    
2947

    
2948
static v8::Handle<v8::Value> NamedGetter(v8::Local<v8::String> name,
2949
                                         const v8::AccessorInfo& info) {
2950
  v8::String::AsciiValue n(name);
2951
  if (strcmp(*n, "a") == 0) {
2952
    return v8::String::New("AA");
2953
  } else if (strcmp(*n, "b") == 0) {
2954
    return v8::String::New("BB");
2955
  } else if (strcmp(*n, "c") == 0) {
2956
    return v8::String::New("CC");
2957
  } else {
2958
    return v8::Undefined();
2959
  }
2960

    
2961
  return name;
2962
}
2963

    
2964

    
2965
static v8::Handle<v8::Value> IndexedGetter(uint32_t index,
2966
                                           const v8::AccessorInfo& info) {
2967
  return v8::Number::New(index + 1);
2968
}
2969

    
2970

    
2971
TEST(InterceptorPropertyMirror) {
2972
  // Create a V8 environment with debug access.
2973
  v8::HandleScope scope;
2974
  DebugLocalContext env;
2975
  env.ExposeDebug();
2976

    
2977
  // Create object with named interceptor.
2978
  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
2979
  named->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
2980
  env->Global()->Set(v8::String::New("intercepted_named"),
2981
                     named->NewInstance());
2982

    
2983
  // Create object with indexed interceptor.
2984
  v8::Handle<v8::ObjectTemplate> indexed = v8::ObjectTemplate::New();
2985
  indexed->SetIndexedPropertyHandler(IndexedGetter,
2986
                                     NULL,
2987
                                     NULL,
2988
                                     NULL,
2989
                                     IndexedEnum);
2990
  env->Global()->Set(v8::String::New("intercepted_indexed"),
2991
                     indexed->NewInstance());
2992

    
2993
  // Create object with both named and indexed interceptor.
2994
  v8::Handle<v8::ObjectTemplate> both = v8::ObjectTemplate::New();
2995
  both->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
2996
  both->SetIndexedPropertyHandler(IndexedGetter, NULL, NULL, NULL, IndexedEnum);
2997
  env->Global()->Set(v8::String::New("intercepted_both"), both->NewInstance());
2998

    
2999
  // Get mirrors for the three objects with interceptor.
3000
  CompileRun(
3001
      "named_mirror = debug.MakeMirror(intercepted_named);"
3002
      "indexed_mirror = debug.MakeMirror(intercepted_indexed);"
3003
      "both_mirror = debug.MakeMirror(intercepted_both)");
3004
  CHECK(CompileRun(
3005
       "named_mirror instanceof debug.ObjectMirror")->BooleanValue());
3006
  CHECK(CompileRun(
3007
        "indexed_mirror instanceof debug.ObjectMirror")->BooleanValue());
3008
  CHECK(CompileRun(
3009
        "both_mirror instanceof debug.ObjectMirror")->BooleanValue());
3010

    
3011
  // Get the property names from the interceptors
3012
  CompileRun(
3013
      "named_names = named_mirror.propertyNames();"
3014
      "indexed_names = indexed_mirror.propertyNames();"
3015
      "both_names = both_mirror.propertyNames()");
3016
  CHECK_EQ(3, CompileRun("named_names.length")->Int32Value());
3017
  CHECK_EQ(2, CompileRun("indexed_names.length")->Int32Value());
3018
  CHECK_EQ(5, CompileRun("both_names.length")->Int32Value());
3019

    
3020
  // Check the expected number of properties.
3021
  const char* source;
3022
  source = "named_mirror.properties().length";
3023
  CHECK_EQ(3, CompileRun(source)->Int32Value());
3024

    
3025
  source = "indexed_mirror.properties().length";
3026
  CHECK_EQ(2, CompileRun(source)->Int32Value());
3027

    
3028
  source = "both_mirror.properties().length";
3029
  CHECK_EQ(5, CompileRun(source)->Int32Value());
3030

    
3031
  // 1 is PropertyKind.Named;
3032
  source = "both_mirror.properties(1).length";
3033
  CHECK_EQ(3, CompileRun(source)->Int32Value());
3034

    
3035
  // 2 is PropertyKind.Indexed;
3036
  source = "both_mirror.properties(2).length";
3037
  CHECK_EQ(2, CompileRun(source)->Int32Value());
3038

    
3039
  // 3 is PropertyKind.Named  | PropertyKind.Indexed;
3040
  source = "both_mirror.properties(3).length";
3041
  CHECK_EQ(5, CompileRun(source)->Int32Value());
3042

    
3043
  // Get the interceptor properties for the object with only named interceptor.
3044
  CompileRun("named_values = named_mirror.properties()");
3045

    
3046
  // Check that the properties are interceptor properties.
3047
  for (int i = 0; i < 3; i++) {
3048
    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
3049
    OS::SNPrintF(buffer,
3050
                 "named_values[%d] instanceof debug.PropertyMirror", i);
3051
    CHECK(CompileRun(buffer.start())->BooleanValue());
3052

    
3053
    // 4 is PropertyType.Interceptor
3054
    OS::SNPrintF(buffer, "named_values[%d].propertyType()", i);
3055
    CHECK_EQ(4, CompileRun(buffer.start())->Int32Value());
3056

    
3057
    OS::SNPrintF(buffer, "named_values[%d].isNative()", i);
3058
    CHECK(CompileRun(buffer.start())->BooleanValue());
3059
  }
3060

    
3061
  // Get the interceptor properties for the object with only indexed
3062
  // interceptor.
3063
  CompileRun("indexed_values = indexed_mirror.properties()");
3064

    
3065
  // Check that the properties are interceptor properties.
3066
  for (int i = 0; i < 2; i++) {
3067
    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
3068
    OS::SNPrintF(buffer,
3069
                 "indexed_values[%d] instanceof debug.PropertyMirror", i);
3070
    CHECK(CompileRun(buffer.start())->BooleanValue());
3071
  }
3072

    
3073
  // Get the interceptor properties for the object with both types of
3074
  // interceptors.
3075
  CompileRun("both_values = both_mirror.properties()");
3076

    
3077
  // Check that the properties are interceptor properties.
3078
  for (int i = 0; i < 5; i++) {
3079
    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
3080
    OS::SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
3081
    CHECK(CompileRun(buffer.start())->BooleanValue());
3082
  }
3083

    
3084
  // Check the property names.
3085
  source = "both_values[0].name() == 'a'";
3086
  CHECK(CompileRun(source)->BooleanValue());
3087

    
3088
  source = "both_values[1].name() == 'b'";
3089
  CHECK(CompileRun(source)->BooleanValue());
3090

    
3091
  source = "both_values[2].name() == 'c'";
3092
  CHECK(CompileRun(source)->BooleanValue());
3093

    
3094
  source = "both_values[3].name() == 1";
3095
  CHECK(CompileRun(source)->BooleanValue());
3096

    
3097
  source = "both_values[4].name() == 10";
3098
  CHECK(CompileRun(source)->BooleanValue());
3099
}
3100

    
3101

    
3102
TEST(HiddenPrototypePropertyMirror) {
3103
  // Create a V8 environment with debug access.
3104
  v8::HandleScope scope;
3105
  DebugLocalContext env;
3106
  env.ExposeDebug();
3107

    
3108
  v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
3109
  t0->InstanceTemplate()->Set(v8::String::New("x"), v8::Number::New(0));
3110
  v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
3111
  t1->SetHiddenPrototype(true);
3112
  t1->InstanceTemplate()->Set(v8::String::New("y"), v8::Number::New(1));
3113
  v8::Handle<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
3114
  t2->SetHiddenPrototype(true);
3115
  t2->InstanceTemplate()->Set(v8::String::New("z"), v8::Number::New(2));
3116
  v8::Handle<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
3117
  t3->InstanceTemplate()->Set(v8::String::New("u"), v8::Number::New(3));
3118

    
3119
  // Create object and set them on the global object.
3120
  v8::Handle<v8::Object> o0 = t0->GetFunction()->NewInstance();
3121
  env->Global()->Set(v8::String::New("o0"), o0);
3122
  v8::Handle<v8::Object> o1 = t1->GetFunction()->NewInstance();
3123
  env->Global()->Set(v8::String::New("o1"), o1);
3124
  v8::Handle<v8::Object> o2 = t2->GetFunction()->NewInstance();
3125
  env->Global()->Set(v8::String::New("o2"), o2);
3126
  v8::Handle<v8::Object> o3 = t3->GetFunction()->NewInstance();
3127
  env->Global()->Set(v8::String::New("o3"), o3);
3128

    
3129
  // Get mirrors for the four objects.
3130
  CompileRun(
3131
      "o0_mirror = debug.MakeMirror(o0);"
3132
      "o1_mirror = debug.MakeMirror(o1);"
3133
      "o2_mirror = debug.MakeMirror(o2);"
3134
      "o3_mirror = debug.MakeMirror(o3)");
3135
  CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")->BooleanValue());
3136
  CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")->BooleanValue());
3137
  CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")->BooleanValue());
3138
  CHECK(CompileRun("o3_mirror instanceof debug.ObjectMirror")->BooleanValue());
3139

    
3140
  // Check that each object has one property.
3141
  CHECK_EQ(1, CompileRun(
3142
              "o0_mirror.propertyNames().length")->Int32Value());
3143
  CHECK_EQ(1, CompileRun(
3144
              "o1_mirror.propertyNames().length")->Int32Value());
3145
  CHECK_EQ(1, CompileRun(
3146
              "o2_mirror.propertyNames().length")->Int32Value());
3147
  CHECK_EQ(1, CompileRun(
3148
              "o3_mirror.propertyNames().length")->Int32Value());
3149

    
3150
  // Set o1 as prototype for o0. o1 has the hidden prototype flag so all
3151
  // properties on o1 should be seen on o0.
3152
  o0->Set(v8::String::New("__proto__"), o1);
3153
  CHECK_EQ(2, CompileRun(
3154
              "o0_mirror.propertyNames().length")->Int32Value());
3155
  CHECK_EQ(0, CompileRun(
3156
              "o0_mirror.property('x').value().value()")->Int32Value());
3157
  CHECK_EQ(1, CompileRun(
3158
              "o0_mirror.property('y').value().value()")->Int32Value());
3159

    
3160
  // Set o2 as prototype for o0 (it will end up after o1 as o1 has the hidden
3161
  // prototype flag. o2 also has the hidden prototype flag so all properties
3162
  // on o2 should be seen on o0 as well as properties on o1.
3163
  o0->Set(v8::String::New("__proto__"), o2);
3164
  CHECK_EQ(3, CompileRun(
3165
              "o0_mirror.propertyNames().length")->Int32Value());
3166
  CHECK_EQ(0, CompileRun(
3167
              "o0_mirror.property('x').value().value()")->Int32Value());
3168
  CHECK_EQ(1, CompileRun(
3169
              "o0_mirror.property('y').value().value()")->Int32Value());
3170
  CHECK_EQ(2, CompileRun(
3171
              "o0_mirror.property('z').value().value()")->Int32Value());
3172

    
3173
  // Set o3 as prototype for o0 (it will end up after o1 and o2 as both o1 and
3174
  // o2 has the hidden prototype flag. o3 does not have the hidden prototype
3175
  // flag so properties on o3 should not be seen on o0 whereas the properties
3176
  // from o1 and o2 should still be seen on o0.
3177
  // Final prototype chain: o0 -> o1 -> o2 -> o3
3178
  // Hidden prototypes:           ^^    ^^
3179
  o0->Set(v8::String::New("__proto__"), o3);
3180
  CHECK_EQ(3, CompileRun(
3181
              "o0_mirror.propertyNames().length")->Int32Value());
3182
  CHECK_EQ(1, CompileRun(
3183
              "o3_mirror.propertyNames().length")->Int32Value());
3184
  CHECK_EQ(0, CompileRun(
3185
              "o0_mirror.property('x').value().value()")->Int32Value());
3186
  CHECK_EQ(1, CompileRun(
3187
              "o0_mirror.property('y').value().value()")->Int32Value());
3188
  CHECK_EQ(2, CompileRun(
3189
              "o0_mirror.property('z').value().value()")->Int32Value());
3190
  CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue());
3191

    
3192
  // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden.
3193
  CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue());
3194
}
3195

    
3196

    
3197
// Multithreaded tests of JSON debugger protocol
3198

    
3199
// Support classes
3200

    
3201
// Copies a C string to a 16-bit string.  Does not check for buffer overflow.
3202
// Does not use the V8 engine to convert strings, so it can be used
3203
// in any thread.  Returns the length of the string.
3204
int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
3205
  int i;
3206
  for (i = 0; input_buffer[i] != '\0'; ++i) {
3207
    // ASCII does not use chars > 127, but be careful anyway.
3208
    output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
3209
  }
3210
  output_buffer[i] = 0;
3211
  return i;
3212
}
3213

    
3214
// Copies a 16-bit string to a C string by dropping the high byte of
3215
// each character.  Does not check for buffer overflow.
3216
// Can be used in any thread.  Requires string length as an input.
3217
int Utf16ToAscii(const uint16_t* input_buffer, int length,
3218
                 char* output_buffer) {
3219
  for (int i = 0; i < length; ++i) {
3220
    output_buffer[i] = static_cast<char>(input_buffer[i]);
3221
  }
3222
  output_buffer[length] = '\0';
3223
  return length;
3224
}
3225

    
3226
// Provides synchronization between k threads, where k is an input to the
3227
// constructor.  The Wait() call blocks a thread until it is called for the
3228
// k'th time, then all calls return.  Each ThreadBarrier object can only
3229
// be used once.
3230
class ThreadBarrier {
3231
 public:
3232
  explicit ThreadBarrier(int num_threads);
3233
  ~ThreadBarrier();
3234
  void Wait();
3235
 private:
3236
  int num_threads_;
3237
  int num_blocked_;
3238
  v8::internal::Mutex* lock_;
3239
  v8::internal::Semaphore* sem_;
3240
  bool invalid_;
3241
};
3242

    
3243
ThreadBarrier::ThreadBarrier(int num_threads)
3244
    : num_threads_(num_threads), num_blocked_(0) {
3245
  lock_ = OS::CreateMutex();
3246
  sem_ = OS::CreateSemaphore(0);
3247
  invalid_ = false;  // A barrier may only be used once.  Then it is invalid.
3248
}
3249

    
3250
// Do not call, due to race condition with Wait().
3251
// Could be resolved with Pthread condition variables.
3252
ThreadBarrier::~ThreadBarrier() {
3253
  lock_->Lock();
3254
  delete lock_;
3255
  delete sem_;
3256
}
3257

    
3258
void ThreadBarrier::Wait() {
3259
  lock_->Lock();
3260
  ASSERT(!invalid_);
3261
  if (num_blocked_ == num_threads_ - 1) {
3262
    // Signal and unblock all waiting threads.
3263
    for (int i = 0; i < num_threads_ - 1; ++i) {
3264
      sem_->Signal();
3265
    }
3266
    invalid_ = true;
3267
    printf("BARRIER\n\n");
3268
    fflush(stdout);
3269
    lock_->Unlock();
3270
  } else {  // Wait for the semaphore.
3271
    ++num_blocked_;
3272
    lock_->Unlock();  // Potential race condition with destructor because
3273
    sem_->Wait();  // these two lines are not atomic.
3274
  }
3275
}
3276

    
3277
// A set containing enough barriers and semaphores for any of the tests.
3278
class Barriers {
3279
 public:
3280
  Barriers();
3281
  void Initialize();
3282
  ThreadBarrier barrier_1;
3283
  ThreadBarrier barrier_2;
3284
  ThreadBarrier barrier_3;
3285
  ThreadBarrier barrier_4;
3286
  ThreadBarrier barrier_5;
3287
  v8::internal::Semaphore* semaphore_1;
3288
  v8::internal::Semaphore* semaphore_2;
3289
};
3290

    
3291
Barriers::Barriers() : barrier_1(2), barrier_2(2),
3292
    barrier_3(2), barrier_4(2), barrier_5(2) {}
3293

    
3294
void Barriers::Initialize() {
3295
  semaphore_1 = OS::CreateSemaphore(0);
3296
  semaphore_2 = OS::CreateSemaphore(0);
3297
}
3298

    
3299

    
3300
// We match parts of the message to decide if it is a break message.
3301
bool IsBreakEventMessage(char *message) {
3302
  const char* type_event = "\"type\":\"event\"";
3303
  const char* event_break = "\"event\":\"break\"";
3304
  // Does the message contain both type:event and event:break?
3305
  return strstr(message, type_event) != NULL &&
3306
         strstr(message, event_break) != NULL;
3307
}
3308

    
3309

    
3310
/* Test MessageQueues */
3311
/* Tests the message queues that hold debugger commands and
3312
 * response messages to the debugger.  Fills queues and makes
3313
 * them grow.
3314
 */
3315
Barriers message_queue_barriers;
3316

    
3317
// This is the debugger thread, that executes no v8 calls except
3318
// placing JSON debugger commands in the queue.
3319
class MessageQueueDebuggerThread : public v8::internal::Thread {
3320
 public:
3321
  void Run();
3322
};
3323

    
3324
static void MessageHandler(const uint16_t* message, int length, void *data) {
3325
  static char print_buffer[1000];
3326
  Utf16ToAscii(message, length, print_buffer);
3327
  if (IsBreakEventMessage(print_buffer)) {
3328
    // Lets test script wait until break occurs to send commands.
3329
    // Signals when a break is reported.
3330
    message_queue_barriers.semaphore_2->Signal();
3331
  }
3332
  // Allow message handler to block on a semaphore, to test queueing of
3333
  // messages while blocked.
3334
  message_queue_barriers.semaphore_1->Wait();
3335
  printf("%s\n", print_buffer);
3336
  fflush(stdout);
3337
}
3338

    
3339

    
3340
void MessageQueueDebuggerThread::Run() {
3341
  const int kBufferSize = 1000;
3342
  uint16_t buffer_1[kBufferSize];
3343
  uint16_t buffer_2[kBufferSize];
3344
  const char* command_1 =
3345
      "{\"seq\":117,"
3346
       "\"type\":\"request\","
3347
       "\"command\":\"evaluate\","
3348
       "\"arguments\":{\"expression\":\"1+2\"}}";
3349
  const char* command_2 =
3350
    "{\"seq\":118,"
3351
     "\"type\":\"request\","
3352
     "\"command\":\"evaluate\","
3353
     "\"arguments\":{\"expression\":\"1+a\"}}";
3354
  const char* command_3 =
3355
    "{\"seq\":119,"
3356
     "\"type\":\"request\","
3357
     "\"command\":\"evaluate\","
3358
     "\"arguments\":{\"expression\":\"c.d * b\"}}";
3359
  const char* command_continue =
3360
    "{\"seq\":106,"
3361
     "\"type\":\"request\","
3362
     "\"command\":\"continue\"}";
3363
  const char* command_single_step =
3364
    "{\"seq\":107,"
3365
     "\"type\":\"request\","
3366
     "\"command\":\"continue\","
3367
     "\"arguments\":{\"stepaction\":\"next\"}}";
3368

    
3369
  /* Interleaved sequence of actions by the two threads:*/
3370
  // Main thread compiles and runs source_1
3371
  message_queue_barriers.barrier_1.Wait();
3372
  // Post 6 commands, filling the command queue and making it expand.
3373
  // These calls return immediately, but the commands stay on the queue
3374
  // until the execution of source_2.
3375
  // Note: AsciiToUtf16 executes before SendCommand, so command is copied
3376
  // to buffer before buffer is sent to SendCommand.
3377
  v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_1, buffer_1));
3378
  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_2, buffer_2));
3379
  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
3380
  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
3381
  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_3, buffer_2));
3382
  message_queue_barriers.barrier_2.Wait();
3383
  // Main thread compiles and runs source_2.
3384
  // Queued commands are executed at the start of compilation of source_2.
3385
  message_queue_barriers.barrier_3.Wait();
3386
  // Free the message handler to process all the messages from the queue.
3387
  for (int i = 0; i < 20 ; ++i) {
3388
    message_queue_barriers.semaphore_1->Signal();
3389
  }
3390
  // Main thread compiles and runs source_3.
3391
  // source_3 includes a debugger statement, which causes a break event.
3392
  // Wait on break event from hitting "debugger" statement
3393
  message_queue_barriers.semaphore_2->Wait();
3394
  // These should execute after the "debugger" statement in source_2
3395
  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_single_step, buffer_2));
3396
  // Wait on break event after a single step executes.
3397
  message_queue_barriers.semaphore_2->Wait();
3398
  v8::Debug::SendCommand(buffer_1, AsciiToUtf16(command_2, buffer_1));
3399
  v8::Debug::SendCommand(buffer_2, AsciiToUtf16(command_continue, buffer_2));
3400
  // Main thread continues running source_3 to end, waits for this thread.
3401
}
3402

    
3403
MessageQueueDebuggerThread message_queue_debugger_thread;
3404

    
3405
// This thread runs the v8 engine.
3406
TEST(MessageQueues) {
3407
  // Create a V8 environment
3408
  v8::HandleScope scope;
3409
  DebugLocalContext env;
3410
  message_queue_barriers.Initialize();
3411
  v8::Debug::SetMessageHandler(MessageHandler);
3412
  message_queue_debugger_thread.Start();
3413

    
3414
  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
3415
  const char* source_2 = "e = 17;";
3416
  const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
3417

    
3418
  // See MessageQueueDebuggerThread::Run for interleaved sequence of
3419
  // API calls and events in the two threads.
3420
  CompileRun(source_1);
3421
  message_queue_barriers.barrier_1.Wait();
3422
  message_queue_barriers.barrier_2.Wait();
3423
  CompileRun(source_2);
3424
  message_queue_barriers.barrier_3.Wait();
3425
  CompileRun(source_3);
3426
  message_queue_debugger_thread.Join();
3427
  fflush(stdout);
3428
}
3429

    
3430
/* Test ThreadedDebugging */
3431
/* This test interrupts a running infinite loop that is
3432
 * occupying the v8 thread by a break command from the
3433
 * debugger thread.  It then changes the value of a
3434
 * global object, to make the loop terminate.
3435
 */
3436

    
3437
Barriers threaded_debugging_barriers;
3438

    
3439
class V8Thread : public v8::internal::Thread {
3440
 public:
3441
  void Run();
3442
};
3443

    
3444
class DebuggerThread : public v8::internal::Thread {
3445
 public:
3446
  void Run();
3447
};
3448

    
3449

    
3450
static v8::Handle<v8::Value> ThreadedAtBarrier1(const v8::Arguments& args) {
3451
  threaded_debugging_barriers.barrier_1.Wait();
3452
  return v8::Undefined();
3453
}
3454

    
3455

    
3456
static void ThreadedMessageHandler(const uint16_t* message, int length,
3457
                                   void *data) {
3458
  static char print_buffer[1000];
3459
  Utf16ToAscii(message, length, print_buffer);
3460
  if (IsBreakEventMessage(print_buffer)) {
3461
    threaded_debugging_barriers.barrier_2.Wait();
3462
  }
3463
  printf("%s\n", print_buffer);
3464
  fflush(stdout);
3465
}
3466

    
3467

    
3468
void V8Thread::Run() {
3469
  const char* source =
3470
      "flag = true;\n"
3471
      "function bar( new_value ) {\n"
3472
      "  flag = new_value;\n"
3473
      "  return \"Return from bar(\" + new_value + \")\";\n"
3474
      "}\n"
3475
      "\n"
3476
      "function foo() {\n"
3477
      "  var x = 1;\n"
3478
      "  while ( flag == true ) {\n"
3479
      "    if ( x == 1 ) {\n"
3480
      "      ThreadedAtBarrier1();\n"
3481
      "    }\n"
3482
      "    x = x + 1;\n"
3483
      "  }\n"
3484
      "}\n"
3485
      "\n"
3486
      "foo();\n";
3487

    
3488
  v8::HandleScope scope;
3489
  DebugLocalContext env;
3490
  v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
3491
  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
3492
  global_template->Set(v8::String::New("ThreadedAtBarrier1"),
3493
                       v8::FunctionTemplate::New(ThreadedAtBarrier1));
3494
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global_template);
3495
  v8::Context::Scope context_scope(context);
3496

    
3497
  CompileRun(source);
3498
}
3499

    
3500
void DebuggerThread::Run() {
3501
  const int kBufSize = 1000;
3502
  uint16_t buffer[kBufSize];
3503

    
3504
  const char* command_1 = "{\"seq\":102,"
3505
      "\"type\":\"request\","
3506
      "\"command\":\"evaluate\","
3507
      "\"arguments\":{\"expression\":\"bar(false)\"}}";
3508
  const char* command_2 = "{\"seq\":103,"
3509
      "\"type\":\"request\","
3510
      "\"command\":\"continue\"}";
3511

    
3512
  threaded_debugging_barriers.barrier_1.Wait();
3513
  v8::Debug::DebugBreak();
3514
  threaded_debugging_barriers.barrier_2.Wait();
3515
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
3516
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
3517
}
3518

    
3519
DebuggerThread debugger_thread;
3520
V8Thread v8_thread;
3521

    
3522
TEST(ThreadedDebugging) {
3523
  // Create a V8 environment
3524
  threaded_debugging_barriers.Initialize();
3525

    
3526
  v8_thread.Start();
3527
  debugger_thread.Start();
3528

    
3529
  v8_thread.Join();
3530
  debugger_thread.Join();
3531
}
3532

    
3533
/* Test RecursiveBreakpoints */
3534
/* In this test, the debugger evaluates a function with a breakpoint, after
3535
 * hitting a breakpoint in another function.  We do this with both values
3536
 * of the flag enabling recursive breakpoints, and verify that the second
3537
 * breakpoint is hit when enabled, and missed when disabled.
3538
 */
3539

    
3540
class BreakpointsV8Thread : public v8::internal::Thread {
3541
 public:
3542
  void Run();
3543
};
3544

    
3545
class BreakpointsDebuggerThread : public v8::internal::Thread {
3546
 public:
3547
  void Run();
3548
};
3549

    
3550

    
3551
Barriers* breakpoints_barriers;
3552

    
3553
static void BreakpointsMessageHandler(const uint16_t* message,
3554
                                      int length,
3555
                                      void *data) {
3556
  static char print_buffer[1000];
3557
  Utf16ToAscii(message, length, print_buffer);
3558
  printf("%s\n", print_buffer);
3559
  fflush(stdout);
3560

    
3561
  // Is break_template a prefix of the message?
3562
  if (IsBreakEventMessage(print_buffer)) {
3563
    breakpoints_barriers->semaphore_1->Signal();
3564
  }
3565
}
3566

    
3567

    
3568
void BreakpointsV8Thread::Run() {
3569
  const char* source_1 = "var y_global = 3;\n"
3570
    "function cat( new_value ) {\n"
3571
    "  var x = new_value;\n"
3572
    "  y_global = 4;\n"
3573
    "  x = 3 * x + 1;\n"
3574
    "  y_global = 5;\n"
3575
    "  return x;\n"
3576
    "}\n"
3577
    "\n"
3578
    "function dog() {\n"
3579
    "  var x = 1;\n"
3580
    "  x = y_global;"
3581
    "  var z = 3;"
3582
    "  x += 100;\n"
3583
    "  return x;\n"
3584
    "}\n"
3585
    "\n";
3586
  const char* source_2 = "cat(17);\n"
3587
    "cat(19);\n";
3588

    
3589
  v8::HandleScope scope;
3590
  DebugLocalContext env;
3591
  v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
3592

    
3593
  CompileRun(source_1);
3594
  breakpoints_barriers->barrier_1.Wait();
3595
  breakpoints_barriers->barrier_2.Wait();
3596
  CompileRun(source_2);
3597
}
3598

    
3599

    
3600
void BreakpointsDebuggerThread::Run() {
3601
  const int kBufSize = 1000;
3602
  uint16_t buffer[kBufSize];
3603

    
3604
  const char* command_1 = "{\"seq\":101,"
3605
      "\"type\":\"request\","
3606
      "\"command\":\"setbreakpoint\","
3607
      "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
3608
  const char* command_2 = "{\"seq\":102,"
3609
      "\"type\":\"request\","
3610
      "\"command\":\"setbreakpoint\","
3611
      "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
3612
  const char* command_3 = "{\"seq\":104,"
3613
      "\"type\":\"request\","
3614
      "\"command\":\"evaluate\","
3615
      "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
3616
  const char* command_4 = "{\"seq\":105,"
3617
      "\"type\":\"request\","
3618
      "\"command\":\"evaluate\","
3619
      "\"arguments\":{\"expression\":\"x\",\"disable_break\":true}}";
3620
  const char* command_5 = "{\"seq\":106,"
3621
      "\"type\":\"request\","
3622
      "\"command\":\"continue\"}";
3623
  const char* command_6 = "{\"seq\":107,"
3624
      "\"type\":\"request\","
3625
      "\"command\":\"continue\"}";
3626
  const char* command_7 = "{\"seq\":108,"
3627
     "\"type\":\"request\","
3628
     "\"command\":\"evaluate\","
3629
     "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
3630
  const char* command_8 = "{\"seq\":109,"
3631
      "\"type\":\"request\","
3632
      "\"command\":\"continue\"}";
3633

    
3634

    
3635
  // v8 thread initializes, runs source_1
3636
  breakpoints_barriers->barrier_1.Wait();
3637
  // 1:Set breakpoint in cat().
3638
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_1, buffer));
3639
  // 2:Set breakpoint in dog()
3640
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_2, buffer));
3641
  breakpoints_barriers->barrier_2.Wait();
3642
  // v8 thread starts compiling source_2.
3643
  // Automatic break happens, to run queued commands
3644
  // breakpoints_barriers->semaphore_1->Wait();
3645
  // Commands 1 through 3 run, thread continues.
3646
  // v8 thread runs source_2 to breakpoint in cat().
3647
  // message callback receives break event.
3648
  breakpoints_barriers->semaphore_1->Wait();
3649
  // 4:Evaluate dog() (which has a breakpoint).
3650
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_3, buffer));
3651
  // v8 thread hits breakpoint in dog()
3652
  breakpoints_barriers->semaphore_1->Wait();  // wait for break event
3653
  // 5:Evaluate x
3654
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_4, buffer));
3655
  // 6:Continue evaluation of dog()
3656
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_5, buffer));
3657
  // dog() finishes.
3658
  // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
3659
  // in cat(19).
3660
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_6, buffer));
3661
  // message callback gets break event
3662
  breakpoints_barriers->semaphore_1->Wait();  // wait for break event
3663
  // 8: Evaluate dog() with breaks disabled
3664
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_7, buffer));
3665
  // 9: Continue evaluation of source2, reach end.
3666
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_8, buffer));
3667
}
3668

    
3669
BreakpointsDebuggerThread breakpoints_debugger_thread;
3670
BreakpointsV8Thread breakpoints_v8_thread;
3671

    
3672
TEST(RecursiveBreakpoints) {
3673
  i::FLAG_debugger_auto_break = true;
3674

    
3675
  // Create a V8 environment
3676
  Barriers stack_allocated_breakpoints_barriers;
3677
  stack_allocated_breakpoints_barriers.Initialize();
3678
  breakpoints_barriers = &stack_allocated_breakpoints_barriers;
3679

    
3680
  breakpoints_v8_thread.Start();
3681
  breakpoints_debugger_thread.Start();
3682

    
3683
  breakpoints_v8_thread.Join();
3684
  breakpoints_debugger_thread.Join();
3685
}
3686

    
3687

    
3688
static void DummyDebugEventListener(v8::DebugEvent event,
3689
                                    v8::Handle<v8::Object> exec_state,
3690
                                    v8::Handle<v8::Object> event_data,
3691
                                    v8::Handle<v8::Value> data) {
3692
}
3693

    
3694

    
3695
TEST(SetDebugEventListenerOnUninitializedVM) {
3696
  v8::Debug::SetDebugEventListener(DummyDebugEventListener);
3697
}
3698

    
3699

    
3700
static void DummyMessageHandler(const uint16_t* message,
3701
                                int length, void *data) {
3702
}
3703

    
3704

    
3705
TEST(SetMessageHandlerOnUninitializedVM) {
3706
  v8::Debug::SetMessageHandler(DummyMessageHandler);
3707
}
3708

    
3709

    
3710
TEST(DebugBreakOnUninitializedVM) {
3711
  v8::Debug::DebugBreak();
3712
}
3713

    
3714

    
3715
TEST(SendCommandToUninitializedVM) {
3716
  const char* dummy_command = "{}";
3717
  uint16_t dummy_buffer[80];
3718
  int dummy_length = AsciiToUtf16(dummy_command, dummy_buffer);
3719
  v8::Debug::SendCommand(dummy_buffer, dummy_length);
3720
}
3721

    
3722

    
3723
// Source for a JavaScript function which returns the data parameter of a
3724
// function called in the context of the debugger. If no data parameter is
3725
// passed it throws an exception.
3726
static const char* debugger_call_with_data_source =
3727
    "function debugger_call_with_data(exec_state, data) {"
3728
    "  if (data) return data;"
3729
    "  throw 'No data!'"
3730
    "}";
3731
v8::Handle<v8::Function> debugger_call_with_data;
3732

    
3733

    
3734
// Source for a JavaScript function which returns the data parameter of a
3735
// function called in the context of the debugger. If no data parameter is
3736
// passed it throws an exception.
3737
static const char* debugger_call_with_closure_source =
3738
    "var x = 3;"
3739
    "function (exec_state) {"
3740
    "  if (exec_state.y) return x - 1;"
3741
    "  exec_state.y = x;"
3742
    "  return exec_state.y"
3743
    "}";
3744
v8::Handle<v8::Function> debugger_call_with_closure;
3745

    
3746
// Function to retrieve the number of JavaScript frames by calling a JavaScript
3747
// in the debugger.
3748
static v8::Handle<v8::Value> CheckFrameCount(const v8::Arguments& args) {
3749
  CHECK(v8::Debug::Call(frame_count)->IsNumber());
3750
  CHECK_EQ(args[0]->Int32Value(),
3751
           v8::Debug::Call(frame_count)->Int32Value());
3752
  return v8::Undefined();
3753
}
3754

    
3755

    
3756
// Function to retrieve the source line of the top JavaScript frame by calling a
3757
// JavaScript function in the debugger.
3758
static v8::Handle<v8::Value> CheckSourceLine(const v8::Arguments& args) {
3759
  CHECK(v8::Debug::Call(frame_source_line)->IsNumber());
3760
  CHECK_EQ(args[0]->Int32Value(),
3761
           v8::Debug::Call(frame_source_line)->Int32Value());
3762
  return v8::Undefined();
3763
}
3764

    
3765

    
3766
// Function to test passing an additional parameter to a JavaScript function
3767
// called in the debugger. It also tests that functions called in the debugger
3768
// can throw exceptions.
3769
static v8::Handle<v8::Value> CheckDataParameter(const v8::Arguments& args) {
3770
  v8::Handle<v8::String> data = v8::String::New("Test");
3771
  CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString());
3772

    
3773
  CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
3774
  CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
3775

    
3776
  v8::TryCatch catcher;
3777
  v8::Debug::Call(debugger_call_with_data);
3778
  CHECK(catcher.HasCaught());
3779
  CHECK(catcher.Exception()->IsString());
3780

    
3781
  return v8::Undefined();
3782
}
3783

    
3784

    
3785
// Function to test using a JavaScript with closure in the debugger.
3786
static v8::Handle<v8::Value> CheckClosure(const v8::Arguments& args) {
3787
  CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber());
3788
  CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value());
3789
  return v8::Undefined();
3790
}
3791

    
3792

    
3793
// Test functions called through the debugger.
3794
TEST(CallFunctionInDebugger) {
3795
  // Create and enter a context with the functions CheckFrameCount,
3796
  // CheckSourceLine and CheckDataParameter installed.
3797
  v8::HandleScope scope;
3798
  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
3799
  global_template->Set(v8::String::New("CheckFrameCount"),
3800
                       v8::FunctionTemplate::New(CheckFrameCount));
3801
  global_template->Set(v8::String::New("CheckSourceLine"),
3802
                       v8::FunctionTemplate::New(CheckSourceLine));
3803
  global_template->Set(v8::String::New("CheckDataParameter"),
3804
                       v8::FunctionTemplate::New(CheckDataParameter));
3805
  global_template->Set(v8::String::New("CheckClosure"),
3806
                       v8::FunctionTemplate::New(CheckClosure));
3807
  v8::Handle<v8::Context> context = v8::Context::New(NULL, global_template);
3808
  v8::Context::Scope context_scope(context);
3809

    
3810
  // Compile a function for checking the number of JavaScript frames.
3811
  v8::Script::Compile(v8::String::New(frame_count_source))->Run();
3812
  frame_count = v8::Local<v8::Function>::Cast(
3813
      context->Global()->Get(v8::String::New("frame_count")));
3814

    
3815
  // Compile a function for returning the source line for the top frame.
3816
  v8::Script::Compile(v8::String::New(frame_source_line_source))->Run();
3817
  frame_source_line = v8::Local<v8::Function>::Cast(
3818
      context->Global()->Get(v8::String::New("frame_source_line")));
3819

    
3820
  // Compile a function returning the data parameter.
3821
  v8::Script::Compile(v8::String::New(debugger_call_with_data_source))->Run();
3822
  debugger_call_with_data = v8::Local<v8::Function>::Cast(
3823
      context->Global()->Get(v8::String::New("debugger_call_with_data")));
3824

    
3825
  // Compile a function capturing closure.
3826
  debugger_call_with_closure = v8::Local<v8::Function>::Cast(
3827
      v8::Script::Compile(
3828
          v8::String::New(debugger_call_with_closure_source))->Run());
3829

    
3830
  // Calling a function through the debugger returns undefined if there are no
3831
  // JavaScript frames.
3832
  CHECK(v8::Debug::Call(frame_count)->IsUndefined());
3833
  CHECK(v8::Debug::Call(frame_source_line)->IsUndefined());
3834
  CHECK(v8::Debug::Call(debugger_call_with_data)->IsUndefined());
3835

    
3836
  // Test that the number of frames can be retrieved.
3837
  v8::Script::Compile(v8::String::New("CheckFrameCount(1)"))->Run();
3838
  v8::Script::Compile(v8::String::New("function f() {"
3839
                                      "  CheckFrameCount(2);"
3840
                                      "}; f()"))->Run();
3841

    
3842
  // Test that the source line can be retrieved.
3843
  v8::Script::Compile(v8::String::New("CheckSourceLine(0)"))->Run();
3844
  v8::Script::Compile(v8::String::New("function f() {\n"
3845
                                      "  CheckSourceLine(1)\n"
3846
                                      "  CheckSourceLine(2)\n"
3847
                                      "  CheckSourceLine(3)\n"
3848
                                      "}; f()"))->Run();
3849

    
3850
  // Test that a parameter can be passed to a function called in the debugger.
3851
  v8::Script::Compile(v8::String::New("CheckDataParameter()"))->Run();
3852

    
3853
  // Test that a function with closure can be run in the debugger.
3854
  v8::Script::Compile(v8::String::New("CheckClosure()"))->Run();
3855

    
3856

    
3857
  // Test that the source line is correct when there is a line offset.
3858
  v8::ScriptOrigin origin(v8::String::New("test"),
3859
                          v8::Integer::New(7));
3860
  v8::Script::Compile(v8::String::New("CheckSourceLine(7)"), &origin)->Run();
3861
  v8::Script::Compile(v8::String::New("function f() {\n"
3862
                                      "  CheckSourceLine(8)\n"
3863
                                      "  CheckSourceLine(9)\n"
3864
                                      "  CheckSourceLine(10)\n"
3865
                                      "}; f()"), &origin)->Run();
3866
}
3867

    
3868

    
3869
// Test that clearing the debug event listener actually clears all break points
3870
// and related information.
3871
TEST(DebuggerUnload) {
3872
  v8::HandleScope scope;
3873
  DebugLocalContext env;
3874

    
3875
  // Check debugger is unloaded before it is used.
3876
  CheckDebuggerUnloaded();
3877

    
3878
  // Add debug event listener.
3879
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
3880
                                   v8::Undefined());
3881
  // Create a couple of functions for the test.
3882
  v8::Local<v8::Function> foo =
3883
      CompileFunction(&env, "function foo(){x=1}", "foo");
3884
  v8::Local<v8::Function> bar =
3885
      CompileFunction(&env, "function bar(){y=2}", "bar");
3886

    
3887
  // Set some break points.
3888
  SetBreakPoint(foo, 0);
3889
  SetBreakPoint(foo, 4);
3890
  SetBreakPoint(bar, 0);
3891
  SetBreakPoint(bar, 4);
3892

    
3893
  // Make sure that the break points are there.
3894
  break_point_hit_count = 0;
3895
  foo->Call(env->Global(), 0, NULL);
3896
  CHECK_EQ(2, break_point_hit_count);
3897
  bar->Call(env->Global(), 0, NULL);
3898
  CHECK_EQ(4, break_point_hit_count);
3899

    
3900
  // Remove the debug event listener without clearing breakpoints.
3901
  v8::Debug::SetDebugEventListener(NULL);
3902
  CheckDebuggerUnloaded(true);
3903

    
3904
  // Set a new debug event listener.
3905
  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
3906
                                   v8::Undefined());
3907
  // Check that the break points was actually cleared.
3908
  break_point_hit_count = 0;
3909
  foo->Call(env->Global(), 0, NULL);
3910
  CHECK_EQ(0, break_point_hit_count);
3911

    
3912
  // Set break points and run again.
3913
  SetBreakPoint(foo, 0);
3914
  SetBreakPoint(foo, 4);
3915
  foo->Call(env->Global(), 0, NULL);
3916
  CHECK_EQ(2, break_point_hit_count);
3917

    
3918
  // Remove the debug event listener without clearing breakpoints again.
3919
  v8::Debug::SetDebugEventListener(NULL);
3920
  CheckDebuggerUnloaded(true);
3921
}
3922

    
3923

    
3924
// Debugger message handler which counts the number of times it is called.
3925
static int message_handler_hit_count = 0;
3926
static void MessageHandlerHitCount(const uint16_t* message,
3927
                                   int length, void* data) {
3928
  message_handler_hit_count++;
3929

    
3930
  const int kBufferSize = 1000;
3931
  uint16_t buffer[kBufferSize];
3932
  const char* command_continue =
3933
    "{\"seq\":0,"
3934
     "\"type\":\"request\","
3935
     "\"command\":\"continue\"}";
3936

    
3937
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
3938
}
3939

    
3940

    
3941
// Test clearing the debug message handler.
3942
TEST(DebuggerClearMessageHandler) {
3943
  v8::HandleScope scope;
3944
  DebugLocalContext env;
3945

    
3946
  // Check debugger is unloaded before it is used.
3947
  CheckDebuggerUnloaded();
3948

    
3949
  // Set a debug message handler.
3950
  v8::Debug::SetMessageHandler(MessageHandlerHitCount);
3951

    
3952
  // Run code to throw a unhandled exception. This should end up in the message
3953
  // handler.
3954
  CompileRun("throw 1");
3955

    
3956
  // The message handler should be called.
3957
  CHECK_GT(message_handler_hit_count, 0);
3958

    
3959
  // Clear debug message handler.
3960
  message_handler_hit_count = 0;
3961
  v8::Debug::SetMessageHandler(NULL);
3962

    
3963
  // Run code to throw a unhandled exception. This should end up in the message
3964
  // handler.
3965
  CompileRun("throw 1");
3966

    
3967
  // The message handler should not be called more.
3968
  CHECK_EQ(0, message_handler_hit_count);
3969

    
3970
  CheckDebuggerUnloaded(true);
3971
}
3972

    
3973

    
3974
// Debugger message handler which clears the message handler while active.
3975
static void MessageHandlerClearingMessageHandler(const uint16_t* message,
3976
                                                 int length,
3977
                                                 void* data) {
3978
  message_handler_hit_count++;
3979

    
3980
  // Clear debug message handler.
3981
  v8::Debug::SetMessageHandler(NULL);
3982
}
3983

    
3984

    
3985
// Test clearing the debug message handler while processing a debug event.
3986
TEST(DebuggerClearMessageHandlerWhileActive) {
3987
  v8::HandleScope scope;
3988
  DebugLocalContext env;
3989

    
3990
  // Check debugger is unloaded before it is used.
3991
  CheckDebuggerUnloaded();
3992

    
3993
  // Set a debug message handler.
3994
  v8::Debug::SetMessageHandler(MessageHandlerClearingMessageHandler);
3995

    
3996
  // Run code to throw a unhandled exception. This should end up in the message
3997
  // handler.
3998
  CompileRun("throw 1");
3999

    
4000
  // The message handler should be called.
4001
  CHECK_EQ(1, message_handler_hit_count);
4002

    
4003
  CheckDebuggerUnloaded(true);
4004
}
4005

    
4006

    
4007
int host_dispatch_hit_count = 0;
4008
static void HostDispatchHandlerHitCount(void* dispatch, void *data) {
4009
  host_dispatch_hit_count++;
4010
}
4011

    
4012

    
4013
// Test that clearing the debug event listener actually clears all break points
4014
// and related information.
4015
TEST(DebuggerHostDispatch) {
4016
  i::FLAG_debugger_auto_break = true;
4017

    
4018
  v8::HandleScope scope;
4019
  DebugLocalContext env;
4020

    
4021
  const int kBufferSize = 1000;
4022
  uint16_t buffer[kBufferSize];
4023
  const char* command_continue =
4024
    "{\"seq\":0,"
4025
     "\"type\":\"request\","
4026
     "\"command\":\"continue\"}";
4027

    
4028
  // Create an empty function to call for processing debug commands
4029
  v8::Local<v8::Function> empty =
4030
      CompileFunction(&env, "function empty(){}", "empty");
4031

    
4032
  // Setup message and host dispatch handlers.
4033
  v8::Debug::SetMessageHandler(DummyMessageHandler);
4034
  v8::Debug::SetHostDispatchHandler(HostDispatchHandlerHitCount,
4035
                                    NULL);
4036

    
4037
  // Send a host dispatch by itself.
4038
  v8::Debug::SendHostDispatch(NULL);
4039
  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
4040
  CHECK_EQ(1, host_dispatch_hit_count);
4041

    
4042
  // Fill a host dispatch and a continue command on the command queue.
4043
  v8::Debug::SendHostDispatch(NULL);
4044
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
4045
  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
4046

    
4047
  // Fill a continue command and a host dispatch on the command queue.
4048
  v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
4049
  v8::Debug::SendHostDispatch(NULL);
4050
  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
4051
  empty->Call(env->Global(), 0, NULL);  // Run JavaScript to activate debugger.
4052

    
4053
  // All the host dispatch callback should be called.
4054
  CHECK_EQ(3, host_dispatch_hit_count);
4055
}
4056

    
4057

    
4058
TEST(DebuggerAgent) {
4059
  // Make sure this port is not used by other tests to allow tests to run in
4060
  // parallel.
4061
  const int kPort = 5858;
4062

    
4063
  // Make a string with the port number.
4064
  const int kPortBufferLen = 6;
4065
  char port_str[kPortBufferLen];
4066
  OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
4067

    
4068
  bool ok;
4069

    
4070
  // Initialize the socket library.
4071
  i::Socket::Setup();
4072

    
4073
  // Test starting and stopping the agent without any client connection.
4074
  i::Debugger::StartAgent("test", kPort);
4075
  i::Debugger::StopAgent();
4076

    
4077
  // Test starting the agent, connecting a client and shutting down the agent
4078
  // with the client connected.
4079
  ok = i::Debugger::StartAgent("test", kPort);
4080
  CHECK(ok);
4081
  i::Socket* client = i::OS::CreateSocket();
4082
  ok = client->Connect("localhost", port_str);
4083
  CHECK(ok);
4084
  i::Debugger::StopAgent();
4085
  delete client;
4086

    
4087
  // Test starting and stopping the agent with the required port already
4088
  // occoupied.
4089
  i::Socket* server = i::OS::CreateSocket();
4090
  server->Bind(kPort);
4091

    
4092
  i::Debugger::StartAgent("test", kPort);
4093
  i::Debugger::StopAgent();
4094

    
4095
  delete server;
4096
}
4097

    
4098

    
4099
class DebuggerAgentProtocolServerThread : public i::Thread {
4100
 public:
4101
  explicit DebuggerAgentProtocolServerThread(int port)
4102
      : port_(port), server_(NULL), client_(NULL),
4103
        listening_(OS::CreateSemaphore(0)) {
4104
  }
4105
  ~DebuggerAgentProtocolServerThread() {
4106
    // Close both sockets.
4107
    delete client_;
4108
    delete server_;
4109
    delete listening_;
4110
  }
4111

    
4112
  void Run();
4113
  void WaitForListening() { listening_->Wait(); }
4114
  char* body() { return *body_; }
4115

    
4116
 private:
4117
  int port_;
4118
  i::SmartPointer<char> body_;
4119
  i::Socket* server_;  // Server socket used for bind/accept.
4120
  i::Socket* client_;  // Single client connection used by the test.
4121
  i::Semaphore* listening_;  // Signalled when the server is in listen mode.
4122
};
4123

    
4124

    
4125
void DebuggerAgentProtocolServerThread::Run() {
4126
  bool ok;
4127

    
4128
  // Create the server socket and bind it to the requested port.
4129
  server_ = i::OS::CreateSocket();
4130
  CHECK(server_ != NULL);
4131
  ok = server_->Bind(port_);
4132
  CHECK(ok);
4133

    
4134
  // Listen for new connections.
4135
  ok = server_->Listen(1);
4136
  CHECK(ok);
4137
  listening_->Signal();
4138

    
4139
  // Accept a connection.
4140
  client_ = server_->Accept();
4141
  CHECK(client_ != NULL);
4142

    
4143
  // Receive a debugger agent protocol message.
4144
  i::DebuggerAgentUtil::ReceiveMessage(client_);
4145
}
4146

    
4147

    
4148
TEST(DebuggerAgentProtocolOverflowHeader) {
4149
  // Make sure this port is not used by other tests to allow tests to run in
4150
  // parallel.
4151
  const int kPort = 5860;
4152
  static const char* kLocalhost = "localhost";
4153

    
4154
  // Make a string with the port number.
4155
  const int kPortBufferLen = 6;
4156
  char port_str[kPortBufferLen];
4157
  OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
4158

    
4159
  // Initialize the socket library.
4160
  i::Socket::Setup();
4161

    
4162
  // Create a socket server to receive a debugger agent message.
4163
  DebuggerAgentProtocolServerThread* server =
4164
      new DebuggerAgentProtocolServerThread(kPort);
4165
  server->Start();
4166
  server->WaitForListening();
4167

    
4168
  // Connect.
4169
  i::Socket* client = i::OS::CreateSocket();
4170
  CHECK(client != NULL);
4171
  bool ok = client->Connect(kLocalhost, port_str);
4172
  CHECK(ok);
4173

    
4174
  // Send headers which overflow the receive buffer.
4175
  static const int kBufferSize = 1000;
4176
  char buffer[kBufferSize];
4177

    
4178
  // Long key and short value: XXXX....XXXX:0\r\n.
4179
  for (int i = 0; i < kBufferSize - 4; i++) {
4180
    buffer[i] = 'X';
4181
  }
4182
  buffer[kBufferSize - 4] = ':';
4183
  buffer[kBufferSize - 3] = '0';
4184
  buffer[kBufferSize - 2] = '\r';
4185
  buffer[kBufferSize - 1] = '\n';
4186
  client->Send(buffer, kBufferSize);
4187

    
4188
  // Short key and long value: X:XXXX....XXXX\r\n.
4189
  buffer[0] = 'X';
4190
  buffer[1] = ':';
4191
  for (int i = 2; i < kBufferSize - 2; i++) {
4192
    buffer[i] = 'X';
4193
  }
4194
  buffer[kBufferSize - 2] = '\r';
4195
  buffer[kBufferSize - 1] = '\n';
4196
  client->Send(buffer, kBufferSize);
4197

    
4198
  // Add empty body to request.
4199
  const char* content_length_zero_header = "Content-Length:0\r\n";
4200
  client->Send(content_length_zero_header, strlen(content_length_zero_header));
4201
  client->Send("\r\n", 2);
4202

    
4203
  // Wait until data is received.
4204
  server->Join();
4205

    
4206
  // Check for empty body.
4207
  CHECK(server->body() == NULL);
4208

    
4209
  // Close the client before the server to avoid TIME_WAIT issues.
4210
  client->Shutdown();
4211
  delete client;
4212
  delete server;
4213
}
4214

    
4215

    
4216
// Test for issue http://code.google.com/p/v8/issues/detail?id=289.
4217
// Make sure that DebugGetLoadedScripts doesn't return scripts
4218
// with disposed external source.
4219
class EmptyExternalStringResource : public v8::String::ExternalStringResource {
4220
 public:
4221
  EmptyExternalStringResource() { empty_[0] = 0; }
4222
  virtual ~EmptyExternalStringResource() {}
4223
  virtual size_t length() const { return empty_.length(); }
4224
  virtual const uint16_t* data() const { return empty_.start(); }
4225
 private:
4226
  ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
4227
};
4228

    
4229

    
4230
TEST(DebugGetLoadedScripts) {
4231
  v8::HandleScope scope;
4232
  DebugLocalContext env;
4233
  EmptyExternalStringResource source_ext_str;
4234
  v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
4235
  v8::Handle<v8::Script> evil_script = v8::Script::Compile(source);
4236
  Handle<i::ExternalTwoByteString> i_source(
4237
      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
4238
  // This situation can happen if source was an external string disposed
4239
  // by its owner.
4240
  i_source->set_resource(0);
4241

    
4242
  bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
4243
  i::FLAG_allow_natives_syntax = true;
4244
  CompileRun(
4245
      "var scripts = %DebugGetLoadedScripts();"
4246
      "for (var i = 0; i < scripts.length; ++i) {"
4247
      "    scripts[i].line_ends;"
4248
      "}");
4249
  // Must not crash while accessing line_ends.
4250
  i::FLAG_allow_natives_syntax = allow_natives_syntax;
4251
}