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 @ f230a1cf

History | View | Annotate | Download (250 KB)

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

    
28
#ifdef ENABLE_DEBUGGER_SUPPORT
29

    
30
#include <stdlib.h>
31

    
32
#include "v8.h"
33

    
34
#include "api.h"
35
#include "cctest.h"
36
#include "compilation-cache.h"
37
#include "debug.h"
38
#include "deoptimizer.h"
39
#include "frames.h"
40
#include "platform.h"
41
#include "platform/condition-variable.h"
42
#include "platform/socket.h"
43
#include "stub-cache.h"
44
#include "utils.h"
45

    
46

    
47
using ::v8::internal::Mutex;
48
using ::v8::internal::LockGuard;
49
using ::v8::internal::ConditionVariable;
50
using ::v8::internal::Semaphore;
51
using ::v8::internal::EmbeddedVector;
52
using ::v8::internal::Object;
53
using ::v8::internal::OS;
54
using ::v8::internal::Handle;
55
using ::v8::internal::Heap;
56
using ::v8::internal::JSGlobalProxy;
57
using ::v8::internal::Code;
58
using ::v8::internal::Debug;
59
using ::v8::internal::Debugger;
60
using ::v8::internal::CommandMessage;
61
using ::v8::internal::CommandMessageQueue;
62
using ::v8::internal::StackFrame;
63
using ::v8::internal::StepAction;
64
using ::v8::internal::StepIn;  // From StepAction enum
65
using ::v8::internal::StepNext;  // From StepAction enum
66
using ::v8::internal::StepOut;  // From StepAction enum
67
using ::v8::internal::Vector;
68
using ::v8::internal::StrLength;
69

    
70
// Size of temp buffer for formatting small strings.
71
#define SMALL_STRING_BUFFER_SIZE 80
72

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

    
75

    
76
// Helper function used by the CHECK_EQ function when given Address
77
// arguments.  Should not be called directly.
78
static inline void CheckEqualsHelper(const char* file, int line,
79
                                     const char* expected_source,
80
                                     ::v8::internal::Address expected,
81
                                     const char* value_source,
82
                                     ::v8::internal::Address value) {
83
  if (expected != value) {
84
    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n#   "
85
                         "Expected: %i\n#   Found: %i",
86
             expected_source, value_source, expected, value);
87
  }
88
}
89

    
90

    
91
// Helper function used by the CHECK_NE function when given Address
92
// arguments.  Should not be called directly.
93
static inline void CheckNonEqualsHelper(const char* file, int line,
94
                                        const char* unexpected_source,
95
                                        ::v8::internal::Address unexpected,
96
                                        const char* value_source,
97
                                        ::v8::internal::Address value) {
98
  if (unexpected == value) {
99
    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %i",
100
             unexpected_source, value_source, value);
101
  }
102
}
103

    
104

    
105
// Helper function used by the CHECK function when given code
106
// arguments.  Should not be called directly.
107
static inline void CheckEqualsHelper(const char* file, int line,
108
                                     const char* expected_source,
109
                                     const Code* expected,
110
                                     const char* value_source,
111
                                     const Code* value) {
112
  if (expected != value) {
113
    V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n#   "
114
                         "Expected: %p\n#   Found: %p",
115
             expected_source, value_source, expected, value);
116
  }
117
}
118

    
119

    
120
static inline void CheckNonEqualsHelper(const char* file, int line,
121
                                        const char* expected_source,
122
                                        const Code* expected,
123
                                        const char* value_source,
124
                                        const Code* value) {
125
  if (expected == value) {
126
    V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
127
             expected_source, value_source, value);
128
  }
129
}
130

    
131

    
132
// --- H e l p e r   C l a s s e s
133

    
134

    
135
// Helper class for creating a V8 enviromnent for running tests
136
class DebugLocalContext {
137
 public:
138
  inline DebugLocalContext(
139
      v8::ExtensionConfiguration* extensions = 0,
140
      v8::Handle<v8::ObjectTemplate> global_template =
141
          v8::Handle<v8::ObjectTemplate>(),
142
      v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
143
      : scope_(CcTest::isolate()),
144
        context_(
145
          v8::Context::New(CcTest::isolate(),
146
                           extensions,
147
                           global_template,
148
                           global_object)) {
149
    context_->Enter();
150
  }
151
  inline ~DebugLocalContext() {
152
    context_->Exit();
153
  }
154
  inline v8::Local<v8::Context> context() { return context_; }
155
  inline v8::Context* operator->() { return *context_; }
156
  inline v8::Context* operator*() { return *context_; }
157
  inline bool IsReady() { return !context_.IsEmpty(); }
158
  void ExposeDebug() {
159
    v8::internal::Isolate* isolate =
160
        reinterpret_cast<v8::internal::Isolate*>(context_->GetIsolate());
161
    v8::internal::Factory* factory = isolate->factory();
162
    v8::internal::Debug* debug = isolate->debug();
163
    // Expose the debug context global object in the global object for testing.
164
    debug->Load();
165
    debug->debug_context()->set_security_token(
166
        v8::Utils::OpenHandle(*context_)->security_token());
167

    
168
    Handle<JSGlobalProxy> global(Handle<JSGlobalProxy>::cast(
169
        v8::Utils::OpenHandle(*context_->Global())));
170
    Handle<v8::internal::String> debug_string =
171
        factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("debug"));
172
    SetProperty(isolate, global, debug_string,
173
                Handle<Object>(debug->debug_context()->global_proxy(), isolate),
174
                DONT_ENUM,
175
                ::v8::internal::kNonStrictMode);
176
  }
177

    
178
 private:
179
  v8::HandleScope scope_;
180
  v8::Local<v8::Context> context_;
181
};
182

    
183

    
184
// --- H e l p e r   F u n c t i o n s
185

    
186

    
187
// Compile and run the supplied source and return the fequested function.
188
static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
189
                                               const char* source,
190
                                               const char* function_name) {
191
  v8::Script::Compile(v8::String::New(source))->Run();
192
  return v8::Local<v8::Function>::Cast(
193
      (*env)->Global()->Get(v8::String::New(function_name)));
194
}
195

    
196

    
197
// Compile and run the supplied source and return the requested function.
198
static v8::Local<v8::Function> CompileFunction(const char* source,
199
                                               const char* function_name) {
200
  v8::Script::Compile(v8::String::New(source))->Run();
201
  v8::Local<v8::Object> global =
202
      CcTest::isolate()->GetCurrentContext()->Global();
203
  return v8::Local<v8::Function>::Cast(
204
      global->Get(v8::String::New(function_name)));
205
}
206

    
207

    
208
// Is there any debug info for the function?
209
static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
210
  Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
211
  Handle<v8::internal::SharedFunctionInfo> shared(f->shared());
212
  return Debug::HasDebugInfo(shared);
213
}
214

    
215

    
216
// Set a break point in a function and return the associated break point
217
// number.
218
static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
219
  static int break_point = 0;
220
  v8::internal::Isolate* isolate = fun->GetIsolate();
221
  v8::internal::Debug* debug = isolate->debug();
222
  debug->SetBreakPoint(
223
      fun,
224
      Handle<Object>(v8::internal::Smi::FromInt(++break_point), isolate),
225
      &position);
226
  return break_point;
227
}
228

    
229

    
230
// Set a break point in a function and return the associated break point
231
// number.
232
static int SetBreakPoint(v8::Handle<v8::Function> fun, int position) {
233
  return SetBreakPoint(v8::Utils::OpenHandle(*fun), position);
234
}
235

    
236

    
237
// Set a break point in a function using the Debug object and return the
238
// associated break point number.
239
static int SetBreakPointFromJS(const char* function_name,
240
                               int line, int position) {
241
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
242
  OS::SNPrintF(buffer,
243
               "debug.Debug.setBreakPoint(%s,%d,%d)",
244
               function_name, line, position);
245
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
246
  v8::Handle<v8::String> str = v8::String::New(buffer.start());
247
  return v8::Script::Compile(str)->Run()->Int32Value();
248
}
249

    
250

    
251
// Set a break point in a script identified by id using the global Debug object.
252
static int SetScriptBreakPointByIdFromJS(int script_id, int line, int column) {
253
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
254
  if (column >= 0) {
255
    // Column specified set script break point on precise location.
256
    OS::SNPrintF(buffer,
257
                 "debug.Debug.setScriptBreakPointById(%d,%d,%d)",
258
                 script_id, line, column);
259
  } else {
260
    // Column not specified set script break point on line.
261
    OS::SNPrintF(buffer,
262
                 "debug.Debug.setScriptBreakPointById(%d,%d)",
263
                 script_id, line);
264
  }
265
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
266
  {
267
    v8::TryCatch try_catch;
268
    v8::Handle<v8::String> str = v8::String::New(buffer.start());
269
    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
270
    CHECK(!try_catch.HasCaught());
271
    return value->Int32Value();
272
  }
273
}
274

    
275

    
276
// Set a break point in a script identified by name using the global Debug
277
// object.
278
static int SetScriptBreakPointByNameFromJS(const char* script_name,
279
                                           int line, int column) {
280
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
281
  if (column >= 0) {
282
    // Column specified set script break point on precise location.
283
    OS::SNPrintF(buffer,
284
                 "debug.Debug.setScriptBreakPointByName(\"%s\",%d,%d)",
285
                 script_name, line, column);
286
  } else {
287
    // Column not specified set script break point on line.
288
    OS::SNPrintF(buffer,
289
                 "debug.Debug.setScriptBreakPointByName(\"%s\",%d)",
290
                 script_name, line);
291
  }
292
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
293
  {
294
    v8::TryCatch try_catch;
295
    v8::Handle<v8::String> str = v8::String::New(buffer.start());
296
    v8::Handle<v8::Value> value = v8::Script::Compile(str)->Run();
297
    CHECK(!try_catch.HasCaught());
298
    return value->Int32Value();
299
  }
300
}
301

    
302

    
303
// Clear a break point.
304
static void ClearBreakPoint(int break_point) {
305
  v8::internal::Isolate* isolate = CcTest::i_isolate();
306
  v8::internal::Debug* debug = isolate->debug();
307
  debug->ClearBreakPoint(
308
      Handle<Object>(v8::internal::Smi::FromInt(break_point), isolate));
309
}
310

    
311

    
312
// Clear a break point using the global Debug object.
313
static void ClearBreakPointFromJS(int break_point_number) {
314
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
315
  OS::SNPrintF(buffer,
316
               "debug.Debug.clearBreakPoint(%d)",
317
               break_point_number);
318
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
319
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
320
}
321

    
322

    
323
static void EnableScriptBreakPointFromJS(int break_point_number) {
324
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
325
  OS::SNPrintF(buffer,
326
               "debug.Debug.enableScriptBreakPoint(%d)",
327
               break_point_number);
328
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
329
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
330
}
331

    
332

    
333
static void DisableScriptBreakPointFromJS(int break_point_number) {
334
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
335
  OS::SNPrintF(buffer,
336
               "debug.Debug.disableScriptBreakPoint(%d)",
337
               break_point_number);
338
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
339
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
340
}
341

    
342

    
343
static void ChangeScriptBreakPointConditionFromJS(int break_point_number,
344
                                                  const char* condition) {
345
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
346
  OS::SNPrintF(buffer,
347
               "debug.Debug.changeScriptBreakPointCondition(%d, \"%s\")",
348
               break_point_number, condition);
349
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
350
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
351
}
352

    
353

    
354
static void ChangeScriptBreakPointIgnoreCountFromJS(int break_point_number,
355
                                                    int ignoreCount) {
356
  EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
357
  OS::SNPrintF(buffer,
358
               "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
359
               break_point_number, ignoreCount);
360
  buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
361
  v8::Script::Compile(v8::String::New(buffer.start()))->Run();
362
}
363

    
364

    
365
// Change break on exception.
366
static void ChangeBreakOnException(bool caught, bool uncaught) {
367
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
368
  debug->ChangeBreakOnException(v8::internal::BreakException, caught);
369
  debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
370
}
371

    
372

    
373
// Change break on exception using the global Debug object.
374
static void ChangeBreakOnExceptionFromJS(bool caught, bool uncaught) {
375
  if (caught) {
376
    v8::Script::Compile(
377
        v8::String::New("debug.Debug.setBreakOnException()"))->Run();
378
  } else {
379
    v8::Script::Compile(
380
        v8::String::New("debug.Debug.clearBreakOnException()"))->Run();
381
  }
382
  if (uncaught) {
383
    v8::Script::Compile(
384
        v8::String::New("debug.Debug.setBreakOnUncaughtException()"))->Run();
385
  } else {
386
    v8::Script::Compile(
387
        v8::String::New("debug.Debug.clearBreakOnUncaughtException()"))->Run();
388
  }
389
}
390

    
391

    
392
// Prepare to step to next break location.
393
static void PrepareStep(StepAction step_action) {
394
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
395
  debug->PrepareStep(step_action, 1, StackFrame::NO_ID);
396
}
397

    
398

    
399
// This function is in namespace v8::internal to be friend with class
400
// v8::internal::Debug.
401
namespace v8 {
402
namespace internal {
403

    
404
// Collect the currently debugged functions.
405
Handle<FixedArray> GetDebuggedFunctions() {
406
  Debug* debug = CcTest::i_isolate()->debug();
407

    
408
  v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
409

    
410
  // Find the number of debugged functions.
411
  int count = 0;
412
  while (node) {
413
    count++;
414
    node = node->next();
415
  }
416

    
417
  // Allocate array for the debugged functions
418
  Handle<FixedArray> debugged_functions =
419
      CcTest::i_isolate()->factory()->NewFixedArray(count);
420

    
421
  // Run through the debug info objects and collect all functions.
422
  count = 0;
423
  while (node) {
424
    debugged_functions->set(count++, *node->debug_info());
425
    node = node->next();
426
  }
427

    
428
  return debugged_functions;
429
}
430

    
431

    
432
static Handle<Code> ComputeCallDebugBreak(int argc) {
433
  return CcTest::i_isolate()->stub_cache()->ComputeCallDebugBreak(argc,
434
                                                                 Code::CALL_IC);
435
}
436

    
437

    
438
// Check that the debugger has been fully unloaded.
439
void CheckDebuggerUnloaded(bool check_functions) {
440
  // Check that the debugger context is cleared and that there is no debug
441
  // information stored for the debugger.
442
  CHECK(CcTest::i_isolate()->debug()->debug_context().is_null());
443
  CHECK_EQ(NULL, CcTest::i_isolate()->debug()->debug_info_list_);
444

    
445
  // Collect garbage to ensure weak handles are cleared.
446
  CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
447
  CcTest::heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
448

    
449
  // Iterate the head and check that there are no debugger related objects left.
450
  HeapIterator iterator(CcTest::heap());
451
  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
452
    CHECK(!obj->IsDebugInfo());
453
    CHECK(!obj->IsBreakPointInfo());
454

    
455
    // If deep check of functions is requested check that no debug break code
456
    // is left in all functions.
457
    if (check_functions) {
458
      if (obj->IsJSFunction()) {
459
        JSFunction* fun = JSFunction::cast(obj);
460
        for (RelocIterator it(fun->shared()->code()); !it.done(); it.next()) {
461
          RelocInfo::Mode rmode = it.rinfo()->rmode();
462
          if (RelocInfo::IsCodeTarget(rmode)) {
463
            CHECK(!Debug::IsDebugBreak(it.rinfo()->target_address()));
464
          } else if (RelocInfo::IsJSReturn(rmode)) {
465
            CHECK(!Debug::IsDebugBreakAtReturn(it.rinfo()));
466
          }
467
        }
468
      }
469
    }
470
  }
471
}
472

    
473

    
474
void ForceUnloadDebugger() {
475
  CcTest::i_isolate()->debugger()->never_unload_debugger_ = false;
476
  CcTest::i_isolate()->debugger()->UnloadDebugger();
477
}
478

    
479

    
480
} }  // namespace v8::internal
481

    
482

    
483
// Check that the debugger has been fully unloaded.
484
static void CheckDebuggerUnloaded(bool check_functions = false) {
485
  // Let debugger to unload itself synchronously
486
  v8::Debug::ProcessDebugMessages();
487

    
488
  v8::internal::CheckDebuggerUnloaded(check_functions);
489
}
490

    
491

    
492
// Inherit from BreakLocationIterator to get access to protected parts for
493
// testing.
494
class TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
495
 public:
496
  explicit TestBreakLocationIterator(Handle<v8::internal::DebugInfo> debug_info)
497
    : BreakLocationIterator(debug_info, v8::internal::SOURCE_BREAK_LOCATIONS) {}
498
  v8::internal::RelocIterator* it() { return reloc_iterator_; }
499
  v8::internal::RelocIterator* it_original() {
500
    return reloc_iterator_original_;
501
  }
502
};
503

    
504

    
505
// Compile a function, set a break point and check that the call at the break
506
// location in the code is the expected debug_break function.
507
void CheckDebugBreakFunction(DebugLocalContext* env,
508
                             const char* source, const char* name,
509
                             int position, v8::internal::RelocInfo::Mode mode,
510
                             Code* debug_break) {
511
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
512

    
513
  // Create function and set the break point.
514
  Handle<v8::internal::JSFunction> fun = v8::Utils::OpenHandle(
515
      *CompileFunction(env, source, name));
516
  int bp = SetBreakPoint(fun, position);
517

    
518
  // Check that the debug break function is as expected.
519
  Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
520
  CHECK(Debug::HasDebugInfo(shared));
521
  TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
522
  it1.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
523
  v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode();
524
  if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
525
    actual_mode = v8::internal::RelocInfo::CODE_TARGET;
526
  }
527
  CHECK_EQ(mode, actual_mode);
528
  if (mode != v8::internal::RelocInfo::JS_RETURN) {
529
    CHECK_EQ(debug_break,
530
        Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
531
  } else {
532
    CHECK(Debug::IsDebugBreakAtReturn(it1.it()->rinfo()));
533
  }
534

    
535
  // Clear the break point and check that the debug break function is no longer
536
  // there
537
  ClearBreakPoint(bp);
538
  CHECK(!debug->HasDebugInfo(shared));
539
  CHECK(debug->EnsureDebugInfo(shared, fun));
540
  TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
541
  it2.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
542
  actual_mode = it2.it()->rinfo()->rmode();
543
  if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
544
    actual_mode = v8::internal::RelocInfo::CODE_TARGET;
545
  }
546
  CHECK_EQ(mode, actual_mode);
547
  if (mode == v8::internal::RelocInfo::JS_RETURN) {
548
    CHECK(!Debug::IsDebugBreakAtReturn(it2.it()->rinfo()));
549
  }
550
}
551

    
552

    
553
// --- D e b u g   E v e n t   H a n d l e r s
554
// ---
555
// --- The different tests uses a number of debug event handlers.
556
// ---
557

    
558

    
559
// Source for the JavaScript function which picks out the function
560
// name of a frame.
561
const char* frame_function_name_source =
562
    "function frame_function_name(exec_state, frame_number) {"
563
    "  return exec_state.frame(frame_number).func().name();"
564
    "}";
565
v8::Local<v8::Function> frame_function_name;
566

    
567

    
568
// Source for the JavaScript function which pick out the name of the
569
// first argument of a frame.
570
const char* frame_argument_name_source =
571
    "function frame_argument_name(exec_state, frame_number) {"
572
    "  return exec_state.frame(frame_number).argumentName(0);"
573
    "}";
574
v8::Local<v8::Function> frame_argument_name;
575

    
576

    
577
// Source for the JavaScript function which pick out the value of the
578
// first argument of a frame.
579
const char* frame_argument_value_source =
580
    "function frame_argument_value(exec_state, frame_number) {"
581
    "  return exec_state.frame(frame_number).argumentValue(0).value_;"
582
    "}";
583
v8::Local<v8::Function> frame_argument_value;
584

    
585

    
586
// Source for the JavaScript function which pick out the name of the
587
// first argument of a frame.
588
const char* frame_local_name_source =
589
    "function frame_local_name(exec_state, frame_number) {"
590
    "  return exec_state.frame(frame_number).localName(0);"
591
    "}";
592
v8::Local<v8::Function> frame_local_name;
593

    
594

    
595
// Source for the JavaScript function which pick out the value of the
596
// first argument of a frame.
597
const char* frame_local_value_source =
598
    "function frame_local_value(exec_state, frame_number) {"
599
    "  return exec_state.frame(frame_number).localValue(0).value_;"
600
    "}";
601
v8::Local<v8::Function> frame_local_value;
602

    
603

    
604
// Source for the JavaScript function which picks out the source line for the
605
// top frame.
606
const char* frame_source_line_source =
607
    "function frame_source_line(exec_state) {"
608
    "  return exec_state.frame(0).sourceLine();"
609
    "}";
610
v8::Local<v8::Function> frame_source_line;
611

    
612

    
613
// Source for the JavaScript function which picks out the source column for the
614
// top frame.
615
const char* frame_source_column_source =
616
    "function frame_source_column(exec_state) {"
617
    "  return exec_state.frame(0).sourceColumn();"
618
    "}";
619
v8::Local<v8::Function> frame_source_column;
620

    
621

    
622
// Source for the JavaScript function which picks out the script name for the
623
// top frame.
624
const char* frame_script_name_source =
625
    "function frame_script_name(exec_state) {"
626
    "  return exec_state.frame(0).func().script().name();"
627
    "}";
628
v8::Local<v8::Function> frame_script_name;
629

    
630

    
631
// Source for the JavaScript function which picks out the script data for the
632
// top frame.
633
const char* frame_script_data_source =
634
    "function frame_script_data(exec_state) {"
635
    "  return exec_state.frame(0).func().script().data();"
636
    "}";
637
v8::Local<v8::Function> frame_script_data;
638

    
639

    
640
// Source for the JavaScript function which picks out the script data from
641
// AfterCompile event
642
const char* compiled_script_data_source =
643
    "function compiled_script_data(event_data) {"
644
    "  return event_data.script().data();"
645
    "}";
646
v8::Local<v8::Function> compiled_script_data;
647

    
648

    
649
// Source for the JavaScript function which returns the number of frames.
650
static const char* frame_count_source =
651
    "function frame_count(exec_state) {"
652
    "  return exec_state.frameCount();"
653
    "}";
654
v8::Handle<v8::Function> frame_count;
655

    
656

    
657
// Global variable to store the last function hit - used by some tests.
658
char last_function_hit[80];
659

    
660
// Global variable to store the name and data for last script hit - used by some
661
// tests.
662
char last_script_name_hit[80];
663
char last_script_data_hit[80];
664

    
665
// Global variables to store the last source position - used by some tests.
666
int last_source_line = -1;
667
int last_source_column = -1;
668

    
669
// Debug event handler which counts the break points which have been hit.
670
int break_point_hit_count = 0;
671
int break_point_hit_count_deoptimize = 0;
672
static void DebugEventBreakPointHitCount(
673
    const v8::Debug::EventDetails& event_details) {
674
  v8::DebugEvent event = event_details.GetEvent();
675
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
676
  v8::Handle<v8::Object> event_data = event_details.GetEventData();
677
  v8::internal::Isolate* isolate = CcTest::i_isolate();
678
  Debug* debug = isolate->debug();
679
  // When hitting a debug event listener there must be a break set.
680
  CHECK_NE(debug->break_id(), 0);
681

    
682
  // Count the number of breaks.
683
  if (event == v8::Break) {
684
    break_point_hit_count++;
685
    if (!frame_function_name.IsEmpty()) {
686
      // Get the name of the function.
687
      const int argc = 2;
688
      v8::Handle<v8::Value> argv[argc] = { exec_state, v8::Integer::New(0) };
689
      v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
690
                                                               argc, argv);
691
      if (result->IsUndefined()) {
692
        last_function_hit[0] = '\0';
693
      } else {
694
        CHECK(result->IsString());
695
        v8::Handle<v8::String> function_name(result->ToString());
696
        function_name->WriteUtf8(last_function_hit);
697
      }
698
    }
699

    
700
    if (!frame_source_line.IsEmpty()) {
701
      // Get the source line.
702
      const int argc = 1;
703
      v8::Handle<v8::Value> argv[argc] = { exec_state };
704
      v8::Handle<v8::Value> result = frame_source_line->Call(exec_state,
705
                                                             argc, argv);
706
      CHECK(result->IsNumber());
707
      last_source_line = result->Int32Value();
708
    }
709

    
710
    if (!frame_source_column.IsEmpty()) {
711
      // Get the source column.
712
      const int argc = 1;
713
      v8::Handle<v8::Value> argv[argc] = { exec_state };
714
      v8::Handle<v8::Value> result = frame_source_column->Call(exec_state,
715
                                                               argc, argv);
716
      CHECK(result->IsNumber());
717
      last_source_column = result->Int32Value();
718
    }
719

    
720
    if (!frame_script_name.IsEmpty()) {
721
      // Get the script name of the function script.
722
      const int argc = 1;
723
      v8::Handle<v8::Value> argv[argc] = { exec_state };
724
      v8::Handle<v8::Value> result = frame_script_name->Call(exec_state,
725
                                                             argc, argv);
726
      if (result->IsUndefined()) {
727
        last_script_name_hit[0] = '\0';
728
      } else {
729
        CHECK(result->IsString());
730
        v8::Handle<v8::String> script_name(result->ToString());
731
        script_name->WriteUtf8(last_script_name_hit);
732
      }
733
    }
734

    
735
    if (!frame_script_data.IsEmpty()) {
736
      // Get the script data of the function script.
737
      const int argc = 1;
738
      v8::Handle<v8::Value> argv[argc] = { exec_state };
739
      v8::Handle<v8::Value> result = frame_script_data->Call(exec_state,
740
                                                             argc, argv);
741
      if (result->IsUndefined()) {
742
        last_script_data_hit[0] = '\0';
743
      } else {
744
        result = result->ToString();
745
        CHECK(result->IsString());
746
        v8::Handle<v8::String> script_data(result->ToString());
747
        script_data->WriteUtf8(last_script_data_hit);
748
      }
749
    }
750

    
751
    // Perform a full deoptimization when the specified number of
752
    // breaks have been hit.
753
    if (break_point_hit_count == break_point_hit_count_deoptimize) {
754
      i::Deoptimizer::DeoptimizeAll(isolate);
755
    }
756
  } else if (event == v8::AfterCompile && !compiled_script_data.IsEmpty()) {
757
    const int argc = 1;
758
    v8::Handle<v8::Value> argv[argc] = { event_data };
759
    v8::Handle<v8::Value> result = compiled_script_data->Call(exec_state,
760
                                                              argc, argv);
761
    if (result->IsUndefined()) {
762
      last_script_data_hit[0] = '\0';
763
    } else {
764
      result = result->ToString();
765
      CHECK(result->IsString());
766
      v8::Handle<v8::String> script_data(result->ToString());
767
      script_data->WriteUtf8(last_script_data_hit);
768
    }
769
  }
770
}
771

    
772

    
773
// Debug event handler which counts a number of events and collects the stack
774
// height if there is a function compiled for that.
775
int exception_hit_count = 0;
776
int uncaught_exception_hit_count = 0;
777
int last_js_stack_height = -1;
778

    
779
static void DebugEventCounterClear() {
780
  break_point_hit_count = 0;
781
  exception_hit_count = 0;
782
  uncaught_exception_hit_count = 0;
783
}
784

    
785
static void DebugEventCounter(
786
    const v8::Debug::EventDetails& event_details) {
787
  v8::DebugEvent event = event_details.GetEvent();
788
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
789
  v8::Handle<v8::Object> event_data = event_details.GetEventData();
790
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
791

    
792
  // When hitting a debug event listener there must be a break set.
793
  CHECK_NE(debug->break_id(), 0);
794

    
795
  // Count the number of breaks.
796
  if (event == v8::Break) {
797
    break_point_hit_count++;
798
  } else if (event == v8::Exception) {
799
    exception_hit_count++;
800

    
801
    // Check whether the exception was uncaught.
802
    v8::Local<v8::String> fun_name = v8::String::New("uncaught");
803
    v8::Local<v8::Function> fun =
804
        v8::Local<v8::Function>::Cast(event_data->Get(fun_name));
805
    v8::Local<v8::Value> result = fun->Call(event_data, 0, NULL);
806
    if (result->IsTrue()) {
807
      uncaught_exception_hit_count++;
808
    }
809
  }
810

    
811
  // Collect the JavsScript stack height if the function frame_count is
812
  // compiled.
813
  if (!frame_count.IsEmpty()) {
814
    static const int kArgc = 1;
815
    v8::Handle<v8::Value> argv[kArgc] = { exec_state };
816
    // Using exec_state as receiver is just to have a receiver.
817
    v8::Handle<v8::Value> result =  frame_count->Call(exec_state, kArgc, argv);
818
    last_js_stack_height = result->Int32Value();
819
  }
820
}
821

    
822

    
823
// Debug event handler which evaluates a number of expressions when a break
824
// point is hit. Each evaluated expression is compared with an expected value.
825
// For this debug event handler to work the following two global varaibles
826
// must be initialized.
827
//   checks: An array of expressions and expected results
828
//   evaluate_check_function: A JavaScript function (see below)
829

    
830
// Structure for holding checks to do.
831
struct EvaluateCheck {
832
  const char* expr;  // An expression to evaluate when a break point is hit.
833
  v8::Handle<v8::Value> expected;  // The expected result.
834
};
835

    
836

    
837
// Array of checks to do.
838
struct EvaluateCheck* checks = NULL;
839
// Source for The JavaScript function which can do the evaluation when a break
840
// point is hit.
841
const char* evaluate_check_source =
842
    "function evaluate_check(exec_state, expr, expected) {"
843
    "  return exec_state.frame(0).evaluate(expr).value() === expected;"
844
    "}";
845
v8::Local<v8::Function> evaluate_check_function;
846

    
847
// The actual debug event described by the longer comment above.
848
static void DebugEventEvaluate(
849
    const v8::Debug::EventDetails& event_details) {
850
  v8::DebugEvent event = event_details.GetEvent();
851
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
852
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
853
  // When hitting a debug event listener there must be a break set.
854
  CHECK_NE(debug->break_id(), 0);
855

    
856
  if (event == v8::Break) {
857
    for (int i = 0; checks[i].expr != NULL; i++) {
858
      const int argc = 3;
859
      v8::Handle<v8::Value> argv[argc] = { exec_state,
860
                                           v8::String::New(checks[i].expr),
861
                                           checks[i].expected };
862
      v8::Handle<v8::Value> result =
863
          evaluate_check_function->Call(exec_state, argc, argv);
864
      if (!result->IsTrue()) {
865
        v8::String::Utf8Value utf8(checks[i].expected->ToString());
866
        V8_Fatal(__FILE__, __LINE__, "%s != %s", checks[i].expr, *utf8);
867
      }
868
    }
869
  }
870
}
871

    
872

    
873
// This debug event listener removes a breakpoint in a function
874
int debug_event_remove_break_point = 0;
875
static void DebugEventRemoveBreakPoint(
876
    const v8::Debug::EventDetails& event_details) {
877
  v8::DebugEvent event = event_details.GetEvent();
878
  v8::Handle<v8::Value> data = event_details.GetCallbackData();
879
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
880
  // When hitting a debug event listener there must be a break set.
881
  CHECK_NE(debug->break_id(), 0);
882

    
883
  if (event == v8::Break) {
884
    break_point_hit_count++;
885
    CHECK(data->IsFunction());
886
    ClearBreakPoint(debug_event_remove_break_point);
887
  }
888
}
889

    
890

    
891
// Debug event handler which counts break points hit and performs a step
892
// afterwards.
893
StepAction step_action = StepIn;  // Step action to perform when stepping.
894
static void DebugEventStep(
895
    const v8::Debug::EventDetails& event_details) {
896
  v8::DebugEvent event = event_details.GetEvent();
897
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
898
  // When hitting a debug event listener there must be a break set.
899
  CHECK_NE(debug->break_id(), 0);
900

    
901
  if (event == v8::Break) {
902
    break_point_hit_count++;
903
    PrepareStep(step_action);
904
  }
905
}
906

    
907

    
908
// Debug event handler which counts break points hit and performs a step
909
// afterwards. For each call the expected function is checked.
910
// For this debug event handler to work the following two global varaibles
911
// must be initialized.
912
//   expected_step_sequence: An array of the expected function call sequence.
913
//   frame_function_name: A JavaScript function (see below).
914

    
915
// String containing the expected function call sequence. Note: this only works
916
// if functions have name length of one.
917
const char* expected_step_sequence = NULL;
918

    
919
// The actual debug event described by the longer comment above.
920
static void DebugEventStepSequence(
921
    const v8::Debug::EventDetails& event_details) {
922
  v8::DebugEvent event = event_details.GetEvent();
923
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
924
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
925
  // When hitting a debug event listener there must be a break set.
926
  CHECK_NE(debug->break_id(), 0);
927

    
928
  if (event == v8::Break || event == v8::Exception) {
929
    // Check that the current function is the expected.
930
    CHECK(break_point_hit_count <
931
          StrLength(expected_step_sequence));
932
    const int argc = 2;
933
    v8::Handle<v8::Value> argv[argc] = { exec_state, v8::Integer::New(0) };
934
    v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
935
                                                             argc, argv);
936
    CHECK(result->IsString());
937
    v8::String::Utf8Value function_name(result->ToString());
938
    CHECK_EQ(1, StrLength(*function_name));
939
    CHECK_EQ((*function_name)[0],
940
              expected_step_sequence[break_point_hit_count]);
941

    
942
    // Perform step.
943
    break_point_hit_count++;
944
    PrepareStep(step_action);
945
  }
946
}
947

    
948

    
949
// Debug event handler which performs a garbage collection.
950
static void DebugEventBreakPointCollectGarbage(
951
    const v8::Debug::EventDetails& event_details) {
952
  v8::DebugEvent event = event_details.GetEvent();
953
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
954
  // When hitting a debug event listener there must be a break set.
955
  CHECK_NE(debug->break_id(), 0);
956

    
957
  // Perform a garbage collection when break point is hit and continue. Based
958
  // on the number of break points hit either scavenge or mark compact
959
  // collector is used.
960
  if (event == v8::Break) {
961
    break_point_hit_count++;
962
    if (break_point_hit_count % 2 == 0) {
963
      // Scavenge.
964
      CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
965
    } else {
966
      // Mark sweep compact.
967
      CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
968
    }
969
  }
970
}
971

    
972

    
973
// Debug event handler which re-issues a debug break and calls the garbage
974
// collector to have the heap verified.
975
static void DebugEventBreak(
976
    const v8::Debug::EventDetails& event_details) {
977
  v8::DebugEvent event = event_details.GetEvent();
978
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
979
  // When hitting a debug event listener there must be a break set.
980
  CHECK_NE(debug->break_id(), 0);
981

    
982
  if (event == v8::Break) {
983
    // Count the number of breaks.
984
    break_point_hit_count++;
985

    
986
    // Run the garbage collector to enforce heap verification if option
987
    // --verify-heap is set.
988
    CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
989

    
990
    // Set the break flag again to come back here as soon as possible.
991
    v8::Debug::DebugBreak(CcTest::isolate());
992
  }
993
}
994

    
995

    
996
// Debug event handler which re-issues a debug break until a limit has been
997
// reached.
998
int max_break_point_hit_count = 0;
999
bool terminate_after_max_break_point_hit = false;
1000
static void DebugEventBreakMax(
1001
    const v8::Debug::EventDetails& event_details) {
1002
  v8::DebugEvent event = event_details.GetEvent();
1003
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
1004
  v8::Isolate* v8_isolate = CcTest::isolate();
1005
  v8::internal::Isolate* isolate = CcTest::i_isolate();
1006
  v8::internal::Debug* debug = isolate->debug();
1007
  // When hitting a debug event listener there must be a break set.
1008
  CHECK_NE(debug->break_id(), 0);
1009

    
1010
  if (event == v8::Break) {
1011
    if (break_point_hit_count < max_break_point_hit_count) {
1012
      // Count the number of breaks.
1013
      break_point_hit_count++;
1014

    
1015
      // Collect the JavsScript stack height if the function frame_count is
1016
      // compiled.
1017
      if (!frame_count.IsEmpty()) {
1018
        static const int kArgc = 1;
1019
        v8::Handle<v8::Value> argv[kArgc] = { exec_state };
1020
        // Using exec_state as receiver is just to have a receiver.
1021
        v8::Handle<v8::Value> result =
1022
            frame_count->Call(exec_state, kArgc, argv);
1023
        last_js_stack_height = result->Int32Value();
1024
      }
1025

    
1026
      // Set the break flag again to come back here as soon as possible.
1027
      v8::Debug::DebugBreak(v8_isolate);
1028

    
1029
    } else if (terminate_after_max_break_point_hit) {
1030
      // Terminate execution after the last break if requested.
1031
      v8::V8::TerminateExecution(v8_isolate);
1032
    }
1033

    
1034
    // Perform a full deoptimization when the specified number of
1035
    // breaks have been hit.
1036
    if (break_point_hit_count == break_point_hit_count_deoptimize) {
1037
      i::Deoptimizer::DeoptimizeAll(isolate);
1038
    }
1039
  }
1040
}
1041

    
1042

    
1043
// --- M e s s a g e   C a l l b a c k
1044

    
1045

    
1046
// Message callback which counts the number of messages.
1047
int message_callback_count = 0;
1048

    
1049
static void MessageCallbackCountClear() {
1050
  message_callback_count = 0;
1051
}
1052

    
1053
static void MessageCallbackCount(v8::Handle<v8::Message> message,
1054
                                 v8::Handle<v8::Value> data) {
1055
  message_callback_count++;
1056
}
1057

    
1058

    
1059
// --- T h e   A c t u a l   T e s t s
1060

    
1061

    
1062
// Test that the debug break function is the expected one for different kinds
1063
// of break locations.
1064
TEST(DebugStub) {
1065
  using ::v8::internal::Builtins;
1066
  using ::v8::internal::Isolate;
1067
  DebugLocalContext env;
1068
  v8::HandleScope scope(env->GetIsolate());
1069

    
1070
  CheckDebugBreakFunction(&env,
1071
                          "function f1(){}", "f1",
1072
                          0,
1073
                          v8::internal::RelocInfo::JS_RETURN,
1074
                          NULL);
1075
  CheckDebugBreakFunction(&env,
1076
                          "function f2(){x=1;}", "f2",
1077
                          0,
1078
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
1079
                          CcTest::i_isolate()->builtins()->builtin(
1080
                              Builtins::kStoreIC_DebugBreak));
1081
  CheckDebugBreakFunction(&env,
1082
                          "function f3(){var a=x;}", "f3",
1083
                          0,
1084
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
1085
                          CcTest::i_isolate()->builtins()->builtin(
1086
                              Builtins::kLoadIC_DebugBreak));
1087

    
1088
// TODO(1240753): Make the test architecture independent or split
1089
// parts of the debugger into architecture dependent files. This
1090
// part currently disabled as it is not portable between IA32/ARM.
1091
// Currently on ICs for keyed store/load on ARM.
1092
#if !defined (__arm__) && !defined(__thumb__)
1093
  CheckDebugBreakFunction(
1094
      &env,
1095
      "function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
1096
      "f4",
1097
      0,
1098
      v8::internal::RelocInfo::CODE_TARGET,
1099
      CcTest::i_isolate()->builtins()->builtin(
1100
          Builtins::kKeyedStoreIC_DebugBreak));
1101
  CheckDebugBreakFunction(
1102
      &env,
1103
      "function f5(){var index='propertyName'; var a={}; return a[index];}",
1104
      "f5",
1105
      0,
1106
      v8::internal::RelocInfo::CODE_TARGET,
1107
      CcTest::i_isolate()->builtins()->builtin(
1108
          Builtins::kKeyedLoadIC_DebugBreak));
1109
#endif
1110

    
1111
  CheckDebugBreakFunction(
1112
      &env,
1113
      "function f6(a){return a==null;}",
1114
      "f6",
1115
      0,
1116
      v8::internal::RelocInfo::CODE_TARGET,
1117
      CcTest::i_isolate()->builtins()->builtin(
1118
          Builtins::kCompareNilIC_DebugBreak));
1119

    
1120
  // Check the debug break code stubs for call ICs with different number of
1121
  // parameters.
1122
  Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
1123
  Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
1124
  Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
1125

    
1126
  CheckDebugBreakFunction(&env,
1127
                          "function f4_0(){x();}", "f4_0",
1128
                          0,
1129
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
1130
                          *debug_break_0);
1131

    
1132
  CheckDebugBreakFunction(&env,
1133
                          "function f4_1(){x(1);}", "f4_1",
1134
                          0,
1135
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
1136
                          *debug_break_1);
1137

    
1138
  CheckDebugBreakFunction(&env,
1139
                          "function f4_4(){x(1,2,3,4);}", "f4_4",
1140
                          0,
1141
                          v8::internal::RelocInfo::CODE_TARGET_CONTEXT,
1142
                          *debug_break_4);
1143
}
1144

    
1145

    
1146
// Test that the debug info in the VM is in sync with the functions being
1147
// debugged.
1148
TEST(DebugInfo) {
1149
  DebugLocalContext env;
1150
  v8::HandleScope scope(env->GetIsolate());
1151
  // Create a couple of functions for the test.
1152
  v8::Local<v8::Function> foo =
1153
      CompileFunction(&env, "function foo(){}", "foo");
1154
  v8::Local<v8::Function> bar =
1155
      CompileFunction(&env, "function bar(){}", "bar");
1156
  // Initially no functions are debugged.
1157
  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
1158
  CHECK(!HasDebugInfo(foo));
1159
  CHECK(!HasDebugInfo(bar));
1160
  // One function (foo) is debugged.
1161
  int bp1 = SetBreakPoint(foo, 0);
1162
  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
1163
  CHECK(HasDebugInfo(foo));
1164
  CHECK(!HasDebugInfo(bar));
1165
  // Two functions are debugged.
1166
  int bp2 = SetBreakPoint(bar, 0);
1167
  CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
1168
  CHECK(HasDebugInfo(foo));
1169
  CHECK(HasDebugInfo(bar));
1170
  // One function (bar) is debugged.
1171
  ClearBreakPoint(bp1);
1172
  CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
1173
  CHECK(!HasDebugInfo(foo));
1174
  CHECK(HasDebugInfo(bar));
1175
  // No functions are debugged.
1176
  ClearBreakPoint(bp2);
1177
  CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
1178
  CHECK(!HasDebugInfo(foo));
1179
  CHECK(!HasDebugInfo(bar));
1180
}
1181

    
1182

    
1183
// Test that a break point can be set at an IC store location.
1184
TEST(BreakPointICStore) {
1185
  break_point_hit_count = 0;
1186
  DebugLocalContext env;
1187
  v8::HandleScope scope(env->GetIsolate());
1188

    
1189
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1190
  v8::Script::Compile(v8::String::New("function foo(){bar=0;}"))->Run();
1191
  v8::Local<v8::Function> foo =
1192
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1193

    
1194
  // Run without breakpoints.
1195
  foo->Call(env->Global(), 0, NULL);
1196
  CHECK_EQ(0, break_point_hit_count);
1197

    
1198
  // Run with breakpoint
1199
  int bp = SetBreakPoint(foo, 0);
1200
  foo->Call(env->Global(), 0, NULL);
1201
  CHECK_EQ(1, break_point_hit_count);
1202
  foo->Call(env->Global(), 0, NULL);
1203
  CHECK_EQ(2, break_point_hit_count);
1204

    
1205
  // Run without breakpoints.
1206
  ClearBreakPoint(bp);
1207
  foo->Call(env->Global(), 0, NULL);
1208
  CHECK_EQ(2, break_point_hit_count);
1209

    
1210
  v8::Debug::SetDebugEventListener2(NULL);
1211
  CheckDebuggerUnloaded();
1212
}
1213

    
1214

    
1215
// Test that a break point can be set at an IC load location.
1216
TEST(BreakPointICLoad) {
1217
  break_point_hit_count = 0;
1218
  DebugLocalContext env;
1219
  v8::HandleScope scope(env->GetIsolate());
1220
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1221
  v8::Script::Compile(v8::String::New("bar=1"))->Run();
1222
  v8::Script::Compile(v8::String::New("function foo(){var x=bar;}"))->Run();
1223
  v8::Local<v8::Function> foo =
1224
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1225

    
1226
  // Run without breakpoints.
1227
  foo->Call(env->Global(), 0, NULL);
1228
  CHECK_EQ(0, break_point_hit_count);
1229

    
1230
  // Run with breakpoint.
1231
  int bp = SetBreakPoint(foo, 0);
1232
  foo->Call(env->Global(), 0, NULL);
1233
  CHECK_EQ(1, break_point_hit_count);
1234
  foo->Call(env->Global(), 0, NULL);
1235
  CHECK_EQ(2, break_point_hit_count);
1236

    
1237
  // Run without breakpoints.
1238
  ClearBreakPoint(bp);
1239
  foo->Call(env->Global(), 0, NULL);
1240
  CHECK_EQ(2, break_point_hit_count);
1241

    
1242
  v8::Debug::SetDebugEventListener2(NULL);
1243
  CheckDebuggerUnloaded();
1244
}
1245

    
1246

    
1247
// Test that a break point can be set at an IC call location.
1248
TEST(BreakPointICCall) {
1249
  break_point_hit_count = 0;
1250
  DebugLocalContext env;
1251
  v8::HandleScope scope(env->GetIsolate());
1252
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1253
  v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
1254
  v8::Script::Compile(v8::String::New("function foo(){bar();}"))->Run();
1255
  v8::Local<v8::Function> foo =
1256
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1257

    
1258
  // Run without breakpoints.
1259
  foo->Call(env->Global(), 0, NULL);
1260
  CHECK_EQ(0, break_point_hit_count);
1261

    
1262
  // Run with breakpoint
1263
  int bp = SetBreakPoint(foo, 0);
1264
  foo->Call(env->Global(), 0, NULL);
1265
  CHECK_EQ(1, break_point_hit_count);
1266
  foo->Call(env->Global(), 0, NULL);
1267
  CHECK_EQ(2, break_point_hit_count);
1268

    
1269
  // Run without breakpoints.
1270
  ClearBreakPoint(bp);
1271
  foo->Call(env->Global(), 0, NULL);
1272
  CHECK_EQ(2, break_point_hit_count);
1273

    
1274
  v8::Debug::SetDebugEventListener2(NULL);
1275
  CheckDebuggerUnloaded();
1276
}
1277

    
1278

    
1279
// Test that a break point can be set at an IC call location and survive a GC.
1280
TEST(BreakPointICCallWithGC) {
1281
  break_point_hit_count = 0;
1282
  DebugLocalContext env;
1283
  v8::HandleScope scope(env->GetIsolate());
1284
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage);
1285
  v8::Script::Compile(v8::String::New("function bar(){return 1;}"))->Run();
1286
  v8::Script::Compile(v8::String::New("function foo(){return bar();}"))->Run();
1287
  v8::Local<v8::Function> foo =
1288
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1289

    
1290
  // Run without breakpoints.
1291
  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1292
  CHECK_EQ(0, break_point_hit_count);
1293

    
1294
  // Run with breakpoint.
1295
  int bp = SetBreakPoint(foo, 0);
1296
  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1297
  CHECK_EQ(1, break_point_hit_count);
1298
  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1299
  CHECK_EQ(2, break_point_hit_count);
1300

    
1301
  // Run without breakpoints.
1302
  ClearBreakPoint(bp);
1303
  foo->Call(env->Global(), 0, NULL);
1304
  CHECK_EQ(2, break_point_hit_count);
1305

    
1306
  v8::Debug::SetDebugEventListener2(NULL);
1307
  CheckDebuggerUnloaded();
1308
}
1309

    
1310

    
1311
// Test that a break point can be set at an IC call location and survive a GC.
1312
TEST(BreakPointConstructCallWithGC) {
1313
  break_point_hit_count = 0;
1314
  DebugLocalContext env;
1315
  v8::HandleScope scope(env->GetIsolate());
1316
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage);
1317
  v8::Script::Compile(v8::String::New("function bar(){ this.x = 1;}"))->Run();
1318
  v8::Script::Compile(v8::String::New(
1319
      "function foo(){return new bar(1).x;}"))->Run();
1320
  v8::Local<v8::Function> foo =
1321
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1322

    
1323
  // Run without breakpoints.
1324
  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1325
  CHECK_EQ(0, break_point_hit_count);
1326

    
1327
  // Run with breakpoint.
1328
  int bp = SetBreakPoint(foo, 0);
1329
  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1330
  CHECK_EQ(1, break_point_hit_count);
1331
  CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
1332
  CHECK_EQ(2, break_point_hit_count);
1333

    
1334
  // Run without breakpoints.
1335
  ClearBreakPoint(bp);
1336
  foo->Call(env->Global(), 0, NULL);
1337
  CHECK_EQ(2, break_point_hit_count);
1338

    
1339
  v8::Debug::SetDebugEventListener2(NULL);
1340
  CheckDebuggerUnloaded();
1341
}
1342

    
1343

    
1344
// Test that a break point can be set at a return store location.
1345
TEST(BreakPointReturn) {
1346
  break_point_hit_count = 0;
1347
  DebugLocalContext env;
1348
  v8::HandleScope scope(env->GetIsolate());
1349

    
1350
  // Create a functions for checking the source line and column when hitting
1351
  // a break point.
1352
  frame_source_line = CompileFunction(&env,
1353
                                      frame_source_line_source,
1354
                                      "frame_source_line");
1355
  frame_source_column = CompileFunction(&env,
1356
                                        frame_source_column_source,
1357
                                        "frame_source_column");
1358

    
1359

    
1360
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1361
  v8::Script::Compile(v8::String::New("function foo(){}"))->Run();
1362
  v8::Local<v8::Function> foo =
1363
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
1364

    
1365
  // Run without breakpoints.
1366
  foo->Call(env->Global(), 0, NULL);
1367
  CHECK_EQ(0, break_point_hit_count);
1368

    
1369
  // Run with breakpoint
1370
  int bp = SetBreakPoint(foo, 0);
1371
  foo->Call(env->Global(), 0, NULL);
1372
  CHECK_EQ(1, break_point_hit_count);
1373
  CHECK_EQ(0, last_source_line);
1374
  CHECK_EQ(15, last_source_column);
1375
  foo->Call(env->Global(), 0, NULL);
1376
  CHECK_EQ(2, break_point_hit_count);
1377
  CHECK_EQ(0, last_source_line);
1378
  CHECK_EQ(15, last_source_column);
1379

    
1380
  // Run without breakpoints.
1381
  ClearBreakPoint(bp);
1382
  foo->Call(env->Global(), 0, NULL);
1383
  CHECK_EQ(2, break_point_hit_count);
1384

    
1385
  v8::Debug::SetDebugEventListener2(NULL);
1386
  CheckDebuggerUnloaded();
1387
}
1388

    
1389

    
1390
static void CallWithBreakPoints(v8::Local<v8::Object> recv,
1391
                                v8::Local<v8::Function> f,
1392
                                int break_point_count,
1393
                                int call_count) {
1394
  break_point_hit_count = 0;
1395
  for (int i = 0; i < call_count; i++) {
1396
    f->Call(recv, 0, NULL);
1397
    CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
1398
  }
1399
}
1400

    
1401

    
1402
// Test GC during break point processing.
1403
TEST(GCDuringBreakPointProcessing) {
1404
  break_point_hit_count = 0;
1405
  DebugLocalContext env;
1406
  v8::HandleScope scope(env->GetIsolate());
1407

    
1408
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage);
1409
  v8::Local<v8::Function> foo;
1410

    
1411
  // Test IC store break point with garbage collection.
1412
  foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1413
  SetBreakPoint(foo, 0);
1414
  CallWithBreakPoints(env->Global(), foo, 1, 10);
1415

    
1416
  // Test IC load break point with garbage collection.
1417
  foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1418
  SetBreakPoint(foo, 0);
1419
  CallWithBreakPoints(env->Global(), foo, 1, 10);
1420

    
1421
  // Test IC call break point with garbage collection.
1422
  foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
1423
  SetBreakPoint(foo, 0);
1424
  CallWithBreakPoints(env->Global(), foo, 1, 10);
1425

    
1426
  // Test return break point with garbage collection.
1427
  foo = CompileFunction(&env, "function foo(){}", "foo");
1428
  SetBreakPoint(foo, 0);
1429
  CallWithBreakPoints(env->Global(), foo, 1, 25);
1430

    
1431
  // Test debug break slot break point with garbage collection.
1432
  foo = CompileFunction(&env, "function foo(){var a;}", "foo");
1433
  SetBreakPoint(foo, 0);
1434
  CallWithBreakPoints(env->Global(), foo, 1, 25);
1435

    
1436
  v8::Debug::SetDebugEventListener2(NULL);
1437
  CheckDebuggerUnloaded();
1438
}
1439

    
1440

    
1441
// Call the function three times with different garbage collections in between
1442
// and make sure that the break point survives.
1443
static void CallAndGC(v8::Local<v8::Object> recv,
1444
                      v8::Local<v8::Function> f) {
1445
  break_point_hit_count = 0;
1446

    
1447
  for (int i = 0; i < 3; i++) {
1448
    // Call function.
1449
    f->Call(recv, 0, NULL);
1450
    CHECK_EQ(1 + i * 3, break_point_hit_count);
1451

    
1452
    // Scavenge and call function.
1453
    CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
1454
    f->Call(recv, 0, NULL);
1455
    CHECK_EQ(2 + i * 3, break_point_hit_count);
1456

    
1457
    // Mark sweep (and perhaps compact) and call function.
1458
    CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
1459
    f->Call(recv, 0, NULL);
1460
    CHECK_EQ(3 + i * 3, break_point_hit_count);
1461
  }
1462
}
1463

    
1464

    
1465
// Test that a break point can be set at a return store location.
1466
TEST(BreakPointSurviveGC) {
1467
  break_point_hit_count = 0;
1468
  DebugLocalContext env;
1469
  v8::HandleScope scope(env->GetIsolate());
1470

    
1471
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1472
  v8::Local<v8::Function> foo;
1473

    
1474
  // Test IC store break point with garbage collection.
1475
  {
1476
    CompileFunction(&env, "function foo(){}", "foo");
1477
    foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
1478
    SetBreakPoint(foo, 0);
1479
  }
1480
  CallAndGC(env->Global(), foo);
1481

    
1482
  // Test IC load break point with garbage collection.
1483
  {
1484
    CompileFunction(&env, "function foo(){}", "foo");
1485
    foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
1486
    SetBreakPoint(foo, 0);
1487
  }
1488
  CallAndGC(env->Global(), foo);
1489

    
1490
  // Test IC call break point with garbage collection.
1491
  {
1492
    CompileFunction(&env, "function foo(){}", "foo");
1493
    foo = CompileFunction(&env,
1494
                          "function bar(){};function foo(){bar();}",
1495
                          "foo");
1496
    SetBreakPoint(foo, 0);
1497
  }
1498
  CallAndGC(env->Global(), foo);
1499

    
1500
  // Test return break point with garbage collection.
1501
  {
1502
    CompileFunction(&env, "function foo(){}", "foo");
1503
    foo = CompileFunction(&env, "function foo(){}", "foo");
1504
    SetBreakPoint(foo, 0);
1505
  }
1506
  CallAndGC(env->Global(), foo);
1507

    
1508
  // Test non IC break point with garbage collection.
1509
  {
1510
    CompileFunction(&env, "function foo(){}", "foo");
1511
    foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
1512
    SetBreakPoint(foo, 0);
1513
  }
1514
  CallAndGC(env->Global(), foo);
1515

    
1516

    
1517
  v8::Debug::SetDebugEventListener2(NULL);
1518
  CheckDebuggerUnloaded();
1519
}
1520

    
1521

    
1522
// Test that break points can be set using the global Debug object.
1523
TEST(BreakPointThroughJavaScript) {
1524
  break_point_hit_count = 0;
1525
  DebugLocalContext env;
1526
  v8::HandleScope scope(env->GetIsolate());
1527
  env.ExposeDebug();
1528

    
1529
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1530
  v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
1531
  v8::Script::Compile(v8::String::New("function foo(){bar();bar();}"))->Run();
1532
  //                                               012345678901234567890
1533
  //                                                         1         2
1534
  // Break points are set at position 3 and 9
1535
  v8::Local<v8::Script> foo = v8::Script::Compile(v8::String::New("foo()"));
1536

    
1537
  // Run without breakpoints.
1538
  foo->Run();
1539
  CHECK_EQ(0, break_point_hit_count);
1540

    
1541
  // Run with one breakpoint
1542
  int bp1 = SetBreakPointFromJS("foo", 0, 3);
1543
  foo->Run();
1544
  CHECK_EQ(1, break_point_hit_count);
1545
  foo->Run();
1546
  CHECK_EQ(2, break_point_hit_count);
1547

    
1548
  // Run with two breakpoints
1549
  int bp2 = SetBreakPointFromJS("foo", 0, 9);
1550
  foo->Run();
1551
  CHECK_EQ(4, break_point_hit_count);
1552
  foo->Run();
1553
  CHECK_EQ(6, break_point_hit_count);
1554

    
1555
  // Run with one breakpoint
1556
  ClearBreakPointFromJS(bp2);
1557
  foo->Run();
1558
  CHECK_EQ(7, break_point_hit_count);
1559
  foo->Run();
1560
  CHECK_EQ(8, break_point_hit_count);
1561

    
1562
  // Run without breakpoints.
1563
  ClearBreakPointFromJS(bp1);
1564
  foo->Run();
1565
  CHECK_EQ(8, break_point_hit_count);
1566

    
1567
  v8::Debug::SetDebugEventListener2(NULL);
1568
  CheckDebuggerUnloaded();
1569

    
1570
  // Make sure that the break point numbers are consecutive.
1571
  CHECK_EQ(1, bp1);
1572
  CHECK_EQ(2, bp2);
1573
}
1574

    
1575

    
1576
// Test that break points on scripts identified by name can be set using the
1577
// global Debug object.
1578
TEST(ScriptBreakPointByNameThroughJavaScript) {
1579
  break_point_hit_count = 0;
1580
  DebugLocalContext env;
1581
  v8::HandleScope scope(env->GetIsolate());
1582
  env.ExposeDebug();
1583

    
1584
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1585

    
1586
  v8::Local<v8::String> script = v8::String::New(
1587
    "function f() {\n"
1588
    "  function h() {\n"
1589
    "    a = 0;  // line 2\n"
1590
    "  }\n"
1591
    "  b = 1;  // line 4\n"
1592
    "  return h();\n"
1593
    "}\n"
1594
    "\n"
1595
    "function g() {\n"
1596
    "  function h() {\n"
1597
    "    a = 0;\n"
1598
    "  }\n"
1599
    "  b = 2;  // line 12\n"
1600
    "  h();\n"
1601
    "  b = 3;  // line 14\n"
1602
    "  f();    // line 15\n"
1603
    "}");
1604

    
1605
  // Compile the script and get the two functions.
1606
  v8::ScriptOrigin origin =
1607
      v8::ScriptOrigin(v8::String::New("test"));
1608
  v8::Script::Compile(script, &origin)->Run();
1609
  v8::Local<v8::Function> f =
1610
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1611
  v8::Local<v8::Function> g =
1612
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
1613

    
1614
  // Call f and g without break points.
1615
  break_point_hit_count = 0;
1616
  f->Call(env->Global(), 0, NULL);
1617
  CHECK_EQ(0, break_point_hit_count);
1618
  g->Call(env->Global(), 0, NULL);
1619
  CHECK_EQ(0, break_point_hit_count);
1620

    
1621
  // Call f and g with break point on line 12.
1622
  int sbp1 = SetScriptBreakPointByNameFromJS("test", 12, 0);
1623
  break_point_hit_count = 0;
1624
  f->Call(env->Global(), 0, NULL);
1625
  CHECK_EQ(0, break_point_hit_count);
1626
  g->Call(env->Global(), 0, NULL);
1627
  CHECK_EQ(1, break_point_hit_count);
1628

    
1629
  // Remove the break point again.
1630
  break_point_hit_count = 0;
1631
  ClearBreakPointFromJS(sbp1);
1632
  f->Call(env->Global(), 0, NULL);
1633
  CHECK_EQ(0, break_point_hit_count);
1634
  g->Call(env->Global(), 0, NULL);
1635
  CHECK_EQ(0, break_point_hit_count);
1636

    
1637
  // Call f and g with break point on line 2.
1638
  int sbp2 = SetScriptBreakPointByNameFromJS("test", 2, 0);
1639
  break_point_hit_count = 0;
1640
  f->Call(env->Global(), 0, NULL);
1641
  CHECK_EQ(1, break_point_hit_count);
1642
  g->Call(env->Global(), 0, NULL);
1643
  CHECK_EQ(2, break_point_hit_count);
1644

    
1645
  // Call f and g with break point on line 2, 4, 12, 14 and 15.
1646
  int sbp3 = SetScriptBreakPointByNameFromJS("test", 4, 0);
1647
  int sbp4 = SetScriptBreakPointByNameFromJS("test", 12, 0);
1648
  int sbp5 = SetScriptBreakPointByNameFromJS("test", 14, 0);
1649
  int sbp6 = SetScriptBreakPointByNameFromJS("test", 15, 0);
1650
  break_point_hit_count = 0;
1651
  f->Call(env->Global(), 0, NULL);
1652
  CHECK_EQ(2, break_point_hit_count);
1653
  g->Call(env->Global(), 0, NULL);
1654
  CHECK_EQ(7, break_point_hit_count);
1655

    
1656
  // Remove all the break points again.
1657
  break_point_hit_count = 0;
1658
  ClearBreakPointFromJS(sbp2);
1659
  ClearBreakPointFromJS(sbp3);
1660
  ClearBreakPointFromJS(sbp4);
1661
  ClearBreakPointFromJS(sbp5);
1662
  ClearBreakPointFromJS(sbp6);
1663
  f->Call(env->Global(), 0, NULL);
1664
  CHECK_EQ(0, break_point_hit_count);
1665
  g->Call(env->Global(), 0, NULL);
1666
  CHECK_EQ(0, break_point_hit_count);
1667

    
1668
  v8::Debug::SetDebugEventListener2(NULL);
1669
  CheckDebuggerUnloaded();
1670

    
1671
  // Make sure that the break point numbers are consecutive.
1672
  CHECK_EQ(1, sbp1);
1673
  CHECK_EQ(2, sbp2);
1674
  CHECK_EQ(3, sbp3);
1675
  CHECK_EQ(4, sbp4);
1676
  CHECK_EQ(5, sbp5);
1677
  CHECK_EQ(6, sbp6);
1678
}
1679

    
1680

    
1681
TEST(ScriptBreakPointByIdThroughJavaScript) {
1682
  break_point_hit_count = 0;
1683
  DebugLocalContext env;
1684
  v8::HandleScope scope(env->GetIsolate());
1685
  env.ExposeDebug();
1686

    
1687
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1688

    
1689
  v8::Local<v8::String> source = v8::String::New(
1690
    "function f() {\n"
1691
    "  function h() {\n"
1692
    "    a = 0;  // line 2\n"
1693
    "  }\n"
1694
    "  b = 1;  // line 4\n"
1695
    "  return h();\n"
1696
    "}\n"
1697
    "\n"
1698
    "function g() {\n"
1699
    "  function h() {\n"
1700
    "    a = 0;\n"
1701
    "  }\n"
1702
    "  b = 2;  // line 12\n"
1703
    "  h();\n"
1704
    "  b = 3;  // line 14\n"
1705
    "  f();    // line 15\n"
1706
    "}");
1707

    
1708
  // Compile the script and get the two functions.
1709
  v8::ScriptOrigin origin =
1710
      v8::ScriptOrigin(v8::String::New("test"));
1711
  v8::Local<v8::Script> script = v8::Script::Compile(source, &origin);
1712
  script->Run();
1713
  v8::Local<v8::Function> f =
1714
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1715
  v8::Local<v8::Function> g =
1716
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
1717

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

    
1721
  // Call f and g without break points.
1722
  break_point_hit_count = 0;
1723
  f->Call(env->Global(), 0, NULL);
1724
  CHECK_EQ(0, break_point_hit_count);
1725
  g->Call(env->Global(), 0, NULL);
1726
  CHECK_EQ(0, break_point_hit_count);
1727

    
1728
  // Call f and g with break point on line 12.
1729
  int sbp1 = SetScriptBreakPointByIdFromJS(script_id, 12, 0);
1730
  break_point_hit_count = 0;
1731
  f->Call(env->Global(), 0, NULL);
1732
  CHECK_EQ(0, break_point_hit_count);
1733
  g->Call(env->Global(), 0, NULL);
1734
  CHECK_EQ(1, break_point_hit_count);
1735

    
1736
  // Remove the break point again.
1737
  break_point_hit_count = 0;
1738
  ClearBreakPointFromJS(sbp1);
1739
  f->Call(env->Global(), 0, NULL);
1740
  CHECK_EQ(0, break_point_hit_count);
1741
  g->Call(env->Global(), 0, NULL);
1742
  CHECK_EQ(0, break_point_hit_count);
1743

    
1744
  // Call f and g with break point on line 2.
1745
  int sbp2 = SetScriptBreakPointByIdFromJS(script_id, 2, 0);
1746
  break_point_hit_count = 0;
1747
  f->Call(env->Global(), 0, NULL);
1748
  CHECK_EQ(1, break_point_hit_count);
1749
  g->Call(env->Global(), 0, NULL);
1750
  CHECK_EQ(2, break_point_hit_count);
1751

    
1752
  // Call f and g with break point on line 2, 4, 12, 14 and 15.
1753
  int sbp3 = SetScriptBreakPointByIdFromJS(script_id, 4, 0);
1754
  int sbp4 = SetScriptBreakPointByIdFromJS(script_id, 12, 0);
1755
  int sbp5 = SetScriptBreakPointByIdFromJS(script_id, 14, 0);
1756
  int sbp6 = SetScriptBreakPointByIdFromJS(script_id, 15, 0);
1757
  break_point_hit_count = 0;
1758
  f->Call(env->Global(), 0, NULL);
1759
  CHECK_EQ(2, break_point_hit_count);
1760
  g->Call(env->Global(), 0, NULL);
1761
  CHECK_EQ(7, break_point_hit_count);
1762

    
1763
  // Remove all the break points again.
1764
  break_point_hit_count = 0;
1765
  ClearBreakPointFromJS(sbp2);
1766
  ClearBreakPointFromJS(sbp3);
1767
  ClearBreakPointFromJS(sbp4);
1768
  ClearBreakPointFromJS(sbp5);
1769
  ClearBreakPointFromJS(sbp6);
1770
  f->Call(env->Global(), 0, NULL);
1771
  CHECK_EQ(0, break_point_hit_count);
1772
  g->Call(env->Global(), 0, NULL);
1773
  CHECK_EQ(0, break_point_hit_count);
1774

    
1775
  v8::Debug::SetDebugEventListener2(NULL);
1776
  CheckDebuggerUnloaded();
1777

    
1778
  // Make sure that the break point numbers are consecutive.
1779
  CHECK_EQ(1, sbp1);
1780
  CHECK_EQ(2, sbp2);
1781
  CHECK_EQ(3, sbp3);
1782
  CHECK_EQ(4, sbp4);
1783
  CHECK_EQ(5, sbp5);
1784
  CHECK_EQ(6, sbp6);
1785
}
1786

    
1787

    
1788
// Test conditional script break points.
1789
TEST(EnableDisableScriptBreakPoint) {
1790
  break_point_hit_count = 0;
1791
  DebugLocalContext env;
1792
  v8::HandleScope scope(env->GetIsolate());
1793
  env.ExposeDebug();
1794

    
1795
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1796

    
1797
  v8::Local<v8::String> script = v8::String::New(
1798
    "function f() {\n"
1799
    "  a = 0;  // line 1\n"
1800
    "};");
1801

    
1802
  // Compile the script and get function f.
1803
  v8::ScriptOrigin origin =
1804
      v8::ScriptOrigin(v8::String::New("test"));
1805
  v8::Script::Compile(script, &origin)->Run();
1806
  v8::Local<v8::Function> f =
1807
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1808

    
1809
  // Set script break point on line 1 (in function f).
1810
  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
1811

    
1812
  // Call f while enabeling and disabling the script break point.
1813
  break_point_hit_count = 0;
1814
  f->Call(env->Global(), 0, NULL);
1815
  CHECK_EQ(1, break_point_hit_count);
1816

    
1817
  DisableScriptBreakPointFromJS(sbp);
1818
  f->Call(env->Global(), 0, NULL);
1819
  CHECK_EQ(1, break_point_hit_count);
1820

    
1821
  EnableScriptBreakPointFromJS(sbp);
1822
  f->Call(env->Global(), 0, NULL);
1823
  CHECK_EQ(2, break_point_hit_count);
1824

    
1825
  DisableScriptBreakPointFromJS(sbp);
1826
  f->Call(env->Global(), 0, NULL);
1827
  CHECK_EQ(2, break_point_hit_count);
1828

    
1829
  // Reload the script and get f again checking that the disabeling survives.
1830
  v8::Script::Compile(script, &origin)->Run();
1831
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1832
  f->Call(env->Global(), 0, NULL);
1833
  CHECK_EQ(2, break_point_hit_count);
1834

    
1835
  EnableScriptBreakPointFromJS(sbp);
1836
  f->Call(env->Global(), 0, NULL);
1837
  CHECK_EQ(3, break_point_hit_count);
1838

    
1839
  v8::Debug::SetDebugEventListener2(NULL);
1840
  CheckDebuggerUnloaded();
1841
}
1842

    
1843

    
1844
// Test conditional script break points.
1845
TEST(ConditionalScriptBreakPoint) {
1846
  break_point_hit_count = 0;
1847
  DebugLocalContext env;
1848
  v8::HandleScope scope(env->GetIsolate());
1849
  env.ExposeDebug();
1850

    
1851
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1852

    
1853
  v8::Local<v8::String> script = v8::String::New(
1854
    "count = 0;\n"
1855
    "function f() {\n"
1856
    "  g(count++);  // line 2\n"
1857
    "};\n"
1858
    "function g(x) {\n"
1859
    "  var a=x;  // line 5\n"
1860
    "};");
1861

    
1862
  // Compile the script and get function f.
1863
  v8::ScriptOrigin origin =
1864
      v8::ScriptOrigin(v8::String::New("test"));
1865
  v8::Script::Compile(script, &origin)->Run();
1866
  v8::Local<v8::Function> f =
1867
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1868

    
1869
  // Set script break point on line 5 (in function g).
1870
  int sbp1 = SetScriptBreakPointByNameFromJS("test", 5, 0);
1871

    
1872
  // Call f with different conditions on the script break point.
1873
  break_point_hit_count = 0;
1874
  ChangeScriptBreakPointConditionFromJS(sbp1, "false");
1875
  f->Call(env->Global(), 0, NULL);
1876
  CHECK_EQ(0, break_point_hit_count);
1877

    
1878
  ChangeScriptBreakPointConditionFromJS(sbp1, "true");
1879
  break_point_hit_count = 0;
1880
  f->Call(env->Global(), 0, NULL);
1881
  CHECK_EQ(1, break_point_hit_count);
1882

    
1883
  ChangeScriptBreakPointConditionFromJS(sbp1, "x % 2 == 0");
1884
  break_point_hit_count = 0;
1885
  for (int i = 0; i < 10; i++) {
1886
    f->Call(env->Global(), 0, NULL);
1887
  }
1888
  CHECK_EQ(5, break_point_hit_count);
1889

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

    
1894
  break_point_hit_count = 0;
1895
  for (int i = 0; i < 10; i++) {
1896
    f->Call(env->Global(), 0, NULL);
1897
  }
1898
  CHECK_EQ(5, break_point_hit_count);
1899

    
1900
  v8::Debug::SetDebugEventListener2(NULL);
1901
  CheckDebuggerUnloaded();
1902
}
1903

    
1904

    
1905
// Test ignore count on script break points.
1906
TEST(ScriptBreakPointIgnoreCount) {
1907
  break_point_hit_count = 0;
1908
  DebugLocalContext env;
1909
  v8::HandleScope scope(env->GetIsolate());
1910
  env.ExposeDebug();
1911

    
1912
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1913

    
1914
  v8::Local<v8::String> script = v8::String::New(
1915
    "function f() {\n"
1916
    "  a = 0;  // line 1\n"
1917
    "};");
1918

    
1919
  // Compile the script and get function f.
1920
  v8::ScriptOrigin origin =
1921
      v8::ScriptOrigin(v8::String::New("test"));
1922
  v8::Script::Compile(script, &origin)->Run();
1923
  v8::Local<v8::Function> f =
1924
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1925

    
1926
  // Set script break point on line 1 (in function f).
1927
  int sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
1928

    
1929
  // Call f with different ignores on the script break point.
1930
  break_point_hit_count = 0;
1931
  ChangeScriptBreakPointIgnoreCountFromJS(sbp, 1);
1932
  f->Call(env->Global(), 0, NULL);
1933
  CHECK_EQ(0, break_point_hit_count);
1934
  f->Call(env->Global(), 0, NULL);
1935
  CHECK_EQ(1, break_point_hit_count);
1936

    
1937
  ChangeScriptBreakPointIgnoreCountFromJS(sbp, 5);
1938
  break_point_hit_count = 0;
1939
  for (int i = 0; i < 10; i++) {
1940
    f->Call(env->Global(), 0, NULL);
1941
  }
1942
  CHECK_EQ(5, break_point_hit_count);
1943

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

    
1948
  break_point_hit_count = 0;
1949
  for (int i = 0; i < 10; i++) {
1950
    f->Call(env->Global(), 0, NULL);
1951
  }
1952
  CHECK_EQ(5, break_point_hit_count);
1953

    
1954
  v8::Debug::SetDebugEventListener2(NULL);
1955
  CheckDebuggerUnloaded();
1956
}
1957

    
1958

    
1959
// Test that script break points survive when a script is reloaded.
1960
TEST(ScriptBreakPointReload) {
1961
  break_point_hit_count = 0;
1962
  DebugLocalContext env;
1963
  v8::HandleScope scope(env->GetIsolate());
1964
  env.ExposeDebug();
1965

    
1966
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
1967

    
1968
  v8::Local<v8::Function> f;
1969
  v8::Local<v8::String> script = v8::String::New(
1970
    "function f() {\n"
1971
    "  function h() {\n"
1972
    "    a = 0;  // line 2\n"
1973
    "  }\n"
1974
    "  b = 1;  // line 4\n"
1975
    "  return h();\n"
1976
    "}");
1977

    
1978
  v8::ScriptOrigin origin_1 = v8::ScriptOrigin(v8::String::New("1"));
1979
  v8::ScriptOrigin origin_2 = v8::ScriptOrigin(v8::String::New("2"));
1980

    
1981
  // Set a script break point before the script is loaded.
1982
  SetScriptBreakPointByNameFromJS("1", 2, 0);
1983

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

    
1988
  // Call f and check that the script break point is active.
1989
  break_point_hit_count = 0;
1990
  f->Call(env->Global(), 0, NULL);
1991
  CHECK_EQ(1, break_point_hit_count);
1992

    
1993
  // Compile the script again with a different script data and get the
1994
  // function.
1995
  v8::Script::Compile(script, &origin_2)->Run();
1996
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
1997

    
1998
  // Call f and check that no break points are set.
1999
  break_point_hit_count = 0;
2000
  f->Call(env->Global(), 0, NULL);
2001
  CHECK_EQ(0, break_point_hit_count);
2002

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

    
2007
  // Call f and check that the script break point is active.
2008
  break_point_hit_count = 0;
2009
  f->Call(env->Global(), 0, NULL);
2010
  CHECK_EQ(1, break_point_hit_count);
2011

    
2012
  v8::Debug::SetDebugEventListener2(NULL);
2013
  CheckDebuggerUnloaded();
2014
}
2015

    
2016

    
2017
// Test when several scripts has the same script data
2018
TEST(ScriptBreakPointMultiple) {
2019
  break_point_hit_count = 0;
2020
  DebugLocalContext env;
2021
  v8::HandleScope scope(env->GetIsolate());
2022
  env.ExposeDebug();
2023

    
2024
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2025

    
2026
  v8::Local<v8::Function> f;
2027
  v8::Local<v8::String> script_f = v8::String::New(
2028
    "function f() {\n"
2029
    "  a = 0;  // line 1\n"
2030
    "}");
2031

    
2032
  v8::Local<v8::Function> g;
2033
  v8::Local<v8::String> script_g = v8::String::New(
2034
    "function g() {\n"
2035
    "  b = 0;  // line 1\n"
2036
    "}");
2037

    
2038
  v8::ScriptOrigin origin =
2039
      v8::ScriptOrigin(v8::String::New("test"));
2040

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

    
2044
  // Compile the scripts with same script data and get the functions.
2045
  v8::Script::Compile(script_f, &origin)->Run();
2046
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
2047
  v8::Script::Compile(script_g, &origin)->Run();
2048
  g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
2049

    
2050
  // Call f and g and check that the script break point is active.
2051
  break_point_hit_count = 0;
2052
  f->Call(env->Global(), 0, NULL);
2053
  CHECK_EQ(1, break_point_hit_count);
2054
  g->Call(env->Global(), 0, NULL);
2055
  CHECK_EQ(2, break_point_hit_count);
2056

    
2057
  // Clear the script break point.
2058
  ClearBreakPointFromJS(sbp);
2059

    
2060
  // Call f and g and check that the script break point is no longer active.
2061
  break_point_hit_count = 0;
2062
  f->Call(env->Global(), 0, NULL);
2063
  CHECK_EQ(0, break_point_hit_count);
2064
  g->Call(env->Global(), 0, NULL);
2065
  CHECK_EQ(0, break_point_hit_count);
2066

    
2067
  // Set script break point with the scripts loaded.
2068
  sbp = SetScriptBreakPointByNameFromJS("test", 1, 0);
2069

    
2070
  // Call f and g and check that the script break point is active.
2071
  break_point_hit_count = 0;
2072
  f->Call(env->Global(), 0, NULL);
2073
  CHECK_EQ(1, break_point_hit_count);
2074
  g->Call(env->Global(), 0, NULL);
2075
  CHECK_EQ(2, break_point_hit_count);
2076

    
2077
  v8::Debug::SetDebugEventListener2(NULL);
2078
  CheckDebuggerUnloaded();
2079
}
2080

    
2081

    
2082
// Test the script origin which has both name and line offset.
2083
TEST(ScriptBreakPointLineOffset) {
2084
  break_point_hit_count = 0;
2085
  DebugLocalContext env;
2086
  v8::HandleScope scope(env->GetIsolate());
2087
  env.ExposeDebug();
2088

    
2089
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2090

    
2091
  v8::Local<v8::Function> f;
2092
  v8::Local<v8::String> script = v8::String::New(
2093
    "function f() {\n"
2094
    "  a = 0;  // line 8 as this script has line offset 7\n"
2095
    "  b = 0;  // line 9 as this script has line offset 7\n"
2096
    "}");
2097

    
2098
  // Create script origin both name and line offset.
2099
  v8::ScriptOrigin origin(v8::String::New("test.html"),
2100
                          v8::Integer::New(7));
2101

    
2102
  // Set two script break points before the script is loaded.
2103
  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 8, 0);
2104
  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 9, 0);
2105

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

    
2110
  // Call f and check that the script break point is active.
2111
  break_point_hit_count = 0;
2112
  f->Call(env->Global(), 0, NULL);
2113
  CHECK_EQ(2, break_point_hit_count);
2114

    
2115
  // Clear the script break points.
2116
  ClearBreakPointFromJS(sbp1);
2117
  ClearBreakPointFromJS(sbp2);
2118

    
2119
  // Call f and check that no script break points are active.
2120
  break_point_hit_count = 0;
2121
  f->Call(env->Global(), 0, NULL);
2122
  CHECK_EQ(0, break_point_hit_count);
2123

    
2124
  // Set a script break point with the script loaded.
2125
  sbp1 = SetScriptBreakPointByNameFromJS("test.html", 9, 0);
2126

    
2127
  // Call f and check that the script break point is active.
2128
  break_point_hit_count = 0;
2129
  f->Call(env->Global(), 0, NULL);
2130
  CHECK_EQ(1, break_point_hit_count);
2131

    
2132
  v8::Debug::SetDebugEventListener2(NULL);
2133
  CheckDebuggerUnloaded();
2134
}
2135

    
2136

    
2137
// Test script break points set on lines.
2138
TEST(ScriptBreakPointLine) {
2139
  DebugLocalContext env;
2140
  v8::HandleScope scope(env->GetIsolate());
2141
  env.ExposeDebug();
2142

    
2143
  // Create a function for checking the function when hitting a break point.
2144
  frame_function_name = CompileFunction(&env,
2145
                                        frame_function_name_source,
2146
                                        "frame_function_name");
2147

    
2148
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2149

    
2150
  v8::Local<v8::Function> f;
2151
  v8::Local<v8::Function> g;
2152
  v8::Local<v8::String> script = v8::String::New(
2153
    "a = 0                      // line 0\n"
2154
    "function f() {\n"
2155
    "  a = 1;                   // line 2\n"
2156
    "}\n"
2157
    " a = 2;                    // line 4\n"
2158
    "  /* xx */ function g() {  // line 5\n"
2159
    "    function h() {         // line 6\n"
2160
    "      a = 3;               // line 7\n"
2161
    "    }\n"
2162
    "    h();                   // line 9\n"
2163
    "    a = 4;                 // line 10\n"
2164
    "  }\n"
2165
    " a=5;                      // line 12");
2166

    
2167
  // Set a couple script break point before the script is loaded.
2168
  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 0, -1);
2169
  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 1, -1);
2170
  int sbp3 = SetScriptBreakPointByNameFromJS("test.html", 5, -1);
2171

    
2172
  // Compile the script and get the function.
2173
  break_point_hit_count = 0;
2174
  v8::ScriptOrigin origin(v8::String::New("test.html"), v8::Integer::New(0));
2175
  v8::Script::Compile(script, &origin)->Run();
2176
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
2177
  g = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
2178

    
2179
  // Check that a break point was hit when the script was run.
2180
  CHECK_EQ(1, break_point_hit_count);
2181
  CHECK_EQ(0, StrLength(last_function_hit));
2182

    
2183
  // Call f and check that the script break point.
2184
  f->Call(env->Global(), 0, NULL);
2185
  CHECK_EQ(2, break_point_hit_count);
2186
  CHECK_EQ("f", last_function_hit);
2187

    
2188
  // Call g and check that the script break point.
2189
  g->Call(env->Global(), 0, NULL);
2190
  CHECK_EQ(3, break_point_hit_count);
2191
  CHECK_EQ("g", last_function_hit);
2192

    
2193
  // Clear the script break point on g and set one on h.
2194
  ClearBreakPointFromJS(sbp3);
2195
  int sbp4 = SetScriptBreakPointByNameFromJS("test.html", 6, -1);
2196

    
2197
  // Call g and check that the script break point in h is hit.
2198
  g->Call(env->Global(), 0, NULL);
2199
  CHECK_EQ(4, break_point_hit_count);
2200
  CHECK_EQ("h", last_function_hit);
2201

    
2202
  // Clear break points in f and h. Set a new one in the script between
2203
  // functions f and g and test that there is no break points in f and g any
2204
  // more.
2205
  ClearBreakPointFromJS(sbp2);
2206
  ClearBreakPointFromJS(sbp4);
2207
  int sbp5 = SetScriptBreakPointByNameFromJS("test.html", 4, -1);
2208
  break_point_hit_count = 0;
2209
  f->Call(env->Global(), 0, NULL);
2210
  g->Call(env->Global(), 0, NULL);
2211
  CHECK_EQ(0, break_point_hit_count);
2212

    
2213
  // Reload the script which should hit two break points.
2214
  break_point_hit_count = 0;
2215
  v8::Script::Compile(script, &origin)->Run();
2216
  CHECK_EQ(2, break_point_hit_count);
2217
  CHECK_EQ(0, StrLength(last_function_hit));
2218

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

    
2222
  // Reload the script which should hit three break points.
2223
  break_point_hit_count = 0;
2224
  v8::Script::Compile(script, &origin)->Run();
2225
  CHECK_EQ(3, break_point_hit_count);
2226
  CHECK_EQ(0, StrLength(last_function_hit));
2227

    
2228
  // Clear the last break points, and reload the script which should not hit any
2229
  // break points.
2230
  ClearBreakPointFromJS(sbp1);
2231
  ClearBreakPointFromJS(sbp5);
2232
  ClearBreakPointFromJS(sbp6);
2233
  break_point_hit_count = 0;
2234
  v8::Script::Compile(script, &origin)->Run();
2235
  CHECK_EQ(0, break_point_hit_count);
2236

    
2237
  v8::Debug::SetDebugEventListener2(NULL);
2238
  CheckDebuggerUnloaded();
2239
}
2240

    
2241

    
2242
// Test top level script break points set on lines.
2243
TEST(ScriptBreakPointLineTopLevel) {
2244
  DebugLocalContext env;
2245
  v8::HandleScope scope(env->GetIsolate());
2246
  env.ExposeDebug();
2247

    
2248
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2249

    
2250
  v8::Local<v8::String> script = v8::String::New(
2251
    "function f() {\n"
2252
    "  a = 1;                   // line 1\n"
2253
    "}\n"
2254
    "a = 2;                     // line 3\n");
2255
  v8::Local<v8::Function> f;
2256
  {
2257
    v8::HandleScope scope(env->GetIsolate());
2258
    v8::Script::Compile(script, v8::String::New("test.html"))->Run();
2259
  }
2260
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
2261

    
2262
  CcTest::heap()->CollectAllGarbage(Heap::kNoGCFlags);
2263

    
2264
  SetScriptBreakPointByNameFromJS("test.html", 3, -1);
2265

    
2266
  // Call f and check that there was no break points.
2267
  break_point_hit_count = 0;
2268
  f->Call(env->Global(), 0, NULL);
2269
  CHECK_EQ(0, break_point_hit_count);
2270

    
2271
  // Recompile and run script and check that break point was hit.
2272
  break_point_hit_count = 0;
2273
  v8::Script::Compile(script, v8::String::New("test.html"))->Run();
2274
  CHECK_EQ(1, break_point_hit_count);
2275

    
2276
  // Call f and check that there are still no break points.
2277
  break_point_hit_count = 0;
2278
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
2279
  CHECK_EQ(0, break_point_hit_count);
2280

    
2281
  v8::Debug::SetDebugEventListener2(NULL);
2282
  CheckDebuggerUnloaded();
2283
}
2284

    
2285

    
2286
// Test that it is possible to add and remove break points in a top level
2287
// function which has no references but has not been collected yet.
2288
TEST(ScriptBreakPointTopLevelCrash) {
2289
  DebugLocalContext env;
2290
  v8::HandleScope scope(env->GetIsolate());
2291
  env.ExposeDebug();
2292

    
2293
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2294

    
2295
  v8::Local<v8::String> script_source = v8::String::New(
2296
    "function f() {\n"
2297
    "  return 0;\n"
2298
    "}\n"
2299
    "f()");
2300

    
2301
  int sbp1 = SetScriptBreakPointByNameFromJS("test.html", 3, -1);
2302
  {
2303
    v8::HandleScope scope(env->GetIsolate());
2304
    break_point_hit_count = 0;
2305
    v8::Script::Compile(script_source, v8::String::New("test.html"))->Run();
2306
    CHECK_EQ(1, break_point_hit_count);
2307
  }
2308

    
2309
  int sbp2 = SetScriptBreakPointByNameFromJS("test.html", 3, -1);
2310
  ClearBreakPointFromJS(sbp1);
2311
  ClearBreakPointFromJS(sbp2);
2312

    
2313
  v8::Debug::SetDebugEventListener2(NULL);
2314
  CheckDebuggerUnloaded();
2315
}
2316

    
2317

    
2318
// Test that it is possible to remove the last break point for a function
2319
// inside the break handling of that break point.
2320
TEST(RemoveBreakPointInBreak) {
2321
  DebugLocalContext env;
2322
  v8::HandleScope scope(env->GetIsolate());
2323

    
2324
  v8::Local<v8::Function> foo =
2325
      CompileFunction(&env, "function foo(){a=1;}", "foo");
2326
  debug_event_remove_break_point = SetBreakPoint(foo, 0);
2327

    
2328
  // Register the debug event listener pasing the function
2329
  v8::Debug::SetDebugEventListener2(DebugEventRemoveBreakPoint, foo);
2330

    
2331
  break_point_hit_count = 0;
2332
  foo->Call(env->Global(), 0, NULL);
2333
  CHECK_EQ(1, break_point_hit_count);
2334

    
2335
  break_point_hit_count = 0;
2336
  foo->Call(env->Global(), 0, NULL);
2337
  CHECK_EQ(0, break_point_hit_count);
2338

    
2339
  v8::Debug::SetDebugEventListener2(NULL);
2340
  CheckDebuggerUnloaded();
2341
}
2342

    
2343

    
2344
// Test that the debugger statement causes a break.
2345
TEST(DebuggerStatement) {
2346
  break_point_hit_count = 0;
2347
  DebugLocalContext env;
2348
  v8::HandleScope scope(env->GetIsolate());
2349
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2350
  v8::Script::Compile(v8::String::New("function bar(){debugger}"))->Run();
2351
  v8::Script::Compile(v8::String::New(
2352
      "function foo(){debugger;debugger;}"))->Run();
2353
  v8::Local<v8::Function> foo =
2354
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
2355
  v8::Local<v8::Function> bar =
2356
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("bar")));
2357

    
2358
  // Run function with debugger statement
2359
  bar->Call(env->Global(), 0, NULL);
2360
  CHECK_EQ(1, break_point_hit_count);
2361

    
2362
  // Run function with two debugger statement
2363
  foo->Call(env->Global(), 0, NULL);
2364
  CHECK_EQ(3, break_point_hit_count);
2365

    
2366
  v8::Debug::SetDebugEventListener2(NULL);
2367
  CheckDebuggerUnloaded();
2368
}
2369

    
2370

    
2371
// Test setting a breakpoint on the debugger statement.
2372
TEST(DebuggerStatementBreakpoint) {
2373
    break_point_hit_count = 0;
2374
    DebugLocalContext env;
2375
    v8::HandleScope scope(env->GetIsolate());
2376
    v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2377
    v8::Script::Compile(v8::String::New("function foo(){debugger;}"))->Run();
2378
    v8::Local<v8::Function> foo =
2379
    v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
2380

    
2381
    // The debugger statement triggers breakpint hit
2382
    foo->Call(env->Global(), 0, NULL);
2383
    CHECK_EQ(1, break_point_hit_count);
2384

    
2385
    int bp = SetBreakPoint(foo, 0);
2386

    
2387
    // Set breakpoint does not duplicate hits
2388
    foo->Call(env->Global(), 0, NULL);
2389
    CHECK_EQ(2, break_point_hit_count);
2390

    
2391
    ClearBreakPoint(bp);
2392
    v8::Debug::SetDebugEventListener2(NULL);
2393
    CheckDebuggerUnloaded();
2394
}
2395

    
2396

    
2397
// Test that the evaluation of expressions when a break point is hit generates
2398
// the correct results.
2399
TEST(DebugEvaluate) {
2400
  DebugLocalContext env;
2401
  v8::Isolate* isolate = env->GetIsolate();
2402
  v8::HandleScope scope(isolate);
2403
  env.ExposeDebug();
2404

    
2405
  // Create a function for checking the evaluation when hitting a break point.
2406
  evaluate_check_function = CompileFunction(&env,
2407
                                            evaluate_check_source,
2408
                                            "evaluate_check");
2409
  // Register the debug event listener
2410
  v8::Debug::SetDebugEventListener2(DebugEventEvaluate);
2411

    
2412
  // Different expected vaules of x and a when in a break point (u = undefined,
2413
  // d = Hello, world!).
2414
  struct EvaluateCheck checks_uu[] = {
2415
    {"x", v8::Undefined(isolate)},
2416
    {"a", v8::Undefined(isolate)},
2417
    {NULL, v8::Handle<v8::Value>()}
2418
  };
2419
  struct EvaluateCheck checks_hu[] = {
2420
    {"x", v8::String::New("Hello, world!")},
2421
    {"a", v8::Undefined(isolate)},
2422
    {NULL, v8::Handle<v8::Value>()}
2423
  };
2424
  struct EvaluateCheck checks_hh[] = {
2425
    {"x", v8::String::New("Hello, world!")},
2426
    {"a", v8::String::New("Hello, world!")},
2427
    {NULL, v8::Handle<v8::Value>()}
2428
  };
2429

    
2430
  // Simple test function. The "y=0" is in the function foo to provide a break
2431
  // location. For "y=0" the "y" is at position 15 in the barbar function
2432
  // therefore setting breakpoint at position 15 will break at "y=0" and
2433
  // setting it higher will break after.
2434
  v8::Local<v8::Function> foo = CompileFunction(&env,
2435
    "function foo(x) {"
2436
    "  var a;"
2437
    "  y=0;"  // To ensure break location 1.
2438
    "  a=x;"
2439
    "  y=0;"  // To ensure break location 2.
2440
    "}",
2441
    "foo");
2442
  const int foo_break_position_1 = 15;
2443
  const int foo_break_position_2 = 29;
2444

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

    
2448
  // Call foo with breakpoint set before a=x and undefined as parameter.
2449
  int bp = SetBreakPoint(foo, foo_break_position_1);
2450
  checks = checks_uu;
2451
  foo->Call(env->Global(), 0, NULL);
2452

    
2453
  // Call foo with breakpoint set before a=x and parameter "Hello, world!".
2454
  checks = checks_hu;
2455
  foo->Call(env->Global(), 1, argv_foo);
2456

    
2457
  // Call foo with breakpoint set after a=x and parameter "Hello, world!".
2458
  ClearBreakPoint(bp);
2459
  SetBreakPoint(foo, foo_break_position_2);
2460
  checks = checks_hh;
2461
  foo->Call(env->Global(), 1, argv_foo);
2462

    
2463
  // Test function with an inner function. The "y=0" is in function barbar
2464
  // to provide a break location. For "y=0" the "y" is at position 8 in the
2465
  // barbar function therefore setting breakpoint at position 8 will break at
2466
  // "y=0" and setting it higher will break after.
2467
  v8::Local<v8::Function> bar = CompileFunction(&env,
2468
    "y = 0;"
2469
    "x = 'Goodbye, world!';"
2470
    "function bar(x, b) {"
2471
    "  var a;"
2472
    "  function barbar() {"
2473
    "    y=0; /* To ensure break location.*/"
2474
    "    a=x;"
2475
    "  };"
2476
    "  debug.Debug.clearAllBreakPoints();"
2477
    "  barbar();"
2478
    "  y=0;a=x;"
2479
    "}",
2480
    "bar");
2481
  const int barbar_break_position = 8;
2482

    
2483
  // Call bar setting breakpoint before a=x in barbar and undefined as
2484
  // parameter.
2485
  checks = checks_uu;
2486
  v8::Handle<v8::Value> argv_bar_1[2] = {
2487
    v8::Undefined(isolate),
2488
    v8::Number::New(barbar_break_position)
2489
  };
2490
  bar->Call(env->Global(), 2, argv_bar_1);
2491

    
2492
  // Call bar setting breakpoint before a=x in barbar and parameter
2493
  // "Hello, world!".
2494
  checks = checks_hu;
2495
  v8::Handle<v8::Value> argv_bar_2[2] = {
2496
    v8::String::New("Hello, world!"),
2497
    v8::Number::New(barbar_break_position)
2498
  };
2499
  bar->Call(env->Global(), 2, argv_bar_2);
2500

    
2501
  // Call bar setting breakpoint after a=x in barbar and parameter
2502
  // "Hello, world!".
2503
  checks = checks_hh;
2504
  v8::Handle<v8::Value> argv_bar_3[2] = {
2505
    v8::String::New("Hello, world!"),
2506
    v8::Number::New(barbar_break_position + 1)
2507
  };
2508
  bar->Call(env->Global(), 2, argv_bar_3);
2509

    
2510
  v8::Debug::SetDebugEventListener2(NULL);
2511
  CheckDebuggerUnloaded();
2512
}
2513

    
2514

    
2515
int debugEventCount = 0;
2516
static void CheckDebugEvent(const v8::Debug::EventDetails& eventDetails) {
2517
  if (eventDetails.GetEvent() == v8::Break) ++debugEventCount;
2518
}
2519

    
2520

    
2521
// Test that the conditional breakpoints work event if code generation from
2522
// strings is prohibited in the debugee context.
2523
TEST(ConditionalBreakpointWithCodeGenerationDisallowed) {
2524
  DebugLocalContext env;
2525
  v8::HandleScope scope(env->GetIsolate());
2526
  env.ExposeDebug();
2527

    
2528
  v8::Debug::SetDebugEventListener2(CheckDebugEvent);
2529

    
2530
  v8::Local<v8::Function> foo = CompileFunction(&env,
2531
    "function foo(x) {\n"
2532
    "  var s = 'String value2';\n"
2533
    "  return s + x;\n"
2534
    "}",
2535
    "foo");
2536

    
2537
  // Set conditional breakpoint with condition 'true'.
2538
  CompileRun("debug.Debug.setBreakPoint(foo, 2, 0, 'true')");
2539

    
2540
  debugEventCount = 0;
2541
  env->AllowCodeGenerationFromStrings(false);
2542
  foo->Call(env->Global(), 0, NULL);
2543
  CHECK_EQ(1, debugEventCount);
2544

    
2545
  v8::Debug::SetDebugEventListener2(NULL);
2546
  CheckDebuggerUnloaded();
2547
}
2548

    
2549

    
2550
bool checkedDebugEvals = true;
2551
v8::Handle<v8::Function> checkGlobalEvalFunction;
2552
v8::Handle<v8::Function> checkFrameEvalFunction;
2553
static void CheckDebugEval(const v8::Debug::EventDetails& eventDetails) {
2554
  if (eventDetails.GetEvent() == v8::Break) {
2555
    ++debugEventCount;
2556
    v8::HandleScope handleScope(CcTest::isolate());
2557

    
2558
    v8::Handle<v8::Value> args[] = { eventDetails.GetExecutionState() };
2559
    CHECK(checkGlobalEvalFunction->Call(
2560
        eventDetails.GetEventContext()->Global(), 1, args)->IsTrue());
2561
    CHECK(checkFrameEvalFunction->Call(
2562
        eventDetails.GetEventContext()->Global(), 1, args)->IsTrue());
2563
  }
2564
}
2565

    
2566

    
2567
// Test that the evaluation of expressions when a break point is hit generates
2568
// the correct results in case code generation from strings is disallowed in the
2569
// debugee context.
2570
TEST(DebugEvaluateWithCodeGenerationDisallowed) {
2571
  DebugLocalContext env;
2572
  v8::HandleScope scope(env->GetIsolate());
2573
  env.ExposeDebug();
2574

    
2575
  v8::Debug::SetDebugEventListener2(CheckDebugEval);
2576

    
2577
  v8::Local<v8::Function> foo = CompileFunction(&env,
2578
    "var global = 'Global';\n"
2579
    "function foo(x) {\n"
2580
    "  var local = 'Local';\n"
2581
    "  debugger;\n"
2582
    "  return local + x;\n"
2583
    "}",
2584
    "foo");
2585
  checkGlobalEvalFunction = CompileFunction(&env,
2586
    "function checkGlobalEval(exec_state) {\n"
2587
    "  return exec_state.evaluateGlobal('global').value() === 'Global';\n"
2588
    "}",
2589
    "checkGlobalEval");
2590

    
2591
  checkFrameEvalFunction = CompileFunction(&env,
2592
    "function checkFrameEval(exec_state) {\n"
2593
    "  return exec_state.frame(0).evaluate('local').value() === 'Local';\n"
2594
    "}",
2595
    "checkFrameEval");
2596
  debugEventCount = 0;
2597
  env->AllowCodeGenerationFromStrings(false);
2598
  foo->Call(env->Global(), 0, NULL);
2599
  CHECK_EQ(1, debugEventCount);
2600

    
2601
  checkGlobalEvalFunction.Clear();
2602
  checkFrameEvalFunction.Clear();
2603
  v8::Debug::SetDebugEventListener2(NULL);
2604
  CheckDebuggerUnloaded();
2605
}
2606

    
2607

    
2608
// Copies a C string to a 16-bit string.  Does not check for buffer overflow.
2609
// Does not use the V8 engine to convert strings, so it can be used
2610
// in any thread.  Returns the length of the string.
2611
int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
2612
  int i;
2613
  for (i = 0; input_buffer[i] != '\0'; ++i) {
2614
    // ASCII does not use chars > 127, but be careful anyway.
2615
    output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
2616
  }
2617
  output_buffer[i] = 0;
2618
  return i;
2619
}
2620

    
2621

    
2622
// Copies a 16-bit string to a C string by dropping the high byte of
2623
// each character.  Does not check for buffer overflow.
2624
// Can be used in any thread.  Requires string length as an input.
2625
int Utf16ToAscii(const uint16_t* input_buffer, int length,
2626
                 char* output_buffer, int output_len = -1) {
2627
  if (output_len >= 0) {
2628
    if (length > output_len - 1) {
2629
      length = output_len - 1;
2630
    }
2631
  }
2632

    
2633
  for (int i = 0; i < length; ++i) {
2634
    output_buffer[i] = static_cast<char>(input_buffer[i]);
2635
  }
2636
  output_buffer[length] = '\0';
2637
  return length;
2638
}
2639

    
2640

    
2641
// We match parts of the message to get evaluate result int value.
2642
bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
2643
  if (strstr(message, "\"command\":\"evaluate\"") == NULL) {
2644
    return false;
2645
  }
2646
  const char* prefix = "\"text\":\"";
2647
  char* pos1 = strstr(message, prefix);
2648
  if (pos1 == NULL) {
2649
    return false;
2650
  }
2651
  pos1 += strlen(prefix);
2652
  char* pos2 = strchr(pos1, '"');
2653
  if (pos2 == NULL) {
2654
    return false;
2655
  }
2656
  Vector<char> buf(buffer, buffer_size);
2657
  int len = static_cast<int>(pos2 - pos1);
2658
  if (len > buffer_size - 1) {
2659
    len = buffer_size - 1;
2660
  }
2661
  OS::StrNCpy(buf, pos1, len);
2662
  buffer[buffer_size - 1] = '\0';
2663
  return true;
2664
}
2665

    
2666

    
2667
struct EvaluateResult {
2668
  static const int kBufferSize = 20;
2669
  char buffer[kBufferSize];
2670
};
2671

    
2672
struct DebugProcessDebugMessagesData {
2673
  static const int kArraySize = 5;
2674
  int counter;
2675
  EvaluateResult results[kArraySize];
2676

    
2677
  void reset() {
2678
    counter = 0;
2679
  }
2680
  EvaluateResult* current() {
2681
    return &results[counter % kArraySize];
2682
  }
2683
  void next() {
2684
    counter++;
2685
  }
2686
};
2687

    
2688
DebugProcessDebugMessagesData process_debug_messages_data;
2689

    
2690
static void DebugProcessDebugMessagesHandler(
2691
    const v8::Debug::Message& message) {
2692
  v8::Handle<v8::String> json = message.GetJSON();
2693
  v8::String::AsciiValue ascii(json);
2694
  EvaluateResult* array_item = process_debug_messages_data.current();
2695

    
2696
  bool res = GetEvaluateStringResult(*ascii,
2697
                                     array_item->buffer,
2698
                                     EvaluateResult::kBufferSize);
2699
  if (res) {
2700
    process_debug_messages_data.next();
2701
  }
2702
}
2703

    
2704

    
2705
// Test that the evaluation of expressions works even from ProcessDebugMessages
2706
// i.e. with empty stack.
2707
TEST(DebugEvaluateWithoutStack) {
2708
  v8::Debug::SetMessageHandler2(DebugProcessDebugMessagesHandler);
2709

    
2710
  DebugLocalContext env;
2711
  v8::HandleScope scope(env->GetIsolate());
2712

    
2713
  const char* source =
2714
      "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
2715

    
2716
  v8::Script::Compile(v8::String::New(source))->Run();
2717

    
2718
  v8::Debug::ProcessDebugMessages();
2719

    
2720
  const int kBufferSize = 1000;
2721
  uint16_t buffer[kBufferSize];
2722

    
2723
  const char* command_111 = "{\"seq\":111,"
2724
      "\"type\":\"request\","
2725
      "\"command\":\"evaluate\","
2726
      "\"arguments\":{"
2727
      "    \"global\":true,"
2728
      "    \"expression\":\"v1\",\"disable_break\":true"
2729
      "}}";
2730

    
2731
  v8::Isolate* isolate = CcTest::isolate();
2732
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_111, buffer));
2733

    
2734
  const char* command_112 = "{\"seq\":112,"
2735
      "\"type\":\"request\","
2736
      "\"command\":\"evaluate\","
2737
      "\"arguments\":{"
2738
      "    \"global\":true,"
2739
      "    \"expression\":\"getAnimal()\",\"disable_break\":true"
2740
      "}}";
2741

    
2742
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_112, buffer));
2743

    
2744
  const char* command_113 = "{\"seq\":113,"
2745
     "\"type\":\"request\","
2746
     "\"command\":\"evaluate\","
2747
     "\"arguments\":{"
2748
     "    \"global\":true,"
2749
     "    \"expression\":\"239 + 566\",\"disable_break\":true"
2750
     "}}";
2751

    
2752
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_113, buffer));
2753

    
2754
  v8::Debug::ProcessDebugMessages();
2755

    
2756
  CHECK_EQ(3, process_debug_messages_data.counter);
2757

    
2758
  CHECK_EQ(strcmp("Pinguin", process_debug_messages_data.results[0].buffer), 0);
2759
  CHECK_EQ(strcmp("Capybara", process_debug_messages_data.results[1].buffer),
2760
           0);
2761
  CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0);
2762

    
2763
  v8::Debug::SetMessageHandler2(NULL);
2764
  v8::Debug::SetDebugEventListener2(NULL);
2765
  CheckDebuggerUnloaded();
2766
}
2767

    
2768

    
2769
// Simple test of the stepping mechanism using only store ICs.
2770
TEST(DebugStepLinear) {
2771
  DebugLocalContext env;
2772
  v8::HandleScope scope(env->GetIsolate());
2773

    
2774
  // Create a function for testing stepping.
2775
  v8::Local<v8::Function> foo = CompileFunction(&env,
2776
                                                "function foo(){a=1;b=1;c=1;}",
2777
                                                "foo");
2778

    
2779
  // Run foo to allow it to get optimized.
2780
  CompileRun("a=0; b=0; c=0; foo();");
2781

    
2782
  SetBreakPoint(foo, 3);
2783

    
2784
  // Register a debug event listener which steps and counts.
2785
  v8::Debug::SetDebugEventListener2(DebugEventStep);
2786

    
2787
  step_action = StepIn;
2788
  break_point_hit_count = 0;
2789
  foo->Call(env->Global(), 0, NULL);
2790

    
2791
  // With stepping all break locations are hit.
2792
  CHECK_EQ(4, break_point_hit_count);
2793

    
2794
  v8::Debug::SetDebugEventListener2(NULL);
2795
  CheckDebuggerUnloaded();
2796

    
2797
  // Register a debug event listener which just counts.
2798
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
2799

    
2800
  SetBreakPoint(foo, 3);
2801
  break_point_hit_count = 0;
2802
  foo->Call(env->Global(), 0, NULL);
2803

    
2804
  // Without stepping only active break points are hit.
2805
  CHECK_EQ(1, break_point_hit_count);
2806

    
2807
  v8::Debug::SetDebugEventListener2(NULL);
2808
  CheckDebuggerUnloaded();
2809
}
2810

    
2811

    
2812
// Test of the stepping mechanism for keyed load in a loop.
2813
TEST(DebugStepKeyedLoadLoop) {
2814
  DebugLocalContext env;
2815
  v8::HandleScope scope(env->GetIsolate());
2816

    
2817
  // Register a debug event listener which steps and counts.
2818
  v8::Debug::SetDebugEventListener2(DebugEventStep);
2819

    
2820
  // Create a function for testing stepping of keyed load. The statement 'y=1'
2821
  // is there to have more than one breakable statement in the loop, TODO(315).
2822
  v8::Local<v8::Function> foo = CompileFunction(
2823
      &env,
2824
      "function foo(a) {\n"
2825
      "  var x;\n"
2826
      "  var len = a.length;\n"
2827
      "  for (var i = 0; i < len; i++) {\n"
2828
      "    y = 1;\n"
2829
      "    x = a[i];\n"
2830
      "  }\n"
2831
      "}\n"
2832
      "y=0\n",
2833
      "foo");
2834

    
2835
  // Create array [0,1,2,3,4,5,6,7,8,9]
2836
  v8::Local<v8::Array> a = v8::Array::New(10);
2837
  for (int i = 0; i < 10; i++) {
2838
    a->Set(v8::Number::New(i), v8::Number::New(i));
2839
  }
2840

    
2841
  // Call function without any break points to ensure inlining is in place.
2842
  const int kArgc = 1;
2843
  v8::Handle<v8::Value> args[kArgc] = { a };
2844
  foo->Call(env->Global(), kArgc, args);
2845

    
2846
  // Set up break point and step through the function.
2847
  SetBreakPoint(foo, 3);
2848
  step_action = StepNext;
2849
  break_point_hit_count = 0;
2850
  foo->Call(env->Global(), kArgc, args);
2851

    
2852
  // With stepping all break locations are hit.
2853
  CHECK_EQ(35, break_point_hit_count);
2854

    
2855
  v8::Debug::SetDebugEventListener2(NULL);
2856
  CheckDebuggerUnloaded();
2857
}
2858

    
2859

    
2860
// Test of the stepping mechanism for keyed store in a loop.
2861
TEST(DebugStepKeyedStoreLoop) {
2862
  DebugLocalContext env;
2863
  v8::HandleScope scope(env->GetIsolate());
2864

    
2865
  // Register a debug event listener which steps and counts.
2866
  v8::Debug::SetDebugEventListener2(DebugEventStep);
2867

    
2868
  // Create a function for testing stepping of keyed store. The statement 'y=1'
2869
  // is there to have more than one breakable statement in the loop, TODO(315).
2870
  v8::Local<v8::Function> foo = CompileFunction(
2871
      &env,
2872
      "function foo(a) {\n"
2873
      "  var len = a.length;\n"
2874
      "  for (var i = 0; i < len; i++) {\n"
2875
      "    y = 1;\n"
2876
      "    a[i] = 42;\n"
2877
      "  }\n"
2878
      "}\n"
2879
      "y=0\n",
2880
      "foo");
2881

    
2882
  // Create array [0,1,2,3,4,5,6,7,8,9]
2883
  v8::Local<v8::Array> a = v8::Array::New(10);
2884
  for (int i = 0; i < 10; i++) {
2885
    a->Set(v8::Number::New(i), v8::Number::New(i));
2886
  }
2887

    
2888
  // Call function without any break points to ensure inlining is in place.
2889
  const int kArgc = 1;
2890
  v8::Handle<v8::Value> args[kArgc] = { a };
2891
  foo->Call(env->Global(), kArgc, args);
2892

    
2893
  // Set up break point and step through the function.
2894
  SetBreakPoint(foo, 3);
2895
  step_action = StepNext;
2896
  break_point_hit_count = 0;
2897
  foo->Call(env->Global(), kArgc, args);
2898

    
2899
  // With stepping all break locations are hit.
2900
  CHECK_EQ(34, break_point_hit_count);
2901

    
2902
  v8::Debug::SetDebugEventListener2(NULL);
2903
  CheckDebuggerUnloaded();
2904
}
2905

    
2906

    
2907
// Test of the stepping mechanism for named load in a loop.
2908
TEST(DebugStepNamedLoadLoop) {
2909
  DebugLocalContext env;
2910
  v8::HandleScope scope(env->GetIsolate());
2911

    
2912
  // Register a debug event listener which steps and counts.
2913
  v8::Debug::SetDebugEventListener2(DebugEventStep);
2914

    
2915
  // Create a function for testing stepping of named load.
2916
  v8::Local<v8::Function> foo = CompileFunction(
2917
      &env,
2918
      "function foo() {\n"
2919
          "  var a = [];\n"
2920
          "  var s = \"\";\n"
2921
          "  for (var i = 0; i < 10; i++) {\n"
2922
          "    var v = new V(i, i + 1);\n"
2923
          "    v.y;\n"
2924
          "    a.length;\n"  // Special case: array length.
2925
          "    s.length;\n"  // Special case: string length.
2926
          "  }\n"
2927
          "}\n"
2928
          "function V(x, y) {\n"
2929
          "  this.x = x;\n"
2930
          "  this.y = y;\n"
2931
          "}\n",
2932
          "foo");
2933

    
2934
  // Call function without any break points to ensure inlining is in place.
2935
  foo->Call(env->Global(), 0, NULL);
2936

    
2937
  // Set up break point and step through the function.
2938
  SetBreakPoint(foo, 4);
2939
  step_action = StepNext;
2940
  break_point_hit_count = 0;
2941
  foo->Call(env->Global(), 0, NULL);
2942

    
2943
  // With stepping all break locations are hit.
2944
  CHECK_EQ(55, break_point_hit_count);
2945

    
2946
  v8::Debug::SetDebugEventListener2(NULL);
2947
  CheckDebuggerUnloaded();
2948
}
2949

    
2950

    
2951
static void DoDebugStepNamedStoreLoop(int expected) {
2952
  DebugLocalContext env;
2953
  v8::HandleScope scope(env->GetIsolate());
2954

    
2955
  // Register a debug event listener which steps and counts.
2956
  v8::Debug::SetDebugEventListener2(DebugEventStep);
2957

    
2958
  // Create a function for testing stepping of named store.
2959
  v8::Local<v8::Function> foo = CompileFunction(
2960
      &env,
2961
      "function foo() {\n"
2962
          "  var a = {a:1};\n"
2963
          "  for (var i = 0; i < 10; i++) {\n"
2964
          "    a.a = 2\n"
2965
          "  }\n"
2966
          "}\n",
2967
          "foo");
2968

    
2969
  // Call function without any break points to ensure inlining is in place.
2970
  foo->Call(env->Global(), 0, NULL);
2971

    
2972
  // Set up break point and step through the function.
2973
  SetBreakPoint(foo, 3);
2974
  step_action = StepNext;
2975
  break_point_hit_count = 0;
2976
  foo->Call(env->Global(), 0, NULL);
2977

    
2978
  // With stepping all expected break locations are hit.
2979
  CHECK_EQ(expected, break_point_hit_count);
2980

    
2981
  v8::Debug::SetDebugEventListener2(NULL);
2982
  CheckDebuggerUnloaded();
2983
}
2984

    
2985

    
2986
// Test of the stepping mechanism for named load in a loop.
2987
TEST(DebugStepNamedStoreLoop) {
2988
  DoDebugStepNamedStoreLoop(24);
2989
}
2990

    
2991

    
2992
// Test the stepping mechanism with different ICs.
2993
TEST(DebugStepLinearMixedICs) {
2994
  DebugLocalContext env;
2995
  v8::HandleScope scope(env->GetIsolate());
2996

    
2997
  // Register a debug event listener which steps and counts.
2998
  v8::Debug::SetDebugEventListener2(DebugEventStep);
2999

    
3000
  // Create a function for testing stepping.
3001
  v8::Local<v8::Function> foo = CompileFunction(&env,
3002
      "function bar() {};"
3003
      "function foo() {"
3004
      "  var x;"
3005
      "  var index='name';"
3006
      "  var y = {};"
3007
      "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
3008

    
3009
  // Run functions to allow them to get optimized.
3010
  CompileRun("a=0; b=0; bar(); foo();");
3011

    
3012
  SetBreakPoint(foo, 0);
3013

    
3014
  step_action = StepIn;
3015
  break_point_hit_count = 0;
3016
  foo->Call(env->Global(), 0, NULL);
3017

    
3018
  // With stepping all break locations are hit.
3019
  CHECK_EQ(11, break_point_hit_count);
3020

    
3021
  v8::Debug::SetDebugEventListener2(NULL);
3022
  CheckDebuggerUnloaded();
3023

    
3024
  // Register a debug event listener which just counts.
3025
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
3026

    
3027
  SetBreakPoint(foo, 0);
3028
  break_point_hit_count = 0;
3029
  foo->Call(env->Global(), 0, NULL);
3030

    
3031
  // Without stepping only active break points are hit.
3032
  CHECK_EQ(1, break_point_hit_count);
3033

    
3034
  v8::Debug::SetDebugEventListener2(NULL);
3035
  CheckDebuggerUnloaded();
3036
}
3037

    
3038

    
3039
TEST(DebugStepDeclarations) {
3040
  DebugLocalContext env;
3041
  v8::HandleScope scope(env->GetIsolate());
3042

    
3043
  // Register a debug event listener which steps and counts.
3044
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3045

    
3046
  // Create a function for testing stepping. Run it to allow it to get
3047
  // optimized.
3048
  const char* src = "function foo() { "
3049
                    "  var a;"
3050
                    "  var b = 1;"
3051
                    "  var c = foo;"
3052
                    "  var d = Math.floor;"
3053
                    "  var e = b + d(1.2);"
3054
                    "}"
3055
                    "foo()";
3056
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3057

    
3058
  SetBreakPoint(foo, 0);
3059

    
3060
  // Stepping through the declarations.
3061
  step_action = StepIn;
3062
  break_point_hit_count = 0;
3063
  foo->Call(env->Global(), 0, NULL);
3064
  CHECK_EQ(6, break_point_hit_count);
3065

    
3066
  // Get rid of the debug event listener.
3067
  v8::Debug::SetDebugEventListener2(NULL);
3068
  CheckDebuggerUnloaded();
3069
}
3070

    
3071

    
3072
TEST(DebugStepLocals) {
3073
  DebugLocalContext env;
3074
  v8::HandleScope scope(env->GetIsolate());
3075

    
3076
  // Register a debug event listener which steps and counts.
3077
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3078

    
3079
  // Create a function for testing stepping. Run it to allow it to get
3080
  // optimized.
3081
  const char* src = "function foo() { "
3082
                    "  var a,b;"
3083
                    "  a = 1;"
3084
                    "  b = a + 2;"
3085
                    "  b = 1 + 2 + 3;"
3086
                    "  a = Math.floor(b);"
3087
                    "}"
3088
                    "foo()";
3089
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3090

    
3091
  SetBreakPoint(foo, 0);
3092

    
3093
  // Stepping through the declarations.
3094
  step_action = StepIn;
3095
  break_point_hit_count = 0;
3096
  foo->Call(env->Global(), 0, NULL);
3097
  CHECK_EQ(6, break_point_hit_count);
3098

    
3099
  // Get rid of the debug event listener.
3100
  v8::Debug::SetDebugEventListener2(NULL);
3101
  CheckDebuggerUnloaded();
3102
}
3103

    
3104

    
3105
TEST(DebugStepIf) {
3106
  DebugLocalContext env;
3107
  v8::Isolate* isolate = env->GetIsolate();
3108
  v8::HandleScope scope(isolate);
3109

    
3110
  // Register a debug event listener which steps and counts.
3111
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3112

    
3113
  // Create a function for testing stepping. Run it to allow it to get
3114
  // optimized.
3115
  const int argc = 1;
3116
  const char* src = "function foo(x) { "
3117
                    "  a = 1;"
3118
                    "  if (x) {"
3119
                    "    b = 1;"
3120
                    "  } else {"
3121
                    "    c = 1;"
3122
                    "    d = 1;"
3123
                    "  }"
3124
                    "}"
3125
                    "a=0; b=0; c=0; d=0; foo()";
3126
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3127
  SetBreakPoint(foo, 0);
3128

    
3129
  // Stepping through the true part.
3130
  step_action = StepIn;
3131
  break_point_hit_count = 0;
3132
  v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
3133
  foo->Call(env->Global(), argc, argv_true);
3134
  CHECK_EQ(4, break_point_hit_count);
3135

    
3136
  // Stepping through the false part.
3137
  step_action = StepIn;
3138
  break_point_hit_count = 0;
3139
  v8::Handle<v8::Value> argv_false[argc] = { v8::False(isolate) };
3140
  foo->Call(env->Global(), argc, argv_false);
3141
  CHECK_EQ(5, break_point_hit_count);
3142

    
3143
  // Get rid of the debug event listener.
3144
  v8::Debug::SetDebugEventListener2(NULL);
3145
  CheckDebuggerUnloaded();
3146
}
3147

    
3148

    
3149
TEST(DebugStepSwitch) {
3150
  DebugLocalContext env;
3151
  v8::HandleScope scope(env->GetIsolate());
3152

    
3153
  // Register a debug event listener which steps and counts.
3154
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3155

    
3156
  // Create a function for testing stepping. Run it to allow it to get
3157
  // optimized.
3158
  const int argc = 1;
3159
  const char* src = "function foo(x) { "
3160
                    "  a = 1;"
3161
                    "  switch (x) {"
3162
                    "    case 1:"
3163
                    "      b = 1;"
3164
                    "    case 2:"
3165
                    "      c = 1;"
3166
                    "      break;"
3167
                    "    case 3:"
3168
                    "      d = 1;"
3169
                    "      e = 1;"
3170
                    "      f = 1;"
3171
                    "      break;"
3172
                    "  }"
3173
                    "}"
3174
                    "a=0; b=0; c=0; d=0; e=0; f=0; foo()";
3175
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3176
  SetBreakPoint(foo, 0);
3177

    
3178
  // One case with fall-through.
3179
  step_action = StepIn;
3180
  break_point_hit_count = 0;
3181
  v8::Handle<v8::Value> argv_1[argc] = { v8::Number::New(1) };
3182
  foo->Call(env->Global(), argc, argv_1);
3183
  CHECK_EQ(6, break_point_hit_count);
3184

    
3185
  // Another case.
3186
  step_action = StepIn;
3187
  break_point_hit_count = 0;
3188
  v8::Handle<v8::Value> argv_2[argc] = { v8::Number::New(2) };
3189
  foo->Call(env->Global(), argc, argv_2);
3190
  CHECK_EQ(5, break_point_hit_count);
3191

    
3192
  // Last case.
3193
  step_action = StepIn;
3194
  break_point_hit_count = 0;
3195
  v8::Handle<v8::Value> argv_3[argc] = { v8::Number::New(3) };
3196
  foo->Call(env->Global(), argc, argv_3);
3197
  CHECK_EQ(7, break_point_hit_count);
3198

    
3199
  // Get rid of the debug event listener.
3200
  v8::Debug::SetDebugEventListener2(NULL);
3201
  CheckDebuggerUnloaded();
3202
}
3203

    
3204

    
3205
TEST(DebugStepWhile) {
3206
  DebugLocalContext env;
3207
  v8::HandleScope scope(env->GetIsolate());
3208

    
3209
  // Register a debug event listener which steps and counts.
3210
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3211

    
3212
  // Create a function for testing stepping. Run it to allow it to get
3213
  // optimized.
3214
  const int argc = 1;
3215
  const char* src = "function foo(x) { "
3216
                    "  var a = 0;"
3217
                    "  while (a < x) {"
3218
                    "    a++;"
3219
                    "  }"
3220
                    "}"
3221
                    "foo()";
3222
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3223
  SetBreakPoint(foo, 8);  // "var a = 0;"
3224

    
3225
  // Looping 10 times.
3226
  step_action = StepIn;
3227
  break_point_hit_count = 0;
3228
  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
3229
  foo->Call(env->Global(), argc, argv_10);
3230
  CHECK_EQ(22, break_point_hit_count);
3231

    
3232
  // Looping 100 times.
3233
  step_action = StepIn;
3234
  break_point_hit_count = 0;
3235
  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
3236
  foo->Call(env->Global(), argc, argv_100);
3237
  CHECK_EQ(202, break_point_hit_count);
3238

    
3239
  // Get rid of the debug event listener.
3240
  v8::Debug::SetDebugEventListener2(NULL);
3241
  CheckDebuggerUnloaded();
3242
}
3243

    
3244

    
3245
TEST(DebugStepDoWhile) {
3246
  DebugLocalContext env;
3247
  v8::HandleScope scope(env->GetIsolate());
3248

    
3249
  // Register a debug event listener which steps and counts.
3250
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3251

    
3252
  // Create a function for testing stepping. Run it to allow it to get
3253
  // optimized.
3254
  const int argc = 1;
3255
  const char* src = "function foo(x) { "
3256
                    "  var a = 0;"
3257
                    "  do {"
3258
                    "    a++;"
3259
                    "  } while (a < x)"
3260
                    "}"
3261
                    "foo()";
3262
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3263
  SetBreakPoint(foo, 8);  // "var a = 0;"
3264

    
3265
  // Looping 10 times.
3266
  step_action = StepIn;
3267
  break_point_hit_count = 0;
3268
  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
3269
  foo->Call(env->Global(), argc, argv_10);
3270
  CHECK_EQ(22, break_point_hit_count);
3271

    
3272
  // Looping 100 times.
3273
  step_action = StepIn;
3274
  break_point_hit_count = 0;
3275
  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
3276
  foo->Call(env->Global(), argc, argv_100);
3277
  CHECK_EQ(202, break_point_hit_count);
3278

    
3279
  // Get rid of the debug event listener.
3280
  v8::Debug::SetDebugEventListener2(NULL);
3281
  CheckDebuggerUnloaded();
3282
}
3283

    
3284

    
3285
TEST(DebugStepFor) {
3286
  DebugLocalContext env;
3287
  v8::HandleScope scope(env->GetIsolate());
3288

    
3289
  // Register a debug event listener which steps and counts.
3290
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3291

    
3292
  // Create a function for testing stepping. Run it to allow it to get
3293
  // optimized.
3294
  const int argc = 1;
3295
  const char* src = "function foo(x) { "
3296
                    "  a = 1;"
3297
                    "  for (i = 0; i < x; i++) {"
3298
                    "    b = 1;"
3299
                    "  }"
3300
                    "}"
3301
                    "a=0; b=0; i=0; foo()";
3302
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3303

    
3304
  SetBreakPoint(foo, 8);  // "a = 1;"
3305

    
3306
  // Looping 10 times.
3307
  step_action = StepIn;
3308
  break_point_hit_count = 0;
3309
  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
3310
  foo->Call(env->Global(), argc, argv_10);
3311
  CHECK_EQ(23, break_point_hit_count);
3312

    
3313
  // Looping 100 times.
3314
  step_action = StepIn;
3315
  break_point_hit_count = 0;
3316
  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
3317
  foo->Call(env->Global(), argc, argv_100);
3318
  CHECK_EQ(203, break_point_hit_count);
3319

    
3320
  // Get rid of the debug event listener.
3321
  v8::Debug::SetDebugEventListener2(NULL);
3322
  CheckDebuggerUnloaded();
3323
}
3324

    
3325

    
3326
TEST(DebugStepForContinue) {
3327
  DebugLocalContext env;
3328
  v8::HandleScope scope(env->GetIsolate());
3329

    
3330
  // Register a debug event listener which steps and counts.
3331
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3332

    
3333
  // Create a function for testing stepping. Run it to allow it to get
3334
  // optimized.
3335
  const int argc = 1;
3336
  const char* src = "function foo(x) { "
3337
                    "  var a = 0;"
3338
                    "  var b = 0;"
3339
                    "  var c = 0;"
3340
                    "  for (var i = 0; i < x; i++) {"
3341
                    "    a++;"
3342
                    "    if (a % 2 == 0) continue;"
3343
                    "    b++;"
3344
                    "    c++;"
3345
                    "  }"
3346
                    "  return b;"
3347
                    "}"
3348
                    "foo()";
3349
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3350
  v8::Handle<v8::Value> result;
3351
  SetBreakPoint(foo, 8);  // "var a = 0;"
3352

    
3353
  // Each loop generates 4 or 5 steps depending on whether a is equal.
3354

    
3355
  // Looping 10 times.
3356
  step_action = StepIn;
3357
  break_point_hit_count = 0;
3358
  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
3359
  result = foo->Call(env->Global(), argc, argv_10);
3360
  CHECK_EQ(5, result->Int32Value());
3361
  CHECK_EQ(52, break_point_hit_count);
3362

    
3363
  // Looping 100 times.
3364
  step_action = StepIn;
3365
  break_point_hit_count = 0;
3366
  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
3367
  result = foo->Call(env->Global(), argc, argv_100);
3368
  CHECK_EQ(50, result->Int32Value());
3369
  CHECK_EQ(457, break_point_hit_count);
3370

    
3371
  // Get rid of the debug event listener.
3372
  v8::Debug::SetDebugEventListener2(NULL);
3373
  CheckDebuggerUnloaded();
3374
}
3375

    
3376

    
3377
TEST(DebugStepForBreak) {
3378
  DebugLocalContext env;
3379
  v8::HandleScope scope(env->GetIsolate());
3380

    
3381
  // Register a debug event listener which steps and counts.
3382
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3383

    
3384
  // Create a function for testing stepping. Run it to allow it to get
3385
  // optimized.
3386
  const int argc = 1;
3387
  const char* src = "function foo(x) { "
3388
                    "  var a = 0;"
3389
                    "  var b = 0;"
3390
                    "  var c = 0;"
3391
                    "  for (var i = 0; i < 1000; i++) {"
3392
                    "    a++;"
3393
                    "    if (a == x) break;"
3394
                    "    b++;"
3395
                    "    c++;"
3396
                    "  }"
3397
                    "  return b;"
3398
                    "}"
3399
                    "foo()";
3400
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3401
  v8::Handle<v8::Value> result;
3402
  SetBreakPoint(foo, 8);  // "var a = 0;"
3403

    
3404
  // Each loop generates 5 steps except for the last (when break is executed)
3405
  // which only generates 4.
3406

    
3407
  // Looping 10 times.
3408
  step_action = StepIn;
3409
  break_point_hit_count = 0;
3410
  v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(10) };
3411
  result = foo->Call(env->Global(), argc, argv_10);
3412
  CHECK_EQ(9, result->Int32Value());
3413
  CHECK_EQ(55, break_point_hit_count);
3414

    
3415
  // Looping 100 times.
3416
  step_action = StepIn;
3417
  break_point_hit_count = 0;
3418
  v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(100) };
3419
  result = foo->Call(env->Global(), argc, argv_100);
3420
  CHECK_EQ(99, result->Int32Value());
3421
  CHECK_EQ(505, break_point_hit_count);
3422

    
3423
  // Get rid of the debug event listener.
3424
  v8::Debug::SetDebugEventListener2(NULL);
3425
  CheckDebuggerUnloaded();
3426
}
3427

    
3428

    
3429
TEST(DebugStepForIn) {
3430
  DebugLocalContext env;
3431
  v8::HandleScope scope(env->GetIsolate());
3432

    
3433
  // Register a debug event listener which steps and counts.
3434
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3435

    
3436
  // Create a function for testing stepping. Run it to allow it to get
3437
  // optimized.
3438
  v8::Local<v8::Function> foo;
3439
  const char* src_1 = "function foo() { "
3440
                      "  var a = [1, 2];"
3441
                      "  for (x in a) {"
3442
                      "    b = 0;"
3443
                      "  }"
3444
                      "}"
3445
                      "foo()";
3446
  foo = CompileFunction(&env, src_1, "foo");
3447
  SetBreakPoint(foo, 0);  // "var a = ..."
3448

    
3449
  step_action = StepIn;
3450
  break_point_hit_count = 0;
3451
  foo->Call(env->Global(), 0, NULL);
3452
  CHECK_EQ(6, break_point_hit_count);
3453

    
3454
  // Create a function for testing stepping. Run it to allow it to get
3455
  // optimized.
3456
  const char* src_2 = "function foo() { "
3457
                      "  var a = {a:[1, 2, 3]};"
3458
                      "  for (x in a.a) {"
3459
                      "    b = 0;"
3460
                      "  }"
3461
                      "}"
3462
                      "foo()";
3463
  foo = CompileFunction(&env, src_2, "foo");
3464
  SetBreakPoint(foo, 0);  // "var a = ..."
3465

    
3466
  step_action = StepIn;
3467
  break_point_hit_count = 0;
3468
  foo->Call(env->Global(), 0, NULL);
3469
  CHECK_EQ(8, break_point_hit_count);
3470

    
3471
  // Get rid of the debug event listener.
3472
  v8::Debug::SetDebugEventListener2(NULL);
3473
  CheckDebuggerUnloaded();
3474
}
3475

    
3476

    
3477
TEST(DebugStepWith) {
3478
  DebugLocalContext env;
3479
  v8::HandleScope scope(env->GetIsolate());
3480

    
3481
  // Register a debug event listener which steps and counts.
3482
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3483

    
3484
  // Create a function for testing stepping. Run it to allow it to get
3485
  // optimized.
3486
  const char* src = "function foo(x) { "
3487
                    "  var a = {};"
3488
                    "  with (a) {}"
3489
                    "  with (b) {}"
3490
                    "}"
3491
                    "foo()";
3492
  env->Global()->Set(v8::String::New("b"), v8::Object::New());
3493
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3494
  v8::Handle<v8::Value> result;
3495
  SetBreakPoint(foo, 8);  // "var a = {};"
3496

    
3497
  step_action = StepIn;
3498
  break_point_hit_count = 0;
3499
  foo->Call(env->Global(), 0, NULL);
3500
  CHECK_EQ(4, break_point_hit_count);
3501

    
3502
  // Get rid of the debug event listener.
3503
  v8::Debug::SetDebugEventListener2(NULL);
3504
  CheckDebuggerUnloaded();
3505
}
3506

    
3507

    
3508
TEST(DebugConditional) {
3509
  DebugLocalContext env;
3510
  v8::Isolate* isolate = env->GetIsolate();
3511
  v8::HandleScope scope(isolate);
3512

    
3513
  // Register a debug event listener which steps and counts.
3514
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3515

    
3516
  // Create a function for testing stepping. Run it to allow it to get
3517
  // optimized.
3518
  const char* src = "function foo(x) { "
3519
                    "  var a;"
3520
                    "  a = x ? 1 : 2;"
3521
                    "  return a;"
3522
                    "}"
3523
                    "foo()";
3524
  v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
3525
  SetBreakPoint(foo, 0);  // "var a;"
3526

    
3527
  step_action = StepIn;
3528
  break_point_hit_count = 0;
3529
  foo->Call(env->Global(), 0, NULL);
3530
  CHECK_EQ(5, break_point_hit_count);
3531

    
3532
  step_action = StepIn;
3533
  break_point_hit_count = 0;
3534
  const int argc = 1;
3535
  v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
3536
  foo->Call(env->Global(), argc, argv_true);
3537
  CHECK_EQ(5, break_point_hit_count);
3538

    
3539
  // Get rid of the debug event listener.
3540
  v8::Debug::SetDebugEventListener2(NULL);
3541
  CheckDebuggerUnloaded();
3542
}
3543

    
3544

    
3545
TEST(StepInOutSimple) {
3546
  DebugLocalContext env;
3547
  v8::HandleScope scope(env->GetIsolate());
3548

    
3549
  // Create a function for checking the function when hitting a break point.
3550
  frame_function_name = CompileFunction(&env,
3551
                                        frame_function_name_source,
3552
                                        "frame_function_name");
3553

    
3554
  // Register a debug event listener which steps and counts.
3555
  v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
3556

    
3557
  // Create a function for testing stepping. Run it to allow it to get
3558
  // optimized.
3559
  const char* src = "function a() {b();c();}; "
3560
                    "function b() {c();}; "
3561
                    "function c() {}; "
3562
                    "a(); b(); c()";
3563
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3564
  SetBreakPoint(a, 0);
3565

    
3566
  // Step through invocation of a with step in.
3567
  step_action = StepIn;
3568
  break_point_hit_count = 0;
3569
  expected_step_sequence = "abcbaca";
3570
  a->Call(env->Global(), 0, NULL);
3571
  CHECK_EQ(StrLength(expected_step_sequence),
3572
           break_point_hit_count);
3573

    
3574
  // Step through invocation of a with step next.
3575
  step_action = StepNext;
3576
  break_point_hit_count = 0;
3577
  expected_step_sequence = "aaa";
3578
  a->Call(env->Global(), 0, NULL);
3579
  CHECK_EQ(StrLength(expected_step_sequence),
3580
           break_point_hit_count);
3581

    
3582
  // Step through invocation of a with step out.
3583
  step_action = StepOut;
3584
  break_point_hit_count = 0;
3585
  expected_step_sequence = "a";
3586
  a->Call(env->Global(), 0, NULL);
3587
  CHECK_EQ(StrLength(expected_step_sequence),
3588
           break_point_hit_count);
3589

    
3590
  // Get rid of the debug event listener.
3591
  v8::Debug::SetDebugEventListener2(NULL);
3592
  CheckDebuggerUnloaded();
3593
}
3594

    
3595

    
3596
TEST(StepInOutTree) {
3597
  DebugLocalContext env;
3598
  v8::HandleScope scope(env->GetIsolate());
3599

    
3600
  // Create a function for checking the function when hitting a break point.
3601
  frame_function_name = CompileFunction(&env,
3602
                                        frame_function_name_source,
3603
                                        "frame_function_name");
3604

    
3605
  // Register a debug event listener which steps and counts.
3606
  v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
3607

    
3608
  // Create a function for testing stepping. Run it to allow it to get
3609
  // optimized.
3610
  const char* src = "function a() {b(c(d()),d());c(d());d()}; "
3611
                    "function b(x,y) {c();}; "
3612
                    "function c(x) {}; "
3613
                    "function d() {}; "
3614
                    "a(); b(); c(); d()";
3615
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3616
  SetBreakPoint(a, 0);
3617

    
3618
  // Step through invocation of a with step in.
3619
  step_action = StepIn;
3620
  break_point_hit_count = 0;
3621
  expected_step_sequence = "adacadabcbadacada";
3622
  a->Call(env->Global(), 0, NULL);
3623
  CHECK_EQ(StrLength(expected_step_sequence),
3624
           break_point_hit_count);
3625

    
3626
  // Step through invocation of a with step next.
3627
  step_action = StepNext;
3628
  break_point_hit_count = 0;
3629
  expected_step_sequence = "aaaa";
3630
  a->Call(env->Global(), 0, NULL);
3631
  CHECK_EQ(StrLength(expected_step_sequence),
3632
           break_point_hit_count);
3633

    
3634
  // Step through invocation of a with step out.
3635
  step_action = StepOut;
3636
  break_point_hit_count = 0;
3637
  expected_step_sequence = "a";
3638
  a->Call(env->Global(), 0, NULL);
3639
  CHECK_EQ(StrLength(expected_step_sequence),
3640
           break_point_hit_count);
3641

    
3642
  // Get rid of the debug event listener.
3643
  v8::Debug::SetDebugEventListener2(NULL);
3644
  CheckDebuggerUnloaded(true);
3645
}
3646

    
3647

    
3648
TEST(StepInOutBranch) {
3649
  DebugLocalContext env;
3650
  v8::HandleScope scope(env->GetIsolate());
3651

    
3652
  // Create a function for checking the function when hitting a break point.
3653
  frame_function_name = CompileFunction(&env,
3654
                                        frame_function_name_source,
3655
                                        "frame_function_name");
3656

    
3657
  // Register a debug event listener which steps and counts.
3658
  v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
3659

    
3660
  // Create a function for testing stepping. Run it to allow it to get
3661
  // optimized.
3662
  const char* src = "function a() {b(false);c();}; "
3663
                    "function b(x) {if(x){c();};}; "
3664
                    "function c() {}; "
3665
                    "a(); b(); c()";
3666
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
3667
  SetBreakPoint(a, 0);
3668

    
3669
  // Step through invocation of a.
3670
  step_action = StepIn;
3671
  break_point_hit_count = 0;
3672
  expected_step_sequence = "abbaca";
3673
  a->Call(env->Global(), 0, NULL);
3674
  CHECK_EQ(StrLength(expected_step_sequence),
3675
           break_point_hit_count);
3676

    
3677
  // Get rid of the debug event listener.
3678
  v8::Debug::SetDebugEventListener2(NULL);
3679
  CheckDebuggerUnloaded();
3680
}
3681

    
3682

    
3683
// Test that step in does not step into native functions.
3684
TEST(DebugStepNatives) {
3685
  DebugLocalContext env;
3686
  v8::HandleScope scope(env->GetIsolate());
3687

    
3688
  // Create a function for testing stepping.
3689
  v8::Local<v8::Function> foo = CompileFunction(
3690
      &env,
3691
      "function foo(){debugger;Math.sin(1);}",
3692
      "foo");
3693

    
3694
  // Register a debug event listener which steps and counts.
3695
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3696

    
3697
  step_action = StepIn;
3698
  break_point_hit_count = 0;
3699
  foo->Call(env->Global(), 0, NULL);
3700

    
3701
  // With stepping all break locations are hit.
3702
  CHECK_EQ(3, break_point_hit_count);
3703

    
3704
  v8::Debug::SetDebugEventListener2(NULL);
3705
  CheckDebuggerUnloaded();
3706

    
3707
  // Register a debug event listener which just counts.
3708
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
3709

    
3710
  break_point_hit_count = 0;
3711
  foo->Call(env->Global(), 0, NULL);
3712

    
3713
  // Without stepping only active break points are hit.
3714
  CHECK_EQ(1, break_point_hit_count);
3715

    
3716
  v8::Debug::SetDebugEventListener2(NULL);
3717
  CheckDebuggerUnloaded();
3718
}
3719

    
3720

    
3721
// Test that step in works with function.apply.
3722
TEST(DebugStepFunctionApply) {
3723
  DebugLocalContext env;
3724
  v8::HandleScope scope(env->GetIsolate());
3725

    
3726
  // Create a function for testing stepping.
3727
  v8::Local<v8::Function> foo = CompileFunction(
3728
      &env,
3729
      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3730
      "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
3731
      "foo");
3732

    
3733
  // Register a debug event listener which steps and counts.
3734
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3735

    
3736
  step_action = StepIn;
3737
  break_point_hit_count = 0;
3738
  foo->Call(env->Global(), 0, NULL);
3739

    
3740
  // With stepping all break locations are hit.
3741
  CHECK_EQ(7, break_point_hit_count);
3742

    
3743
  v8::Debug::SetDebugEventListener2(NULL);
3744
  CheckDebuggerUnloaded();
3745

    
3746
  // Register a debug event listener which just counts.
3747
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
3748

    
3749
  break_point_hit_count = 0;
3750
  foo->Call(env->Global(), 0, NULL);
3751

    
3752
  // Without stepping only the debugger statement is hit.
3753
  CHECK_EQ(1, break_point_hit_count);
3754

    
3755
  v8::Debug::SetDebugEventListener2(NULL);
3756
  CheckDebuggerUnloaded();
3757
}
3758

    
3759

    
3760
// Test that step in works with function.call.
3761
TEST(DebugStepFunctionCall) {
3762
  DebugLocalContext env;
3763
  v8::Isolate* isolate = env->GetIsolate();
3764
  v8::HandleScope scope(isolate);
3765

    
3766
  // Create a function for testing stepping.
3767
  v8::Local<v8::Function> foo = CompileFunction(
3768
      &env,
3769
      "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
3770
      "function foo(a){ debugger;"
3771
      "                 if (a) {"
3772
      "                   bar.call(this, 1, 2, 3);"
3773
      "                 } else {"
3774
      "                   bar.call(this, 0);"
3775
      "                 }"
3776
      "}",
3777
      "foo");
3778

    
3779
  // Register a debug event listener which steps and counts.
3780
  v8::Debug::SetDebugEventListener2(DebugEventStep);
3781
  step_action = StepIn;
3782

    
3783
  // Check stepping where the if condition in bar is false.
3784
  break_point_hit_count = 0;
3785
  foo->Call(env->Global(), 0, NULL);
3786
  CHECK_EQ(6, break_point_hit_count);
3787

    
3788
  // Check stepping where the if condition in bar is true.
3789
  break_point_hit_count = 0;
3790
  const int argc = 1;
3791
  v8::Handle<v8::Value> argv[argc] = { v8::True(isolate) };
3792
  foo->Call(env->Global(), argc, argv);
3793
  CHECK_EQ(8, break_point_hit_count);
3794

    
3795
  v8::Debug::SetDebugEventListener2(NULL);
3796
  CheckDebuggerUnloaded();
3797

    
3798
  // Register a debug event listener which just counts.
3799
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
3800

    
3801
  break_point_hit_count = 0;
3802
  foo->Call(env->Global(), 0, NULL);
3803

    
3804
  // Without stepping only the debugger statement is hit.
3805
  CHECK_EQ(1, break_point_hit_count);
3806

    
3807
  v8::Debug::SetDebugEventListener2(NULL);
3808
  CheckDebuggerUnloaded();
3809
}
3810

    
3811

    
3812
// Tests that breakpoint will be hit if it's set in script.
3813
TEST(PauseInScript) {
3814
  DebugLocalContext env;
3815
  v8::HandleScope scope(env->GetIsolate());
3816
  env.ExposeDebug();
3817

    
3818
  // Register a debug event listener which counts.
3819
  v8::Debug::SetDebugEventListener2(DebugEventCounter);
3820

    
3821
  // Create a script that returns a function.
3822
  const char* src = "(function (evt) {})";
3823
  const char* script_name = "StepInHandlerTest";
3824

    
3825
  // Set breakpoint in the script.
3826
  SetScriptBreakPointByNameFromJS(script_name, 0, -1);
3827
  break_point_hit_count = 0;
3828

    
3829
  v8::ScriptOrigin origin(v8::String::New(script_name), v8::Integer::New(0));
3830
  v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(src),
3831
                                                      &origin);
3832
  v8::Local<v8::Value> r = script->Run();
3833

    
3834
  CHECK(r->IsFunction());
3835
  CHECK_EQ(1, break_point_hit_count);
3836

    
3837
  // Get rid of the debug event listener.
3838
  v8::Debug::SetDebugEventListener2(NULL);
3839
  CheckDebuggerUnloaded();
3840
}
3841

    
3842

    
3843
// Test break on exceptions. For each exception break combination the number
3844
// of debug event exception callbacks and message callbacks are collected. The
3845
// number of debug event exception callbacks are used to check that the
3846
// debugger is called correctly and the number of message callbacks is used to
3847
// check that uncaught exceptions are still returned even if there is a break
3848
// for them.
3849
TEST(BreakOnException) {
3850
  DebugLocalContext env;
3851
  v8::HandleScope scope(env->GetIsolate());
3852
  env.ExposeDebug();
3853

    
3854
  CcTest::i_isolate()->TraceException(false);
3855

    
3856
  // Create functions for testing break on exception.
3857
  CompileFunction(&env, "function throws(){throw 1;}", "throws");
3858
  v8::Local<v8::Function> caught =
3859
      CompileFunction(&env,
3860
                      "function caught(){try {throws();} catch(e) {};}",
3861
                      "caught");
3862
  v8::Local<v8::Function> notCaught =
3863
      CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
3864

    
3865
  v8::V8::AddMessageListener(MessageCallbackCount);
3866
  v8::Debug::SetDebugEventListener2(DebugEventCounter);
3867

    
3868
  // Initial state should be no break on exceptions.
3869
  DebugEventCounterClear();
3870
  MessageCallbackCountClear();
3871
  caught->Call(env->Global(), 0, NULL);
3872
  CHECK_EQ(0, exception_hit_count);
3873
  CHECK_EQ(0, uncaught_exception_hit_count);
3874
  CHECK_EQ(0, message_callback_count);
3875
  notCaught->Call(env->Global(), 0, NULL);
3876
  CHECK_EQ(0, exception_hit_count);
3877
  CHECK_EQ(0, uncaught_exception_hit_count);
3878
  CHECK_EQ(1, message_callback_count);
3879

    
3880
  // No break on exception
3881
  DebugEventCounterClear();
3882
  MessageCallbackCountClear();
3883
  ChangeBreakOnException(false, false);
3884
  caught->Call(env->Global(), 0, NULL);
3885
  CHECK_EQ(0, exception_hit_count);
3886
  CHECK_EQ(0, uncaught_exception_hit_count);
3887
  CHECK_EQ(0, message_callback_count);
3888
  notCaught->Call(env->Global(), 0, NULL);
3889
  CHECK_EQ(0, exception_hit_count);
3890
  CHECK_EQ(0, uncaught_exception_hit_count);
3891
  CHECK_EQ(1, message_callback_count);
3892

    
3893
  // Break on uncaught exception
3894
  DebugEventCounterClear();
3895
  MessageCallbackCountClear();
3896
  ChangeBreakOnException(false, true);
3897
  caught->Call(env->Global(), 0, NULL);
3898
  CHECK_EQ(0, exception_hit_count);
3899
  CHECK_EQ(0, uncaught_exception_hit_count);
3900
  CHECK_EQ(0, message_callback_count);
3901
  notCaught->Call(env->Global(), 0, NULL);
3902
  CHECK_EQ(1, exception_hit_count);
3903
  CHECK_EQ(1, uncaught_exception_hit_count);
3904
  CHECK_EQ(1, message_callback_count);
3905

    
3906
  // Break on exception and uncaught exception
3907
  DebugEventCounterClear();
3908
  MessageCallbackCountClear();
3909
  ChangeBreakOnException(true, true);
3910
  caught->Call(env->Global(), 0, NULL);
3911
  CHECK_EQ(1, exception_hit_count);
3912
  CHECK_EQ(0, uncaught_exception_hit_count);
3913
  CHECK_EQ(0, message_callback_count);
3914
  notCaught->Call(env->Global(), 0, NULL);
3915
  CHECK_EQ(2, exception_hit_count);
3916
  CHECK_EQ(1, uncaught_exception_hit_count);
3917
  CHECK_EQ(1, message_callback_count);
3918

    
3919
  // Break on exception
3920
  DebugEventCounterClear();
3921
  MessageCallbackCountClear();
3922
  ChangeBreakOnException(true, false);
3923
  caught->Call(env->Global(), 0, NULL);
3924
  CHECK_EQ(1, exception_hit_count);
3925
  CHECK_EQ(0, uncaught_exception_hit_count);
3926
  CHECK_EQ(0, message_callback_count);
3927
  notCaught->Call(env->Global(), 0, NULL);
3928
  CHECK_EQ(2, exception_hit_count);
3929
  CHECK_EQ(1, uncaught_exception_hit_count);
3930
  CHECK_EQ(1, message_callback_count);
3931

    
3932
  // No break on exception using JavaScript
3933
  DebugEventCounterClear();
3934
  MessageCallbackCountClear();
3935
  ChangeBreakOnExceptionFromJS(false, false);
3936
  caught->Call(env->Global(), 0, NULL);
3937
  CHECK_EQ(0, exception_hit_count);
3938
  CHECK_EQ(0, uncaught_exception_hit_count);
3939
  CHECK_EQ(0, message_callback_count);
3940
  notCaught->Call(env->Global(), 0, NULL);
3941
  CHECK_EQ(0, exception_hit_count);
3942
  CHECK_EQ(0, uncaught_exception_hit_count);
3943
  CHECK_EQ(1, message_callback_count);
3944

    
3945
  // Break on uncaught exception using JavaScript
3946
  DebugEventCounterClear();
3947
  MessageCallbackCountClear();
3948
  ChangeBreakOnExceptionFromJS(false, true);
3949
  caught->Call(env->Global(), 0, NULL);
3950
  CHECK_EQ(0, exception_hit_count);
3951
  CHECK_EQ(0, uncaught_exception_hit_count);
3952
  CHECK_EQ(0, message_callback_count);
3953
  notCaught->Call(env->Global(), 0, NULL);
3954
  CHECK_EQ(1, exception_hit_count);
3955
  CHECK_EQ(1, uncaught_exception_hit_count);
3956
  CHECK_EQ(1, message_callback_count);
3957

    
3958
  // Break on exception and uncaught exception using JavaScript
3959
  DebugEventCounterClear();
3960
  MessageCallbackCountClear();
3961
  ChangeBreakOnExceptionFromJS(true, true);
3962
  caught->Call(env->Global(), 0, NULL);
3963
  CHECK_EQ(1, exception_hit_count);
3964
  CHECK_EQ(0, message_callback_count);
3965
  CHECK_EQ(0, uncaught_exception_hit_count);
3966
  notCaught->Call(env->Global(), 0, NULL);
3967
  CHECK_EQ(2, exception_hit_count);
3968
  CHECK_EQ(1, uncaught_exception_hit_count);
3969
  CHECK_EQ(1, message_callback_count);
3970

    
3971
  // Break on exception using JavaScript
3972
  DebugEventCounterClear();
3973
  MessageCallbackCountClear();
3974
  ChangeBreakOnExceptionFromJS(true, false);
3975
  caught->Call(env->Global(), 0, NULL);
3976
  CHECK_EQ(1, exception_hit_count);
3977
  CHECK_EQ(0, uncaught_exception_hit_count);
3978
  CHECK_EQ(0, message_callback_count);
3979
  notCaught->Call(env->Global(), 0, NULL);
3980
  CHECK_EQ(2, exception_hit_count);
3981
  CHECK_EQ(1, uncaught_exception_hit_count);
3982
  CHECK_EQ(1, message_callback_count);
3983

    
3984
  v8::Debug::SetDebugEventListener2(NULL);
3985
  CheckDebuggerUnloaded();
3986
  v8::V8::RemoveMessageListeners(MessageCallbackCount);
3987
}
3988

    
3989

    
3990
// Test break on exception from compiler errors. When compiling using
3991
// v8::Script::Compile there is no JavaScript stack whereas when compiling using
3992
// eval there are JavaScript frames.
3993
TEST(BreakOnCompileException) {
3994
  DebugLocalContext env;
3995
  v8::HandleScope scope(env->GetIsolate());
3996

    
3997
  // For this test, we want to break on uncaught exceptions:
3998
  ChangeBreakOnException(false, true);
3999

    
4000
  CcTest::i_isolate()->TraceException(false);
4001

    
4002
  // Create a function for checking the function when hitting a break point.
4003
  frame_count = CompileFunction(&env, frame_count_source, "frame_count");
4004

    
4005
  v8::V8::AddMessageListener(MessageCallbackCount);
4006
  v8::Debug::SetDebugEventListener2(DebugEventCounter);
4007

    
4008
  DebugEventCounterClear();
4009
  MessageCallbackCountClear();
4010

    
4011
  // Check initial state.
4012
  CHECK_EQ(0, exception_hit_count);
4013
  CHECK_EQ(0, uncaught_exception_hit_count);
4014
  CHECK_EQ(0, message_callback_count);
4015
  CHECK_EQ(-1, last_js_stack_height);
4016

    
4017
  // Throws SyntaxError: Unexpected end of input
4018
  v8::Script::Compile(v8::String::New("+++"));
4019
  CHECK_EQ(1, exception_hit_count);
4020
  CHECK_EQ(1, uncaught_exception_hit_count);
4021
  CHECK_EQ(1, message_callback_count);
4022
  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
4023

    
4024
  // Throws SyntaxError: Unexpected identifier
4025
  v8::Script::Compile(v8::String::New("x x"));
4026
  CHECK_EQ(2, exception_hit_count);
4027
  CHECK_EQ(2, uncaught_exception_hit_count);
4028
  CHECK_EQ(2, message_callback_count);
4029
  CHECK_EQ(0, last_js_stack_height);  // No JavaScript stack.
4030

    
4031
  // Throws SyntaxError: Unexpected end of input
4032
  v8::Script::Compile(v8::String::New("eval('+++')"))->Run();
4033
  CHECK_EQ(3, exception_hit_count);
4034
  CHECK_EQ(3, uncaught_exception_hit_count);
4035
  CHECK_EQ(3, message_callback_count);
4036
  CHECK_EQ(1, last_js_stack_height);
4037

    
4038
  // Throws SyntaxError: Unexpected identifier
4039
  v8::Script::Compile(v8::String::New("eval('x x')"))->Run();
4040
  CHECK_EQ(4, exception_hit_count);
4041
  CHECK_EQ(4, uncaught_exception_hit_count);
4042
  CHECK_EQ(4, message_callback_count);
4043
  CHECK_EQ(1, last_js_stack_height);
4044
}
4045

    
4046

    
4047
TEST(StepWithException) {
4048
  DebugLocalContext env;
4049
  v8::HandleScope scope(env->GetIsolate());
4050

    
4051
  // For this test, we want to break on uncaught exceptions:
4052
  ChangeBreakOnException(false, true);
4053

    
4054
  // Create a function for checking the function when hitting a break point.
4055
  frame_function_name = CompileFunction(&env,
4056
                                        frame_function_name_source,
4057
                                        "frame_function_name");
4058

    
4059
  // Register a debug event listener which steps and counts.
4060
  v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
4061

    
4062
  // Create functions for testing stepping.
4063
  const char* src = "function a() { n(); }; "
4064
                    "function b() { c(); }; "
4065
                    "function c() { n(); }; "
4066
                    "function d() { x = 1; try { e(); } catch(x) { x = 2; } }; "
4067
                    "function e() { n(); }; "
4068
                    "function f() { x = 1; try { g(); } catch(x) { x = 2; } }; "
4069
                    "function g() { h(); }; "
4070
                    "function h() { x = 1; throw 1; }; ";
4071

    
4072
  // Step through invocation of a.
4073
  v8::Local<v8::Function> a = CompileFunction(&env, src, "a");
4074
  SetBreakPoint(a, 0);
4075
  step_action = StepIn;
4076
  break_point_hit_count = 0;
4077
  expected_step_sequence = "aa";
4078
  a->Call(env->Global(), 0, NULL);
4079
  CHECK_EQ(StrLength(expected_step_sequence),
4080
           break_point_hit_count);
4081

    
4082
  // Step through invocation of b + c.
4083
  v8::Local<v8::Function> b = CompileFunction(&env, src, "b");
4084
  SetBreakPoint(b, 0);
4085
  step_action = StepIn;
4086
  break_point_hit_count = 0;
4087
  expected_step_sequence = "bcc";
4088
  b->Call(env->Global(), 0, NULL);
4089
  CHECK_EQ(StrLength(expected_step_sequence),
4090
           break_point_hit_count);
4091
  // Step through invocation of d + e.
4092
  v8::Local<v8::Function> d = CompileFunction(&env, src, "d");
4093
  SetBreakPoint(d, 0);
4094
  ChangeBreakOnException(false, true);
4095
  step_action = StepIn;
4096
  break_point_hit_count = 0;
4097
  expected_step_sequence = "ddedd";
4098
  d->Call(env->Global(), 0, NULL);
4099
  CHECK_EQ(StrLength(expected_step_sequence),
4100
           break_point_hit_count);
4101

    
4102
  // Step through invocation of d + e now with break on caught exceptions.
4103
  ChangeBreakOnException(true, true);
4104
  step_action = StepIn;
4105
  break_point_hit_count = 0;
4106
  expected_step_sequence = "ddeedd";
4107
  d->Call(env->Global(), 0, NULL);
4108
  CHECK_EQ(StrLength(expected_step_sequence),
4109
           break_point_hit_count);
4110

    
4111
  // Step through invocation of f + g + h.
4112
  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
4113
  SetBreakPoint(f, 0);
4114
  ChangeBreakOnException(false, true);
4115
  step_action = StepIn;
4116
  break_point_hit_count = 0;
4117
  expected_step_sequence = "ffghhff";
4118
  f->Call(env->Global(), 0, NULL);
4119
  CHECK_EQ(StrLength(expected_step_sequence),
4120
           break_point_hit_count);
4121

    
4122
  // Step through invocation of f + g + h now with break on caught exceptions.
4123
  ChangeBreakOnException(true, true);
4124
  step_action = StepIn;
4125
  break_point_hit_count = 0;
4126
  expected_step_sequence = "ffghhhff";
4127
  f->Call(env->Global(), 0, NULL);
4128
  CHECK_EQ(StrLength(expected_step_sequence),
4129
           break_point_hit_count);
4130

    
4131
  // Get rid of the debug event listener.
4132
  v8::Debug::SetDebugEventListener2(NULL);
4133
  CheckDebuggerUnloaded();
4134
}
4135

    
4136

    
4137
TEST(DebugBreak) {
4138
  i::FLAG_stress_compaction = false;
4139
#ifdef VERIFY_HEAP
4140
  i::FLAG_verify_heap = true;
4141
#endif
4142
  DebugLocalContext env;
4143
  v8::HandleScope scope(env->GetIsolate());
4144

    
4145
  // Register a debug event listener which sets the break flag and counts.
4146
  v8::Debug::SetDebugEventListener2(DebugEventBreak);
4147

    
4148
  // Create a function for testing stepping.
4149
  const char* src = "function f0() {}"
4150
                    "function f1(x1) {}"
4151
                    "function f2(x1,x2) {}"
4152
                    "function f3(x1,x2,x3) {}";
4153
  v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
4154
  v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
4155
  v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
4156
  v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
4157

    
4158
  // Call the function to make sure it is compiled.
4159
  v8::Handle<v8::Value> argv[] = { v8::Number::New(1),
4160
                                   v8::Number::New(1),
4161
                                   v8::Number::New(1),
4162
                                   v8::Number::New(1) };
4163

    
4164
  // Call all functions to make sure that they are compiled.
4165
  f0->Call(env->Global(), 0, NULL);
4166
  f1->Call(env->Global(), 0, NULL);
4167
  f2->Call(env->Global(), 0, NULL);
4168
  f3->Call(env->Global(), 0, NULL);
4169

    
4170
  // Set the debug break flag.
4171
  v8::Debug::DebugBreak(env->GetIsolate());
4172

    
4173
  // Call all functions with different argument count.
4174
  break_point_hit_count = 0;
4175
  for (unsigned int i = 0; i < ARRAY_SIZE(argv); i++) {
4176
    f0->Call(env->Global(), i, argv);
4177
    f1->Call(env->Global(), i, argv);
4178
    f2->Call(env->Global(), i, argv);
4179
    f3->Call(env->Global(), i, argv);
4180
  }
4181

    
4182
  // One break for each function called.
4183
  CHECK_EQ(4 * ARRAY_SIZE(argv), break_point_hit_count);
4184

    
4185
  // Get rid of the debug event listener.
4186
  v8::Debug::SetDebugEventListener2(NULL);
4187
  CheckDebuggerUnloaded();
4188
}
4189

    
4190

    
4191
// Test to ensure that JavaScript code keeps running while the debug break
4192
// through the stack limit flag is set but breaks are disabled.
4193
TEST(DisableBreak) {
4194
  DebugLocalContext env;
4195
  v8::HandleScope scope(env->GetIsolate());
4196

    
4197
  // Register a debug event listener which sets the break flag and counts.
4198
  v8::Debug::SetDebugEventListener2(DebugEventCounter);
4199

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

    
4204
  // Set the debug break flag.
4205
  v8::Debug::DebugBreak(env->GetIsolate());
4206

    
4207
  // Call all functions with different argument count.
4208
  break_point_hit_count = 0;
4209
  f->Call(env->Global(), 0, NULL);
4210
  CHECK_EQ(1, break_point_hit_count);
4211

    
4212
  {
4213
    v8::Debug::DebugBreak(env->GetIsolate());
4214
    i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
4215
    v8::internal::DisableBreak disable_break(isolate, true);
4216
    f->Call(env->Global(), 0, NULL);
4217
    CHECK_EQ(1, break_point_hit_count);
4218
  }
4219

    
4220
  f->Call(env->Global(), 0, NULL);
4221
  CHECK_EQ(2, break_point_hit_count);
4222

    
4223
  // Get rid of the debug event listener.
4224
  v8::Debug::SetDebugEventListener2(NULL);
4225
  CheckDebuggerUnloaded();
4226
}
4227

    
4228
static const char* kSimpleExtensionSource =
4229
  "(function Foo() {"
4230
  "  return 4;"
4231
  "})() ";
4232

    
4233
// http://crbug.com/28933
4234
// Test that debug break is disabled when bootstrapper is active.
4235
TEST(NoBreakWhenBootstrapping) {
4236
  v8::Isolate* isolate = CcTest::isolate();
4237
  v8::HandleScope scope(isolate);
4238

    
4239
  // Register a debug event listener which sets the break flag and counts.
4240
  v8::Debug::SetDebugEventListener2(DebugEventCounter);
4241

    
4242
  // Set the debug break flag.
4243
  v8::Debug::DebugBreak(isolate);
4244
  break_point_hit_count = 0;
4245
  {
4246
    // Create a context with an extension to make sure that some JavaScript
4247
    // code is executed during bootstrapping.
4248
    v8::RegisterExtension(new v8::Extension("simpletest",
4249
                                            kSimpleExtensionSource));
4250
    const char* extension_names[] = { "simpletest" };
4251
    v8::ExtensionConfiguration extensions(1, extension_names);
4252
    v8::HandleScope handle_scope(isolate);
4253
    v8::Context::New(isolate, &extensions);
4254
  }
4255
  // Check that no DebugBreak events occured during the context creation.
4256
  CHECK_EQ(0, break_point_hit_count);
4257

    
4258
  // Get rid of the debug event listener.
4259
  v8::Debug::SetDebugEventListener2(NULL);
4260
  CheckDebuggerUnloaded();
4261
}
4262

    
4263

    
4264
static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4265
  v8::Handle<v8::Array> result = v8::Array::New(3);
4266
  result->Set(v8::Integer::New(0), v8::String::New("a"));
4267
  result->Set(v8::Integer::New(1), v8::String::New("b"));
4268
  result->Set(v8::Integer::New(2), v8::String::New("c"));
4269
  info.GetReturnValue().Set(result);
4270
}
4271

    
4272

    
4273
static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
4274
  v8::Handle<v8::Array> result = v8::Array::New(2);
4275
  result->Set(v8::Integer::New(0), v8::Number::New(1));
4276
  result->Set(v8::Integer::New(1), v8::Number::New(10));
4277
  info.GetReturnValue().Set(result);
4278
}
4279

    
4280

    
4281
static void NamedGetter(v8::Local<v8::String> name,
4282
                        const v8::PropertyCallbackInfo<v8::Value>& info) {
4283
  v8::String::Utf8Value n(name);
4284
  if (strcmp(*n, "a") == 0) {
4285
    info.GetReturnValue().Set(v8::String::New("AA"));
4286
    return;
4287
  } else if (strcmp(*n, "b") == 0) {
4288
    info.GetReturnValue().Set(v8::String::New("BB"));
4289
    return;
4290
  } else if (strcmp(*n, "c") == 0) {
4291
    info.GetReturnValue().Set(v8::String::New("CC"));
4292
    return;
4293
  } else {
4294
    info.GetReturnValue().SetUndefined();
4295
    return;
4296
  }
4297
  info.GetReturnValue().Set(name);
4298
}
4299

    
4300

    
4301
static void IndexedGetter(uint32_t index,
4302
                          const v8::PropertyCallbackInfo<v8::Value>& info) {
4303
  info.GetReturnValue().Set(static_cast<double>(index + 1));
4304
}
4305

    
4306

    
4307
TEST(InterceptorPropertyMirror) {
4308
  // Create a V8 environment with debug access.
4309
  DebugLocalContext env;
4310
  v8::HandleScope scope(env->GetIsolate());
4311
  env.ExposeDebug();
4312

    
4313
  // Create object with named interceptor.
4314
  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
4315
  named->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
4316
  env->Global()->Set(v8::String::New("intercepted_named"),
4317
                     named->NewInstance());
4318

    
4319
  // Create object with indexed interceptor.
4320
  v8::Handle<v8::ObjectTemplate> indexed = v8::ObjectTemplate::New();
4321
  indexed->SetIndexedPropertyHandler(IndexedGetter,
4322
                                     NULL,
4323
                                     NULL,
4324
                                     NULL,
4325
                                     IndexedEnum);
4326
  env->Global()->Set(v8::String::New("intercepted_indexed"),
4327
                     indexed->NewInstance());
4328

    
4329
  // Create object with both named and indexed interceptor.
4330
  v8::Handle<v8::ObjectTemplate> both = v8::ObjectTemplate::New();
4331
  both->SetNamedPropertyHandler(NamedGetter, NULL, NULL, NULL, NamedEnum);
4332
  both->SetIndexedPropertyHandler(IndexedGetter, NULL, NULL, NULL, IndexedEnum);
4333
  env->Global()->Set(v8::String::New("intercepted_both"), both->NewInstance());
4334

    
4335
  // Get mirrors for the three objects with interceptor.
4336
  CompileRun(
4337
      "var named_mirror = debug.MakeMirror(intercepted_named);"
4338
      "var indexed_mirror = debug.MakeMirror(intercepted_indexed);"
4339
      "var both_mirror = debug.MakeMirror(intercepted_both)");
4340
  CHECK(CompileRun(
4341
       "named_mirror instanceof debug.ObjectMirror")->BooleanValue());
4342
  CHECK(CompileRun(
4343
        "indexed_mirror instanceof debug.ObjectMirror")->BooleanValue());
4344
  CHECK(CompileRun(
4345
        "both_mirror instanceof debug.ObjectMirror")->BooleanValue());
4346

    
4347
  // Get the property names from the interceptors
4348
  CompileRun(
4349
      "named_names = named_mirror.propertyNames();"
4350
      "indexed_names = indexed_mirror.propertyNames();"
4351
      "both_names = both_mirror.propertyNames()");
4352
  CHECK_EQ(3, CompileRun("named_names.length")->Int32Value());
4353
  CHECK_EQ(2, CompileRun("indexed_names.length")->Int32Value());
4354
  CHECK_EQ(5, CompileRun("both_names.length")->Int32Value());
4355

    
4356
  // Check the expected number of properties.
4357
  const char* source;
4358
  source = "named_mirror.properties().length";
4359
  CHECK_EQ(3, CompileRun(source)->Int32Value());
4360

    
4361
  source = "indexed_mirror.properties().length";
4362
  CHECK_EQ(2, CompileRun(source)->Int32Value());
4363

    
4364
  source = "both_mirror.properties().length";
4365
  CHECK_EQ(5, CompileRun(source)->Int32Value());
4366

    
4367
  // 1 is PropertyKind.Named;
4368
  source = "both_mirror.properties(1).length";
4369
  CHECK_EQ(3, CompileRun(source)->Int32Value());
4370

    
4371
  // 2 is PropertyKind.Indexed;
4372
  source = "both_mirror.properties(2).length";
4373
  CHECK_EQ(2, CompileRun(source)->Int32Value());
4374

    
4375
  // 3 is PropertyKind.Named  | PropertyKind.Indexed;
4376
  source = "both_mirror.properties(3).length";
4377
  CHECK_EQ(5, CompileRun(source)->Int32Value());
4378

    
4379
  // Get the interceptor properties for the object with only named interceptor.
4380
  CompileRun("var named_values = named_mirror.properties()");
4381

    
4382
  // Check that the properties are interceptor properties.
4383
  for (int i = 0; i < 3; i++) {
4384
    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4385
    OS::SNPrintF(buffer,
4386
                 "named_values[%d] instanceof debug.PropertyMirror", i);
4387
    CHECK(CompileRun(buffer.start())->BooleanValue());
4388

    
4389
    OS::SNPrintF(buffer, "named_values[%d].propertyType()", i);
4390
    CHECK_EQ(v8::internal::INTERCEPTOR,
4391
             CompileRun(buffer.start())->Int32Value());
4392

    
4393
    OS::SNPrintF(buffer, "named_values[%d].isNative()", i);
4394
    CHECK(CompileRun(buffer.start())->BooleanValue());
4395
  }
4396

    
4397
  // Get the interceptor properties for the object with only indexed
4398
  // interceptor.
4399
  CompileRun("var indexed_values = indexed_mirror.properties()");
4400

    
4401
  // Check that the properties are interceptor properties.
4402
  for (int i = 0; i < 2; i++) {
4403
    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4404
    OS::SNPrintF(buffer,
4405
                 "indexed_values[%d] instanceof debug.PropertyMirror", i);
4406
    CHECK(CompileRun(buffer.start())->BooleanValue());
4407
  }
4408

    
4409
  // Get the interceptor properties for the object with both types of
4410
  // interceptors.
4411
  CompileRun("var both_values = both_mirror.properties()");
4412

    
4413
  // Check that the properties are interceptor properties.
4414
  for (int i = 0; i < 5; i++) {
4415
    EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
4416
    OS::SNPrintF(buffer, "both_values[%d] instanceof debug.PropertyMirror", i);
4417
    CHECK(CompileRun(buffer.start())->BooleanValue());
4418
  }
4419

    
4420
  // Check the property names.
4421
  source = "both_values[0].name() == 'a'";
4422
  CHECK(CompileRun(source)->BooleanValue());
4423

    
4424
  source = "both_values[1].name() == 'b'";
4425
  CHECK(CompileRun(source)->BooleanValue());
4426

    
4427
  source = "both_values[2].name() == 'c'";
4428
  CHECK(CompileRun(source)->BooleanValue());
4429

    
4430
  source = "both_values[3].name() == 1";
4431
  CHECK(CompileRun(source)->BooleanValue());
4432

    
4433
  source = "both_values[4].name() == 10";
4434
  CHECK(CompileRun(source)->BooleanValue());
4435
}
4436

    
4437

    
4438
TEST(HiddenPrototypePropertyMirror) {
4439
  // Create a V8 environment with debug access.
4440
  DebugLocalContext env;
4441
  v8::HandleScope scope(env->GetIsolate());
4442
  env.ExposeDebug();
4443

    
4444
  v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
4445
  t0->InstanceTemplate()->Set(v8::String::New("x"), v8::Number::New(0));
4446
  v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
4447
  t1->SetHiddenPrototype(true);
4448
  t1->InstanceTemplate()->Set(v8::String::New("y"), v8::Number::New(1));
4449
  v8::Handle<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
4450
  t2->SetHiddenPrototype(true);
4451
  t2->InstanceTemplate()->Set(v8::String::New("z"), v8::Number::New(2));
4452
  v8::Handle<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
4453
  t3->InstanceTemplate()->Set(v8::String::New("u"), v8::Number::New(3));
4454

    
4455
  // Create object and set them on the global object.
4456
  v8::Handle<v8::Object> o0 = t0->GetFunction()->NewInstance();
4457
  env->Global()->Set(v8::String::New("o0"), o0);
4458
  v8::Handle<v8::Object> o1 = t1->GetFunction()->NewInstance();
4459
  env->Global()->Set(v8::String::New("o1"), o1);
4460
  v8::Handle<v8::Object> o2 = t2->GetFunction()->NewInstance();
4461
  env->Global()->Set(v8::String::New("o2"), o2);
4462
  v8::Handle<v8::Object> o3 = t3->GetFunction()->NewInstance();
4463
  env->Global()->Set(v8::String::New("o3"), o3);
4464

    
4465
  // Get mirrors for the four objects.
4466
  CompileRun(
4467
      "var o0_mirror = debug.MakeMirror(o0);"
4468
      "var o1_mirror = debug.MakeMirror(o1);"
4469
      "var o2_mirror = debug.MakeMirror(o2);"
4470
      "var o3_mirror = debug.MakeMirror(o3)");
4471
  CHECK(CompileRun("o0_mirror instanceof debug.ObjectMirror")->BooleanValue());
4472
  CHECK(CompileRun("o1_mirror instanceof debug.ObjectMirror")->BooleanValue());
4473
  CHECK(CompileRun("o2_mirror instanceof debug.ObjectMirror")->BooleanValue());
4474
  CHECK(CompileRun("o3_mirror instanceof debug.ObjectMirror")->BooleanValue());
4475

    
4476
  // Check that each object has one property.
4477
  CHECK_EQ(1, CompileRun(
4478
              "o0_mirror.propertyNames().length")->Int32Value());
4479
  CHECK_EQ(1, CompileRun(
4480
              "o1_mirror.propertyNames().length")->Int32Value());
4481
  CHECK_EQ(1, CompileRun(
4482
              "o2_mirror.propertyNames().length")->Int32Value());
4483
  CHECK_EQ(1, CompileRun(
4484
              "o3_mirror.propertyNames().length")->Int32Value());
4485

    
4486
  // Set o1 as prototype for o0. o1 has the hidden prototype flag so all
4487
  // properties on o1 should be seen on o0.
4488
  o0->Set(v8::String::New("__proto__"), o1);
4489
  CHECK_EQ(2, CompileRun(
4490
              "o0_mirror.propertyNames().length")->Int32Value());
4491
  CHECK_EQ(0, CompileRun(
4492
              "o0_mirror.property('x').value().value()")->Int32Value());
4493
  CHECK_EQ(1, CompileRun(
4494
              "o0_mirror.property('y').value().value()")->Int32Value());
4495

    
4496
  // Set o2 as prototype for o0 (it will end up after o1 as o1 has the hidden
4497
  // prototype flag. o2 also has the hidden prototype flag so all properties
4498
  // on o2 should be seen on o0 as well as properties on o1.
4499
  o0->Set(v8::String::New("__proto__"), o2);
4500
  CHECK_EQ(3, CompileRun(
4501
              "o0_mirror.propertyNames().length")->Int32Value());
4502
  CHECK_EQ(0, CompileRun(
4503
              "o0_mirror.property('x').value().value()")->Int32Value());
4504
  CHECK_EQ(1, CompileRun(
4505
              "o0_mirror.property('y').value().value()")->Int32Value());
4506
  CHECK_EQ(2, CompileRun(
4507
              "o0_mirror.property('z').value().value()")->Int32Value());
4508

    
4509
  // Set o3 as prototype for o0 (it will end up after o1 and o2 as both o1 and
4510
  // o2 has the hidden prototype flag. o3 does not have the hidden prototype
4511
  // flag so properties on o3 should not be seen on o0 whereas the properties
4512
  // from o1 and o2 should still be seen on o0.
4513
  // Final prototype chain: o0 -> o1 -> o2 -> o3
4514
  // Hidden prototypes:           ^^    ^^
4515
  o0->Set(v8::String::New("__proto__"), o3);
4516
  CHECK_EQ(3, CompileRun(
4517
              "o0_mirror.propertyNames().length")->Int32Value());
4518
  CHECK_EQ(1, CompileRun(
4519
              "o3_mirror.propertyNames().length")->Int32Value());
4520
  CHECK_EQ(0, CompileRun(
4521
              "o0_mirror.property('x').value().value()")->Int32Value());
4522
  CHECK_EQ(1, CompileRun(
4523
              "o0_mirror.property('y').value().value()")->Int32Value());
4524
  CHECK_EQ(2, CompileRun(
4525
              "o0_mirror.property('z').value().value()")->Int32Value());
4526
  CHECK(CompileRun("o0_mirror.property('u').isUndefined()")->BooleanValue());
4527

    
4528
  // The prototype (__proto__) for o0 should be o3 as o1 and o2 are hidden.
4529
  CHECK(CompileRun("o0_mirror.protoObject() == o3_mirror")->BooleanValue());
4530
}
4531

    
4532

    
4533
static void ProtperyXNativeGetter(
4534
    v8::Local<v8::String> property,
4535
    const v8::PropertyCallbackInfo<v8::Value>& info) {
4536
  info.GetReturnValue().Set(10);
4537
}
4538

    
4539

    
4540
TEST(NativeGetterPropertyMirror) {
4541
  // Create a V8 environment with debug access.
4542
  DebugLocalContext env;
4543
  v8::HandleScope scope(env->GetIsolate());
4544
  env.ExposeDebug();
4545

    
4546
  v8::Handle<v8::String> name = v8::String::New("x");
4547
  // Create object with named accessor.
4548
  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
4549
  named->SetAccessor(name, &ProtperyXNativeGetter, NULL,
4550
      v8::Handle<v8::Value>(), v8::DEFAULT, v8::None);
4551

    
4552
  // Create object with named property getter.
4553
  env->Global()->Set(v8::String::New("instance"), named->NewInstance());
4554
  CHECK_EQ(10, CompileRun("instance.x")->Int32Value());
4555

    
4556
  // Get mirror for the object with property getter.
4557
  CompileRun("var instance_mirror = debug.MakeMirror(instance);");
4558
  CHECK(CompileRun(
4559
      "instance_mirror instanceof debug.ObjectMirror")->BooleanValue());
4560

    
4561
  CompileRun("var named_names = instance_mirror.propertyNames();");
4562
  CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4563
  CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue());
4564
  CHECK(CompileRun(
4565
      "instance_mirror.property('x').value().isNumber()")->BooleanValue());
4566
  CHECK(CompileRun(
4567
      "instance_mirror.property('x').value().value() == 10")->BooleanValue());
4568
}
4569

    
4570

    
4571
static void ProtperyXNativeGetterThrowingError(
4572
    v8::Local<v8::String> property,
4573
    const v8::PropertyCallbackInfo<v8::Value>& info) {
4574
  CompileRun("throw new Error('Error message');");
4575
}
4576

    
4577

    
4578
TEST(NativeGetterThrowingErrorPropertyMirror) {
4579
  // Create a V8 environment with debug access.
4580
  DebugLocalContext env;
4581
  v8::HandleScope scope(env->GetIsolate());
4582
  env.ExposeDebug();
4583

    
4584
  v8::Handle<v8::String> name = v8::String::New("x");
4585
  // Create object with named accessor.
4586
  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
4587
  named->SetAccessor(name, &ProtperyXNativeGetterThrowingError, NULL,
4588
      v8::Handle<v8::Value>(), v8::DEFAULT, v8::None);
4589

    
4590
  // Create object with named property getter.
4591
  env->Global()->Set(v8::String::New("instance"), named->NewInstance());
4592

    
4593
  // Get mirror for the object with property getter.
4594
  CompileRun("var instance_mirror = debug.MakeMirror(instance);");
4595
  CHECK(CompileRun(
4596
      "instance_mirror instanceof debug.ObjectMirror")->BooleanValue());
4597
  CompileRun("named_names = instance_mirror.propertyNames();");
4598
  CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4599
  CHECK(CompileRun("named_names[0] == 'x'")->BooleanValue());
4600
  CHECK(CompileRun(
4601
      "instance_mirror.property('x').value().isError()")->BooleanValue());
4602

    
4603
  // Check that the message is that passed to the Error constructor.
4604
  CHECK(CompileRun(
4605
      "instance_mirror.property('x').value().message() == 'Error message'")->
4606
          BooleanValue());
4607
}
4608

    
4609

    
4610
// Test that hidden properties object is not returned as an unnamed property
4611
// among regular properties.
4612
// See http://crbug.com/26491
4613
TEST(NoHiddenProperties) {
4614
  // Create a V8 environment with debug access.
4615
  DebugLocalContext env;
4616
  v8::HandleScope scope(env->GetIsolate());
4617
  env.ExposeDebug();
4618

    
4619
  // Create an object in the global scope.
4620
  const char* source = "var obj = {a: 1};";
4621
  v8::Script::Compile(v8::String::New(source))->Run();
4622
  v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
4623
      env->Global()->Get(v8::String::New("obj")));
4624
  // Set a hidden property on the object.
4625
  obj->SetHiddenValue(v8::String::New("v8::test-debug::a"),
4626
                      v8::Int32::New(11));
4627

    
4628
  // Get mirror for the object with property getter.
4629
  CompileRun("var obj_mirror = debug.MakeMirror(obj);");
4630
  CHECK(CompileRun(
4631
      "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
4632
  CompileRun("var named_names = obj_mirror.propertyNames();");
4633
  // There should be exactly one property. But there is also an unnamed
4634
  // property whose value is hidden properties dictionary. The latter
4635
  // property should not be in the list of reguar properties.
4636
  CHECK_EQ(1, CompileRun("named_names.length")->Int32Value());
4637
  CHECK(CompileRun("named_names[0] == 'a'")->BooleanValue());
4638
  CHECK(CompileRun(
4639
      "obj_mirror.property('a').value().value() == 1")->BooleanValue());
4640

    
4641
  // Object created by t0 will become hidden prototype of object 'obj'.
4642
  v8::Handle<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
4643
  t0->InstanceTemplate()->Set(v8::String::New("b"), v8::Number::New(2));
4644
  t0->SetHiddenPrototype(true);
4645
  v8::Handle<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
4646
  t1->InstanceTemplate()->Set(v8::String::New("c"), v8::Number::New(3));
4647

    
4648
  // Create proto objects, add hidden properties to them and set them on
4649
  // the global object.
4650
  v8::Handle<v8::Object> protoObj = t0->GetFunction()->NewInstance();
4651
  protoObj->SetHiddenValue(v8::String::New("v8::test-debug::b"),
4652
                           v8::Int32::New(12));
4653
  env->Global()->Set(v8::String::New("protoObj"), protoObj);
4654
  v8::Handle<v8::Object> grandProtoObj = t1->GetFunction()->NewInstance();
4655
  grandProtoObj->SetHiddenValue(v8::String::New("v8::test-debug::c"),
4656
                                v8::Int32::New(13));
4657
  env->Global()->Set(v8::String::New("grandProtoObj"), grandProtoObj);
4658

    
4659
  // Setting prototypes: obj->protoObj->grandProtoObj
4660
  protoObj->Set(v8::String::New("__proto__"), grandProtoObj);
4661
  obj->Set(v8::String::New("__proto__"), protoObj);
4662

    
4663
  // Get mirror for the object with property getter.
4664
  CompileRun("var obj_mirror = debug.MakeMirror(obj);");
4665
  CHECK(CompileRun(
4666
      "obj_mirror instanceof debug.ObjectMirror")->BooleanValue());
4667
  CompileRun("var named_names = obj_mirror.propertyNames();");
4668
  // There should be exactly two properties - one from the object itself and
4669
  // another from its hidden prototype.
4670
  CHECK_EQ(2, CompileRun("named_names.length")->Int32Value());
4671
  CHECK(CompileRun("named_names.sort(); named_names[0] == 'a' &&"
4672
                   "named_names[1] == 'b'")->BooleanValue());
4673
  CHECK(CompileRun(
4674
      "obj_mirror.property('a').value().value() == 1")->BooleanValue());
4675
  CHECK(CompileRun(
4676
      "obj_mirror.property('b').value().value() == 2")->BooleanValue());
4677
}
4678

    
4679

    
4680
// Multithreaded tests of JSON debugger protocol
4681

    
4682
// Support classes
4683

    
4684
// Provides synchronization between N threads, where N is a template parameter.
4685
// The Wait() call blocks a thread until it is called for the Nth time, then all
4686
// calls return.  Each ThreadBarrier object can only be used once.
4687
template <int N>
4688
class ThreadBarrier V8_FINAL {
4689
 public:
4690
  ThreadBarrier() : num_blocked_(0) {}
4691

    
4692
  ~ThreadBarrier() {
4693
    LockGuard<Mutex> lock_guard(&mutex_);
4694
    if (num_blocked_ != 0) {
4695
      CHECK_EQ(N, num_blocked_);
4696
    }
4697
  }
4698

    
4699
  void Wait() {
4700
    LockGuard<Mutex> lock_guard(&mutex_);
4701
    CHECK_LT(num_blocked_, N);
4702
    num_blocked_++;
4703
    if (N == num_blocked_) {
4704
      // Signal and unblock all waiting threads.
4705
      cv_.NotifyAll();
4706
      printf("BARRIER\n\n");
4707
      fflush(stdout);
4708
    } else {  // Wait for the semaphore.
4709
      while (num_blocked_ < N) {
4710
        cv_.Wait(&mutex_);
4711
      }
4712
    }
4713
    CHECK_EQ(N, num_blocked_);
4714
  }
4715

    
4716
 private:
4717
  ConditionVariable cv_;
4718
  Mutex mutex_;
4719
  int num_blocked_;
4720

    
4721
  STATIC_CHECK(N > 0);
4722

    
4723
  DISALLOW_COPY_AND_ASSIGN(ThreadBarrier);
4724
};
4725

    
4726

    
4727
// A set containing enough barriers and semaphores for any of the tests.
4728
class Barriers {
4729
 public:
4730
  Barriers() : semaphore_1(0), semaphore_2(0) {}
4731
  ThreadBarrier<2> barrier_1;
4732
  ThreadBarrier<2> barrier_2;
4733
  ThreadBarrier<2> barrier_3;
4734
  ThreadBarrier<2> barrier_4;
4735
  ThreadBarrier<2> barrier_5;
4736
  v8::internal::Semaphore semaphore_1;
4737
  v8::internal::Semaphore semaphore_2;
4738
};
4739

    
4740

    
4741
// We match parts of the message to decide if it is a break message.
4742
bool IsBreakEventMessage(char *message) {
4743
  const char* type_event = "\"type\":\"event\"";
4744
  const char* event_break = "\"event\":\"break\"";
4745
  // Does the message contain both type:event and event:break?
4746
  return strstr(message, type_event) != NULL &&
4747
         strstr(message, event_break) != NULL;
4748
}
4749

    
4750

    
4751
// We match parts of the message to decide if it is a exception message.
4752
bool IsExceptionEventMessage(char *message) {
4753
  const char* type_event = "\"type\":\"event\"";
4754
  const char* event_exception = "\"event\":\"exception\"";
4755
  // Does the message contain both type:event and event:exception?
4756
  return strstr(message, type_event) != NULL &&
4757
      strstr(message, event_exception) != NULL;
4758
}
4759

    
4760

    
4761
// We match the message wether it is an evaluate response message.
4762
bool IsEvaluateResponseMessage(char* message) {
4763
  const char* type_response = "\"type\":\"response\"";
4764
  const char* command_evaluate = "\"command\":\"evaluate\"";
4765
  // Does the message contain both type:response and command:evaluate?
4766
  return strstr(message, type_response) != NULL &&
4767
         strstr(message, command_evaluate) != NULL;
4768
}
4769

    
4770

    
4771
static int StringToInt(const char* s) {
4772
  return atoi(s);  // NOLINT
4773
}
4774

    
4775

    
4776
// We match parts of the message to get evaluate result int value.
4777
int GetEvaluateIntResult(char *message) {
4778
  const char* value = "\"value\":";
4779
  char* pos = strstr(message, value);
4780
  if (pos == NULL) {
4781
    return -1;
4782
  }
4783
  int res = -1;
4784
  res = StringToInt(pos + strlen(value));
4785
  return res;
4786
}
4787

    
4788

    
4789
// We match parts of the message to get hit breakpoint id.
4790
int GetBreakpointIdFromBreakEventMessage(char *message) {
4791
  const char* breakpoints = "\"breakpoints\":[";
4792
  char* pos = strstr(message, breakpoints);
4793
  if (pos == NULL) {
4794
    return -1;
4795
  }
4796
  int res = -1;
4797
  res = StringToInt(pos + strlen(breakpoints));
4798
  return res;
4799
}
4800

    
4801

    
4802
// We match parts of the message to get total frames number.
4803
int GetTotalFramesInt(char *message) {
4804
  const char* prefix = "\"totalFrames\":";
4805
  char* pos = strstr(message, prefix);
4806
  if (pos == NULL) {
4807
    return -1;
4808
  }
4809
  pos += strlen(prefix);
4810
  int res = StringToInt(pos);
4811
  return res;
4812
}
4813

    
4814

    
4815
// We match parts of the message to get source line.
4816
int GetSourceLineFromBreakEventMessage(char *message) {
4817
  const char* source_line = "\"sourceLine\":";
4818
  char* pos = strstr(message, source_line);
4819
  if (pos == NULL) {
4820
    return -1;
4821
  }
4822
  int res = -1;
4823
  res = StringToInt(pos + strlen(source_line));
4824
  return res;
4825
}
4826

    
4827

    
4828
/* Test MessageQueues */
4829
/* Tests the message queues that hold debugger commands and
4830
 * response messages to the debugger.  Fills queues and makes
4831
 * them grow.
4832
 */
4833
Barriers message_queue_barriers;
4834

    
4835
// This is the debugger thread, that executes no v8 calls except
4836
// placing JSON debugger commands in the queue.
4837
class MessageQueueDebuggerThread : public v8::internal::Thread {
4838
 public:
4839
  MessageQueueDebuggerThread()
4840
      : Thread("MessageQueueDebuggerThread") { }
4841
  void Run();
4842
};
4843

    
4844

    
4845
static void MessageHandler(const v8::Debug::Message& message) {
4846
  v8::Handle<v8::String> json = message.GetJSON();
4847
  v8::String::AsciiValue ascii(json);
4848
  if (IsBreakEventMessage(*ascii)) {
4849
    // Lets test script wait until break occurs to send commands.
4850
    // Signals when a break is reported.
4851
    message_queue_barriers.semaphore_2.Signal();
4852
  }
4853

    
4854
  // Allow message handler to block on a semaphore, to test queueing of
4855
  // messages while blocked.
4856
  message_queue_barriers.semaphore_1.Wait();
4857
}
4858

    
4859

    
4860
void MessageQueueDebuggerThread::Run() {
4861
  const int kBufferSize = 1000;
4862
  uint16_t buffer_1[kBufferSize];
4863
  uint16_t buffer_2[kBufferSize];
4864
  const char* command_1 =
4865
      "{\"seq\":117,"
4866
       "\"type\":\"request\","
4867
       "\"command\":\"evaluate\","
4868
       "\"arguments\":{\"expression\":\"1+2\"}}";
4869
  const char* command_2 =
4870
    "{\"seq\":118,"
4871
     "\"type\":\"request\","
4872
     "\"command\":\"evaluate\","
4873
     "\"arguments\":{\"expression\":\"1+a\"}}";
4874
  const char* command_3 =
4875
    "{\"seq\":119,"
4876
     "\"type\":\"request\","
4877
     "\"command\":\"evaluate\","
4878
     "\"arguments\":{\"expression\":\"c.d * b\"}}";
4879
  const char* command_continue =
4880
    "{\"seq\":106,"
4881
     "\"type\":\"request\","
4882
     "\"command\":\"continue\"}";
4883
  const char* command_single_step =
4884
    "{\"seq\":107,"
4885
     "\"type\":\"request\","
4886
     "\"command\":\"continue\","
4887
     "\"arguments\":{\"stepaction\":\"next\"}}";
4888

    
4889
  /* Interleaved sequence of actions by the two threads:*/
4890
  // Main thread compiles and runs source_1
4891
  message_queue_barriers.semaphore_1.Signal();
4892
  message_queue_barriers.barrier_1.Wait();
4893
  // Post 6 commands, filling the command queue and making it expand.
4894
  // These calls return immediately, but the commands stay on the queue
4895
  // until the execution of source_2.
4896
  // Note: AsciiToUtf16 executes before SendCommand, so command is copied
4897
  // to buffer before buffer is sent to SendCommand.
4898
  v8::Isolate* isolate = CcTest::isolate();
4899
  v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
4900
  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
4901
  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4902
  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4903
  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4904
  message_queue_barriers.barrier_2.Wait();
4905
  // Main thread compiles and runs source_2.
4906
  // Queued commands are executed at the start of compilation of source_2(
4907
  // beforeCompile event).
4908
  // Free the message handler to process all the messages from the queue. 7
4909
  // messages are expected: 2 afterCompile events and 5 responses.
4910
  // All the commands added so far will fail to execute as long as call stack
4911
  // is empty on beforeCompile event.
4912
  for (int i = 0; i < 6 ; ++i) {
4913
    message_queue_barriers.semaphore_1.Signal();
4914
  }
4915
  message_queue_barriers.barrier_3.Wait();
4916
  // Main thread compiles and runs source_3.
4917
  // Don't stop in the afterCompile handler.
4918
  message_queue_barriers.semaphore_1.Signal();
4919
  // source_3 includes a debugger statement, which causes a break event.
4920
  // Wait on break event from hitting "debugger" statement
4921
  message_queue_barriers.semaphore_2.Wait();
4922
  // These should execute after the "debugger" statement in source_2
4923
  v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1));
4924
  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2));
4925
  v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2));
4926
  v8::Debug::SendCommand(
4927
      isolate, buffer_2, AsciiToUtf16(command_single_step, buffer_2));
4928
  // Run after 2 break events, 4 responses.
4929
  for (int i = 0; i < 6 ; ++i) {
4930
    message_queue_barriers.semaphore_1.Signal();
4931
  }
4932
  // Wait on break event after a single step executes.
4933
  message_queue_barriers.semaphore_2.Wait();
4934
  v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_2, buffer_1));
4935
  v8::Debug::SendCommand(
4936
      isolate, buffer_2, AsciiToUtf16(command_continue, buffer_2));
4937
  // Run after 2 responses.
4938
  for (int i = 0; i < 2 ; ++i) {
4939
    message_queue_barriers.semaphore_1.Signal();
4940
  }
4941
  // Main thread continues running source_3 to end, waits for this thread.
4942
}
4943

    
4944

    
4945
// This thread runs the v8 engine.
4946
TEST(MessageQueues) {
4947
  MessageQueueDebuggerThread message_queue_debugger_thread;
4948

    
4949
  // Create a V8 environment
4950
  DebugLocalContext env;
4951
  v8::HandleScope scope(env->GetIsolate());
4952
  v8::Debug::SetMessageHandler2(MessageHandler);
4953
  message_queue_debugger_thread.Start();
4954

    
4955
  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
4956
  const char* source_2 = "e = 17;";
4957
  const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;";
4958

    
4959
  // See MessageQueueDebuggerThread::Run for interleaved sequence of
4960
  // API calls and events in the two threads.
4961
  CompileRun(source_1);
4962
  message_queue_barriers.barrier_1.Wait();
4963
  message_queue_barriers.barrier_2.Wait();
4964
  CompileRun(source_2);
4965
  message_queue_barriers.barrier_3.Wait();
4966
  CompileRun(source_3);
4967
  message_queue_debugger_thread.Join();
4968
  fflush(stdout);
4969
}
4970

    
4971

    
4972
class TestClientData : public v8::Debug::ClientData {
4973
 public:
4974
  TestClientData() {
4975
    constructor_call_counter++;
4976
  }
4977
  virtual ~TestClientData() {
4978
    destructor_call_counter++;
4979
  }
4980

    
4981
  static void ResetCounters() {
4982
    constructor_call_counter = 0;
4983
    destructor_call_counter = 0;
4984
  }
4985

    
4986
  static int constructor_call_counter;
4987
  static int destructor_call_counter;
4988
};
4989

    
4990
int TestClientData::constructor_call_counter = 0;
4991
int TestClientData::destructor_call_counter = 0;
4992

    
4993

    
4994
// Tests that MessageQueue doesn't destroy client data when expands and
4995
// does destroy when it dies.
4996
TEST(MessageQueueExpandAndDestroy) {
4997
  TestClientData::ResetCounters();
4998
  { // Create a scope for the queue.
4999
    CommandMessageQueue queue(1);
5000
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5001
                                  new TestClientData()));
5002
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5003
                                  new TestClientData()));
5004
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5005
                                  new TestClientData()));
5006
    CHECK_EQ(0, TestClientData::destructor_call_counter);
5007
    queue.Get().Dispose();
5008
    CHECK_EQ(1, TestClientData::destructor_call_counter);
5009
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5010
                                  new TestClientData()));
5011
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5012
                                  new TestClientData()));
5013
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5014
                                  new TestClientData()));
5015
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5016
                                  new TestClientData()));
5017
    queue.Put(CommandMessage::New(Vector<uint16_t>::empty(),
5018
                                  new TestClientData()));
5019
    CHECK_EQ(1, TestClientData::destructor_call_counter);
5020
    queue.Get().Dispose();
5021
    CHECK_EQ(2, TestClientData::destructor_call_counter);
5022
  }
5023
  // All the client data should be destroyed when the queue is destroyed.
5024
  CHECK_EQ(TestClientData::destructor_call_counter,
5025
           TestClientData::destructor_call_counter);
5026
}
5027

    
5028

    
5029
static int handled_client_data_instances_count = 0;
5030
static void MessageHandlerCountingClientData(
5031
    const v8::Debug::Message& message) {
5032
  if (message.GetClientData() != NULL) {
5033
    handled_client_data_instances_count++;
5034
  }
5035
}
5036

    
5037

    
5038
// Tests that all client data passed to the debugger are sent to the handler.
5039
TEST(SendClientDataToHandler) {
5040
  // Create a V8 environment
5041
  DebugLocalContext env;
5042
  v8::Isolate* isolate = env->GetIsolate();
5043
  v8::HandleScope scope(isolate);
5044
  TestClientData::ResetCounters();
5045
  handled_client_data_instances_count = 0;
5046
  v8::Debug::SetMessageHandler2(MessageHandlerCountingClientData);
5047
  const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
5048
  const int kBufferSize = 1000;
5049
  uint16_t buffer[kBufferSize];
5050
  const char* command_1 =
5051
      "{\"seq\":117,"
5052
       "\"type\":\"request\","
5053
       "\"command\":\"evaluate\","
5054
       "\"arguments\":{\"expression\":\"1+2\"}}";
5055
  const char* command_2 =
5056
    "{\"seq\":118,"
5057
     "\"type\":\"request\","
5058
     "\"command\":\"evaluate\","
5059
     "\"arguments\":{\"expression\":\"1+a\"}}";
5060
  const char* command_continue =
5061
    "{\"seq\":106,"
5062
     "\"type\":\"request\","
5063
     "\"command\":\"continue\"}";
5064

    
5065
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer),
5066
                         new TestClientData());
5067
  v8::Debug::SendCommand(
5068
      isolate, buffer, AsciiToUtf16(command_2, buffer), NULL);
5069
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5070
                         new TestClientData());
5071
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer),
5072
                         new TestClientData());
5073
  // All the messages will be processed on beforeCompile event.
5074
  CompileRun(source_1);
5075
  v8::Debug::SendCommand(
5076
      isolate, buffer, AsciiToUtf16(command_continue, buffer));
5077
  CHECK_EQ(3, TestClientData::constructor_call_counter);
5078
  CHECK_EQ(TestClientData::constructor_call_counter,
5079
           handled_client_data_instances_count);
5080
  CHECK_EQ(TestClientData::constructor_call_counter,
5081
           TestClientData::destructor_call_counter);
5082
}
5083

    
5084

    
5085
/* Test ThreadedDebugging */
5086
/* This test interrupts a running infinite loop that is
5087
 * occupying the v8 thread by a break command from the
5088
 * debugger thread.  It then changes the value of a
5089
 * global object, to make the loop terminate.
5090
 */
5091

    
5092
Barriers threaded_debugging_barriers;
5093

    
5094
class V8Thread : public v8::internal::Thread {
5095
 public:
5096
  V8Thread() : Thread("V8Thread") { }
5097
  void Run();
5098
};
5099

    
5100
class DebuggerThread : public v8::internal::Thread {
5101
 public:
5102
  DebuggerThread() : Thread("DebuggerThread") { }
5103
  void Run();
5104
};
5105

    
5106

    
5107
static void ThreadedAtBarrier1(
5108
    const v8::FunctionCallbackInfo<v8::Value>& args) {
5109
  threaded_debugging_barriers.barrier_1.Wait();
5110
}
5111

    
5112

    
5113
static void ThreadedMessageHandler(const v8::Debug::Message& message) {
5114
  static char print_buffer[1000];
5115
  v8::String::Value json(message.GetJSON());
5116
  Utf16ToAscii(*json, json.length(), print_buffer);
5117
  if (IsBreakEventMessage(print_buffer)) {
5118
    // Check that we are inside the while loop.
5119
    int source_line = GetSourceLineFromBreakEventMessage(print_buffer);
5120
    // TODO(2047): This should really be 8 <= source_line <= 13; but we
5121
    // currently have an off-by-one error when calculating the source
5122
    // position corresponding to the program counter at the debug break.
5123
    CHECK(7 <= source_line && source_line <= 13);
5124
    threaded_debugging_barriers.barrier_2.Wait();
5125
  }
5126
}
5127

    
5128

    
5129
void V8Thread::Run() {
5130
  const char* source =
5131
      "flag = true;\n"
5132
      "function bar( new_value ) {\n"
5133
      "  flag = new_value;\n"
5134
      "  return \"Return from bar(\" + new_value + \")\";\n"
5135
      "}\n"
5136
      "\n"
5137
      "function foo() {\n"
5138
      "  var x = 1;\n"
5139
      "  while ( flag == true ) {\n"
5140
      "    if ( x == 1 ) {\n"
5141
      "      ThreadedAtBarrier1();\n"
5142
      "    }\n"
5143
      "    x = x + 1;\n"
5144
      "  }\n"
5145
      "}\n"
5146
      "\n"
5147
      "foo();\n";
5148

    
5149
  v8::Isolate::Scope isolate_scope(CcTest::isolate());
5150
  DebugLocalContext env;
5151
  v8::HandleScope scope(env->GetIsolate());
5152
  v8::Debug::SetMessageHandler2(&ThreadedMessageHandler);
5153
  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
5154
  global_template->Set(v8::String::New("ThreadedAtBarrier1"),
5155
                       v8::FunctionTemplate::New(ThreadedAtBarrier1));
5156
  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate(),
5157
                                                     NULL,
5158
                                                     global_template);
5159
  v8::Context::Scope context_scope(context);
5160

    
5161
  CompileRun(source);
5162
}
5163

    
5164

    
5165
void DebuggerThread::Run() {
5166
  const int kBufSize = 1000;
5167
  uint16_t buffer[kBufSize];
5168

    
5169
  const char* command_1 = "{\"seq\":102,"
5170
      "\"type\":\"request\","
5171
      "\"command\":\"evaluate\","
5172
      "\"arguments\":{\"expression\":\"bar(false)\"}}";
5173
  const char* command_2 = "{\"seq\":103,"
5174
      "\"type\":\"request\","
5175
      "\"command\":\"continue\"}";
5176

    
5177
  v8::Isolate* isolate = CcTest::isolate();
5178
  threaded_debugging_barriers.barrier_1.Wait();
5179
  v8::Debug::DebugBreak(isolate);
5180
  threaded_debugging_barriers.barrier_2.Wait();
5181
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer));
5182
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer));
5183
}
5184

    
5185

    
5186
TEST(ThreadedDebugging) {
5187
  DebuggerThread debugger_thread;
5188
  V8Thread v8_thread;
5189

    
5190
  // Create a V8 environment
5191
  v8_thread.Start();
5192
  debugger_thread.Start();
5193

    
5194
  v8_thread.Join();
5195
  debugger_thread.Join();
5196
}
5197

    
5198

    
5199
/* Test RecursiveBreakpoints */
5200
/* In this test, the debugger evaluates a function with a breakpoint, after
5201
 * hitting a breakpoint in another function.  We do this with both values
5202
 * of the flag enabling recursive breakpoints, and verify that the second
5203
 * breakpoint is hit when enabled, and missed when disabled.
5204
 */
5205

    
5206
class BreakpointsV8Thread : public v8::internal::Thread {
5207
 public:
5208
  BreakpointsV8Thread() : Thread("BreakpointsV8Thread") { }
5209
  void Run();
5210
};
5211

    
5212
class BreakpointsDebuggerThread : public v8::internal::Thread {
5213
 public:
5214
  explicit BreakpointsDebuggerThread(bool global_evaluate)
5215
      : Thread("BreakpointsDebuggerThread"),
5216
        global_evaluate_(global_evaluate) {}
5217
  void Run();
5218

    
5219
 private:
5220
  bool global_evaluate_;
5221
};
5222

    
5223

    
5224
Barriers* breakpoints_barriers;
5225
int break_event_breakpoint_id;
5226
int evaluate_int_result;
5227

    
5228
static void BreakpointsMessageHandler(const v8::Debug::Message& message) {
5229
  static char print_buffer[1000];
5230
  v8::String::Value json(message.GetJSON());
5231
  Utf16ToAscii(*json, json.length(), print_buffer);
5232

    
5233
  if (IsBreakEventMessage(print_buffer)) {
5234
    break_event_breakpoint_id =
5235
        GetBreakpointIdFromBreakEventMessage(print_buffer);
5236
    breakpoints_barriers->semaphore_1.Signal();
5237
  } else if (IsEvaluateResponseMessage(print_buffer)) {
5238
    evaluate_int_result = GetEvaluateIntResult(print_buffer);
5239
    breakpoints_barriers->semaphore_1.Signal();
5240
  }
5241
}
5242

    
5243

    
5244
void BreakpointsV8Thread::Run() {
5245
  const char* source_1 = "var y_global = 3;\n"
5246
    "function cat( new_value ) {\n"
5247
    "  var x = new_value;\n"
5248
    "  y_global = y_global + 4;\n"
5249
    "  x = 3 * x + 1;\n"
5250
    "  y_global = y_global + 5;\n"
5251
    "  return x;\n"
5252
    "}\n"
5253
    "\n"
5254
    "function dog() {\n"
5255
    "  var x = 1;\n"
5256
    "  x = y_global;"
5257
    "  var z = 3;"
5258
    "  x += 100;\n"
5259
    "  return x;\n"
5260
    "}\n"
5261
    "\n";
5262
  const char* source_2 = "cat(17);\n"
5263
    "cat(19);\n";
5264

    
5265
  v8::Isolate* isolate = CcTest::isolate();
5266
  v8::Isolate::Scope isolate_scope(isolate);
5267
  DebugLocalContext env;
5268
  v8::HandleScope scope(isolate);
5269
  v8::Debug::SetMessageHandler2(&BreakpointsMessageHandler);
5270

    
5271
  CompileRun(source_1);
5272
  breakpoints_barriers->barrier_1.Wait();
5273
  breakpoints_barriers->barrier_2.Wait();
5274
  CompileRun(source_2);
5275
}
5276

    
5277

    
5278
void BreakpointsDebuggerThread::Run() {
5279
  const int kBufSize = 1000;
5280
  uint16_t buffer[kBufSize];
5281

    
5282
  const char* command_1 = "{\"seq\":101,"
5283
      "\"type\":\"request\","
5284
      "\"command\":\"setbreakpoint\","
5285
      "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
5286
  const char* command_2 = "{\"seq\":102,"
5287
      "\"type\":\"request\","
5288
      "\"command\":\"setbreakpoint\","
5289
      "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}";
5290
  const char* command_3;
5291
  if (this->global_evaluate_) {
5292
    command_3 = "{\"seq\":103,"
5293
        "\"type\":\"request\","
5294
        "\"command\":\"evaluate\","
5295
        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false,"
5296
        "\"global\":true}}";
5297
  } else {
5298
    command_3 = "{\"seq\":103,"
5299
        "\"type\":\"request\","
5300
        "\"command\":\"evaluate\","
5301
        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}";
5302
  }
5303
  const char* command_4;
5304
  if (this->global_evaluate_) {
5305
    command_4 = "{\"seq\":104,"
5306
        "\"type\":\"request\","
5307
        "\"command\":\"evaluate\","
5308
        "\"arguments\":{\"expression\":\"100 + 8\",\"disable_break\":true,"
5309
        "\"global\":true}}";
5310
  } else {
5311
    command_4 = "{\"seq\":104,"
5312
        "\"type\":\"request\","
5313
        "\"command\":\"evaluate\","
5314
        "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}";
5315
  }
5316
  const char* command_5 = "{\"seq\":105,"
5317
      "\"type\":\"request\","
5318
      "\"command\":\"continue\"}";
5319
  const char* command_6 = "{\"seq\":106,"
5320
      "\"type\":\"request\","
5321
      "\"command\":\"continue\"}";
5322
  const char* command_7;
5323
  if (this->global_evaluate_) {
5324
    command_7 = "{\"seq\":107,"
5325
        "\"type\":\"request\","
5326
        "\"command\":\"evaluate\","
5327
        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true,"
5328
        "\"global\":true}}";
5329
  } else {
5330
    command_7 = "{\"seq\":107,"
5331
        "\"type\":\"request\","
5332
        "\"command\":\"evaluate\","
5333
        "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}";
5334
  }
5335
  const char* command_8 = "{\"seq\":108,"
5336
      "\"type\":\"request\","
5337
      "\"command\":\"continue\"}";
5338

    
5339

    
5340
  v8::Isolate* isolate = CcTest::isolate();
5341
  v8::Isolate::Scope isolate_scope(isolate);
5342
  // v8 thread initializes, runs source_1
5343
  breakpoints_barriers->barrier_1.Wait();
5344
  // 1:Set breakpoint in cat() (will get id 1).
5345
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer));
5346
  // 2:Set breakpoint in dog() (will get id 2).
5347
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer));
5348
  breakpoints_barriers->barrier_2.Wait();
5349
  // V8 thread starts compiling source_2.
5350
  // Automatic break happens, to run queued commands
5351
  // breakpoints_barriers->semaphore_1.Wait();
5352
  // Commands 1 through 3 run, thread continues.
5353
  // v8 thread runs source_2 to breakpoint in cat().
5354
  // message callback receives break event.
5355
  breakpoints_barriers->semaphore_1.Wait();
5356
  // Must have hit breakpoint #1.
5357
  CHECK_EQ(1, break_event_breakpoint_id);
5358
  // 4:Evaluate dog() (which has a breakpoint).
5359
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_3, buffer));
5360
  // V8 thread hits breakpoint in dog().
5361
  breakpoints_barriers->semaphore_1.Wait();  // wait for break event
5362
  // Must have hit breakpoint #2.
5363
  CHECK_EQ(2, break_event_breakpoint_id);
5364
  // 5:Evaluate (x + 1).
5365
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_4, buffer));
5366
  // Evaluate (x + 1) finishes.
5367
  breakpoints_barriers->semaphore_1.Wait();
5368
  // Must have result 108.
5369
  CHECK_EQ(108, evaluate_int_result);
5370
  // 6:Continue evaluation of dog().
5371
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_5, buffer));
5372
  // Evaluate dog() finishes.
5373
  breakpoints_barriers->semaphore_1.Wait();
5374
  // Must have result 107.
5375
  CHECK_EQ(107, evaluate_int_result);
5376
  // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint
5377
  // in cat(19).
5378
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_6, buffer));
5379
  // Message callback gets break event.
5380
  breakpoints_barriers->semaphore_1.Wait();  // wait for break event
5381
  // Must have hit breakpoint #1.
5382
  CHECK_EQ(1, break_event_breakpoint_id);
5383
  // 8: Evaluate dog() with breaks disabled.
5384
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_7, buffer));
5385
  // Evaluate dog() finishes.
5386
  breakpoints_barriers->semaphore_1.Wait();
5387
  // Must have result 116.
5388
  CHECK_EQ(116, evaluate_int_result);
5389
  // 9: Continue evaluation of source2, reach end.
5390
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_8, buffer));
5391
}
5392

    
5393

    
5394
void TestRecursiveBreakpointsGeneric(bool global_evaluate) {
5395
  i::FLAG_debugger_auto_break = true;
5396

    
5397
  BreakpointsDebuggerThread breakpoints_debugger_thread(global_evaluate);
5398
  BreakpointsV8Thread breakpoints_v8_thread;
5399

    
5400
  // Create a V8 environment
5401
  Barriers stack_allocated_breakpoints_barriers;
5402
  breakpoints_barriers = &stack_allocated_breakpoints_barriers;
5403

    
5404
  breakpoints_v8_thread.Start();
5405
  breakpoints_debugger_thread.Start();
5406

    
5407
  breakpoints_v8_thread.Join();
5408
  breakpoints_debugger_thread.Join();
5409
}
5410

    
5411

    
5412
TEST(RecursiveBreakpoints) {
5413
  TestRecursiveBreakpointsGeneric(false);
5414
}
5415

    
5416

    
5417
TEST(RecursiveBreakpointsGlobal) {
5418
  TestRecursiveBreakpointsGeneric(true);
5419
}
5420

    
5421

    
5422
static void DummyDebugEventListener(
5423
    const v8::Debug::EventDetails& event_details) {
5424
}
5425

    
5426

    
5427
TEST(SetDebugEventListenerOnUninitializedVM) {
5428
  v8::Debug::SetDebugEventListener2(DummyDebugEventListener);
5429
}
5430

    
5431

    
5432
static void DummyMessageHandler(const v8::Debug::Message& message) {
5433
}
5434

    
5435

    
5436
TEST(SetMessageHandlerOnUninitializedVM) {
5437
  v8::Debug::SetMessageHandler2(DummyMessageHandler);
5438
}
5439

    
5440

    
5441
// Source for a JavaScript function which returns the data parameter of a
5442
// function called in the context of the debugger. If no data parameter is
5443
// passed it throws an exception.
5444
static const char* debugger_call_with_data_source =
5445
    "function debugger_call_with_data(exec_state, data) {"
5446
    "  if (data) return data;"
5447
    "  throw 'No data!'"
5448
    "}";
5449
v8::Handle<v8::Function> debugger_call_with_data;
5450

    
5451

    
5452
// Source for a JavaScript function which returns the data parameter of a
5453
// function called in the context of the debugger. If no data parameter is
5454
// passed it throws an exception.
5455
static const char* debugger_call_with_closure_source =
5456
    "var x = 3;"
5457
    "(function (exec_state) {"
5458
    "  if (exec_state.y) return x - 1;"
5459
    "  exec_state.y = x;"
5460
    "  return exec_state.y"
5461
    "})";
5462
v8::Handle<v8::Function> debugger_call_with_closure;
5463

    
5464
// Function to retrieve the number of JavaScript frames by calling a JavaScript
5465
// in the debugger.
5466
static void CheckFrameCount(const v8::FunctionCallbackInfo<v8::Value>& args) {
5467
  CHECK(v8::Debug::Call(frame_count)->IsNumber());
5468
  CHECK_EQ(args[0]->Int32Value(),
5469
           v8::Debug::Call(frame_count)->Int32Value());
5470
}
5471

    
5472

    
5473
// Function to retrieve the source line of the top JavaScript frame by calling a
5474
// JavaScript function in the debugger.
5475
static void CheckSourceLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
5476
  CHECK(v8::Debug::Call(frame_source_line)->IsNumber());
5477
  CHECK_EQ(args[0]->Int32Value(),
5478
           v8::Debug::Call(frame_source_line)->Int32Value());
5479
}
5480

    
5481

    
5482
// Function to test passing an additional parameter to a JavaScript function
5483
// called in the debugger. It also tests that functions called in the debugger
5484
// can throw exceptions.
5485
static void CheckDataParameter(
5486
    const v8::FunctionCallbackInfo<v8::Value>& args) {
5487
  v8::Handle<v8::String> data = v8::String::New("Test");
5488
  CHECK(v8::Debug::Call(debugger_call_with_data, data)->IsString());
5489

    
5490
  CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
5491
  CHECK(v8::Debug::Call(debugger_call_with_data).IsEmpty());
5492

    
5493
  v8::TryCatch catcher;
5494
  v8::Debug::Call(debugger_call_with_data);
5495
  CHECK(catcher.HasCaught());
5496
  CHECK(catcher.Exception()->IsString());
5497
}
5498

    
5499

    
5500
// Function to test using a JavaScript with closure in the debugger.
5501
static void CheckClosure(const v8::FunctionCallbackInfo<v8::Value>& args) {
5502
  CHECK(v8::Debug::Call(debugger_call_with_closure)->IsNumber());
5503
  CHECK_EQ(3, v8::Debug::Call(debugger_call_with_closure)->Int32Value());
5504
}
5505

    
5506

    
5507
// Test functions called through the debugger.
5508
TEST(CallFunctionInDebugger) {
5509
  // Create and enter a context with the functions CheckFrameCount,
5510
  // CheckSourceLine and CheckDataParameter installed.
5511
  v8::HandleScope scope(CcTest::isolate());
5512
  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
5513
  global_template->Set(v8::String::New("CheckFrameCount"),
5514
                       v8::FunctionTemplate::New(CheckFrameCount));
5515
  global_template->Set(v8::String::New("CheckSourceLine"),
5516
                       v8::FunctionTemplate::New(CheckSourceLine));
5517
  global_template->Set(v8::String::New("CheckDataParameter"),
5518
                       v8::FunctionTemplate::New(CheckDataParameter));
5519
  global_template->Set(v8::String::New("CheckClosure"),
5520
                       v8::FunctionTemplate::New(CheckClosure));
5521
  v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate(),
5522
                                                     NULL,
5523
                                                     global_template);
5524
  v8::Context::Scope context_scope(context);
5525

    
5526
  // Compile a function for checking the number of JavaScript frames.
5527
  v8::Script::Compile(v8::String::New(frame_count_source))->Run();
5528
  frame_count = v8::Local<v8::Function>::Cast(
5529
      context->Global()->Get(v8::String::New("frame_count")));
5530

    
5531
  // Compile a function for returning the source line for the top frame.
5532
  v8::Script::Compile(v8::String::New(frame_source_line_source))->Run();
5533
  frame_source_line = v8::Local<v8::Function>::Cast(
5534
      context->Global()->Get(v8::String::New("frame_source_line")));
5535

    
5536
  // Compile a function returning the data parameter.
5537
  v8::Script::Compile(v8::String::New(debugger_call_with_data_source))->Run();
5538
  debugger_call_with_data = v8::Local<v8::Function>::Cast(
5539
      context->Global()->Get(v8::String::New("debugger_call_with_data")));
5540

    
5541
  // Compile a function capturing closure.
5542
  debugger_call_with_closure = v8::Local<v8::Function>::Cast(
5543
      v8::Script::Compile(
5544
          v8::String::New(debugger_call_with_closure_source))->Run());
5545

    
5546
  // Calling a function through the debugger returns 0 frames if there are
5547
  // no JavaScript frames.
5548
  CHECK_EQ(v8::Integer::New(0), v8::Debug::Call(frame_count));
5549

    
5550
  // Test that the number of frames can be retrieved.
5551
  v8::Script::Compile(v8::String::New("CheckFrameCount(1)"))->Run();
5552
  v8::Script::Compile(v8::String::New("function f() {"
5553
                                      "  CheckFrameCount(2);"
5554
                                      "}; f()"))->Run();
5555

    
5556
  // Test that the source line can be retrieved.
5557
  v8::Script::Compile(v8::String::New("CheckSourceLine(0)"))->Run();
5558
  v8::Script::Compile(v8::String::New("function f() {\n"
5559
                                      "  CheckSourceLine(1)\n"
5560
                                      "  CheckSourceLine(2)\n"
5561
                                      "  CheckSourceLine(3)\n"
5562
                                      "}; f()"))->Run();
5563

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

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

    
5570

    
5571
  // Test that the source line is correct when there is a line offset.
5572
  v8::ScriptOrigin origin(v8::String::New("test"),
5573
                          v8::Integer::New(7));
5574
  v8::Script::Compile(v8::String::New("CheckSourceLine(7)"), &origin)->Run();
5575
  v8::Script::Compile(v8::String::New("function f() {\n"
5576
                                      "  CheckSourceLine(8)\n"
5577
                                      "  CheckSourceLine(9)\n"
5578
                                      "  CheckSourceLine(10)\n"
5579
                                      "}; f()"), &origin)->Run();
5580
}
5581

    
5582

    
5583
// Debugger message handler which counts the number of breaks.
5584
static void SendContinueCommand();
5585
static void MessageHandlerBreakPointHitCount(
5586
    const v8::Debug::Message& message) {
5587
  if (message.IsEvent() && message.GetEvent() == v8::Break) {
5588
    // Count the number of breaks.
5589
    break_point_hit_count++;
5590

    
5591
    SendContinueCommand();
5592
  }
5593
}
5594

    
5595

    
5596
// Test that clearing the debug event listener actually clears all break points
5597
// and related information.
5598
TEST(DebuggerUnload) {
5599
  DebugLocalContext env;
5600

    
5601
  // Check debugger is unloaded before it is used.
5602
  CheckDebuggerUnloaded();
5603

    
5604
  // Set a debug event listener.
5605
  break_point_hit_count = 0;
5606
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
5607
  {
5608
    v8::HandleScope scope(env->GetIsolate());
5609
    // Create a couple of functions for the test.
5610
    v8::Local<v8::Function> foo =
5611
        CompileFunction(&env, "function foo(){x=1}", "foo");
5612
    v8::Local<v8::Function> bar =
5613
        CompileFunction(&env, "function bar(){y=2}", "bar");
5614

    
5615
    // Set some break points.
5616
    SetBreakPoint(foo, 0);
5617
    SetBreakPoint(foo, 4);
5618
    SetBreakPoint(bar, 0);
5619
    SetBreakPoint(bar, 4);
5620

    
5621
    // Make sure that the break points are there.
5622
    break_point_hit_count = 0;
5623
    foo->Call(env->Global(), 0, NULL);
5624
    CHECK_EQ(2, break_point_hit_count);
5625
    bar->Call(env->Global(), 0, NULL);
5626
    CHECK_EQ(4, break_point_hit_count);
5627
  }
5628

    
5629
  // Remove the debug event listener without clearing breakpoints. Do this
5630
  // outside a handle scope.
5631
  v8::Debug::SetDebugEventListener2(NULL);
5632
  CheckDebuggerUnloaded(true);
5633

    
5634
  // Now set a debug message handler.
5635
  break_point_hit_count = 0;
5636
  v8::Debug::SetMessageHandler2(MessageHandlerBreakPointHitCount);
5637
  {
5638
    v8::HandleScope scope(env->GetIsolate());
5639

    
5640
    // Get the test functions again.
5641
    v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast(
5642
        env->Global()->Get(v8::String::New("foo"))));
5643

    
5644
    foo->Call(env->Global(), 0, NULL);
5645
    CHECK_EQ(0, break_point_hit_count);
5646

    
5647
    // Set break points and run again.
5648
    SetBreakPoint(foo, 0);
5649
    SetBreakPoint(foo, 4);
5650
    foo->Call(env->Global(), 0, NULL);
5651
    CHECK_EQ(2, break_point_hit_count);
5652
  }
5653

    
5654
  // Remove the debug message handler without clearing breakpoints. Do this
5655
  // outside a handle scope.
5656
  v8::Debug::SetMessageHandler2(NULL);
5657
  CheckDebuggerUnloaded(true);
5658
}
5659

    
5660

    
5661
// Sends continue command to the debugger.
5662
static void SendContinueCommand() {
5663
  const int kBufferSize = 1000;
5664
  uint16_t buffer[kBufferSize];
5665
  const char* command_continue =
5666
    "{\"seq\":0,"
5667
     "\"type\":\"request\","
5668
     "\"command\":\"continue\"}";
5669

    
5670
  v8::Debug::SendCommand(
5671
      CcTest::isolate(), buffer, AsciiToUtf16(command_continue, buffer));
5672
}
5673

    
5674

    
5675
// Debugger message handler which counts the number of times it is called.
5676
static int message_handler_hit_count = 0;
5677
static void MessageHandlerHitCount(const v8::Debug::Message& message) {
5678
  message_handler_hit_count++;
5679

    
5680
  static char print_buffer[1000];
5681
  v8::String::Value json(message.GetJSON());
5682
  Utf16ToAscii(*json, json.length(), print_buffer);
5683
  if (IsExceptionEventMessage(print_buffer)) {
5684
    // Send a continue command for exception events.
5685
    SendContinueCommand();
5686
  }
5687
}
5688

    
5689

    
5690
// Test clearing the debug message handler.
5691
TEST(DebuggerClearMessageHandler) {
5692
  DebugLocalContext env;
5693
  v8::HandleScope scope(env->GetIsolate());
5694

    
5695
  // Check debugger is unloaded before it is used.
5696
  CheckDebuggerUnloaded();
5697

    
5698
  // Set a debug message handler.
5699
  v8::Debug::SetMessageHandler2(MessageHandlerHitCount);
5700

    
5701
  // Run code to throw a unhandled exception. This should end up in the message
5702
  // handler.
5703
  CompileRun("throw 1");
5704

    
5705
  // The message handler should be called.
5706
  CHECK_GT(message_handler_hit_count, 0);
5707

    
5708
  // Clear debug message handler.
5709
  message_handler_hit_count = 0;
5710
  v8::Debug::SetMessageHandler2(NULL);
5711

    
5712
  // Run code to throw a unhandled exception. This should end up in the message
5713
  // handler.
5714
  CompileRun("throw 1");
5715

    
5716
  // The message handler should not be called more.
5717
  CHECK_EQ(0, message_handler_hit_count);
5718

    
5719
  CheckDebuggerUnloaded(true);
5720
}
5721

    
5722

    
5723
// Debugger message handler which clears the message handler while active.
5724
static void MessageHandlerClearingMessageHandler(
5725
    const v8::Debug::Message& message) {
5726
  message_handler_hit_count++;
5727

    
5728
  // Clear debug message handler.
5729
  v8::Debug::SetMessageHandler2(NULL);
5730
}
5731

    
5732

    
5733
// Test clearing the debug message handler while processing a debug event.
5734
TEST(DebuggerClearMessageHandlerWhileActive) {
5735
  DebugLocalContext env;
5736
  v8::HandleScope scope(env->GetIsolate());
5737

    
5738
  // Check debugger is unloaded before it is used.
5739
  CheckDebuggerUnloaded();
5740

    
5741
  // Set a debug message handler.
5742
  v8::Debug::SetMessageHandler2(MessageHandlerClearingMessageHandler);
5743

    
5744
  // Run code to throw a unhandled exception. This should end up in the message
5745
  // handler.
5746
  CompileRun("throw 1");
5747

    
5748
  // The message handler should be called.
5749
  CHECK_EQ(1, message_handler_hit_count);
5750

    
5751
  CheckDebuggerUnloaded(true);
5752
}
5753

    
5754

    
5755
/* Test DebuggerHostDispatch */
5756
/* In this test, the debugger waits for a command on a breakpoint
5757
 * and is dispatching host commands while in the infinite loop.
5758
 */
5759

    
5760
class HostDispatchV8Thread : public v8::internal::Thread {
5761
 public:
5762
  HostDispatchV8Thread() : Thread("HostDispatchV8Thread") { }
5763
  void Run();
5764
};
5765

    
5766
class HostDispatchDebuggerThread : public v8::internal::Thread {
5767
 public:
5768
  HostDispatchDebuggerThread() : Thread("HostDispatchDebuggerThread") { }
5769
  void Run();
5770
};
5771

    
5772
Barriers* host_dispatch_barriers;
5773

    
5774
static void HostDispatchMessageHandler(const v8::Debug::Message& message) {
5775
  static char print_buffer[1000];
5776
  v8::String::Value json(message.GetJSON());
5777
  Utf16ToAscii(*json, json.length(), print_buffer);
5778
}
5779

    
5780

    
5781
static void HostDispatchDispatchHandler() {
5782
  host_dispatch_barriers->semaphore_1.Signal();
5783
}
5784

    
5785

    
5786
void HostDispatchV8Thread::Run() {
5787
  const char* source_1 = "var y_global = 3;\n"
5788
    "function cat( new_value ) {\n"
5789
    "  var x = new_value;\n"
5790
    "  y_global = 4;\n"
5791
    "  x = 3 * x + 1;\n"
5792
    "  y_global = 5;\n"
5793
    "  return x;\n"
5794
    "}\n"
5795
    "\n";
5796
  const char* source_2 = "cat(17);\n";
5797

    
5798
  v8::Isolate::Scope isolate_scope(CcTest::isolate());
5799
  DebugLocalContext env;
5800
  v8::HandleScope scope(env->GetIsolate());
5801

    
5802
  // Set up message and host dispatch handlers.
5803
  v8::Debug::SetMessageHandler2(HostDispatchMessageHandler);
5804
  v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */);
5805

    
5806
  CompileRun(source_1);
5807
  host_dispatch_barriers->barrier_1.Wait();
5808
  host_dispatch_barriers->barrier_2.Wait();
5809
  CompileRun(source_2);
5810
}
5811

    
5812

    
5813
void HostDispatchDebuggerThread::Run() {
5814
  const int kBufSize = 1000;
5815
  uint16_t buffer[kBufSize];
5816

    
5817
  const char* command_1 = "{\"seq\":101,"
5818
      "\"type\":\"request\","
5819
      "\"command\":\"setbreakpoint\","
5820
      "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}";
5821
  const char* command_2 = "{\"seq\":102,"
5822
      "\"type\":\"request\","
5823
      "\"command\":\"continue\"}";
5824

    
5825
  v8::Isolate* isolate = CcTest::isolate();
5826
  // v8 thread initializes, runs source_1
5827
  host_dispatch_barriers->barrier_1.Wait();
5828
  // 1: Set breakpoint in cat().
5829
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer));
5830

    
5831
  host_dispatch_barriers->barrier_2.Wait();
5832
  // v8 thread starts compiling source_2.
5833
  // Break happens, to run queued commands and host dispatches.
5834
  // Wait for host dispatch to be processed.
5835
  host_dispatch_barriers->semaphore_1.Wait();
5836
  // 2: Continue evaluation
5837
  v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer));
5838
}
5839

    
5840

    
5841
TEST(DebuggerHostDispatch) {
5842
  HostDispatchDebuggerThread host_dispatch_debugger_thread;
5843
  HostDispatchV8Thread host_dispatch_v8_thread;
5844
  i::FLAG_debugger_auto_break = true;
5845

    
5846
  // Create a V8 environment
5847
  Barriers stack_allocated_host_dispatch_barriers;
5848
  host_dispatch_barriers = &stack_allocated_host_dispatch_barriers;
5849

    
5850
  host_dispatch_v8_thread.Start();
5851
  host_dispatch_debugger_thread.Start();
5852

    
5853
  host_dispatch_v8_thread.Join();
5854
  host_dispatch_debugger_thread.Join();
5855
}
5856

    
5857

    
5858
/* Test DebugMessageDispatch */
5859
/* In this test, the V8 thread waits for a message from the debug thread.
5860
 * The DebugMessageDispatchHandler is executed from the debugger thread
5861
 * which signals the V8 thread to wake up.
5862
 */
5863

    
5864
class DebugMessageDispatchV8Thread : public v8::internal::Thread {
5865
 public:
5866
  DebugMessageDispatchV8Thread() : Thread("DebugMessageDispatchV8Thread") { }
5867
  void Run();
5868
};
5869

    
5870
class DebugMessageDispatchDebuggerThread : public v8::internal::Thread {
5871
 public:
5872
  DebugMessageDispatchDebuggerThread()
5873
      : Thread("DebugMessageDispatchDebuggerThread") { }
5874
  void Run();
5875
};
5876

    
5877
Barriers* debug_message_dispatch_barriers;
5878

    
5879

    
5880
static void DebugMessageHandler() {
5881
  debug_message_dispatch_barriers->semaphore_1.Signal();
5882
}
5883

    
5884

    
5885
void DebugMessageDispatchV8Thread::Run() {
5886
  v8::Isolate::Scope isolate_scope(CcTest::isolate());
5887
  DebugLocalContext env;
5888
  v8::HandleScope scope(env->GetIsolate());
5889

    
5890
  // Set up debug message dispatch handler.
5891
  v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler);
5892

    
5893
  CompileRun("var y = 1 + 2;\n");
5894
  debug_message_dispatch_barriers->barrier_1.Wait();
5895
  debug_message_dispatch_barriers->semaphore_1.Wait();
5896
  debug_message_dispatch_barriers->barrier_2.Wait();
5897
}
5898

    
5899

    
5900
void DebugMessageDispatchDebuggerThread::Run() {
5901
  debug_message_dispatch_barriers->barrier_1.Wait();
5902
  SendContinueCommand();
5903
  debug_message_dispatch_barriers->barrier_2.Wait();
5904
}
5905

    
5906

    
5907
TEST(DebuggerDebugMessageDispatch) {
5908
  DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread;
5909
  DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread;
5910

    
5911
  i::FLAG_debugger_auto_break = true;
5912

    
5913
  // Create a V8 environment
5914
  Barriers stack_allocated_debug_message_dispatch_barriers;
5915
  debug_message_dispatch_barriers =
5916
      &stack_allocated_debug_message_dispatch_barriers;
5917

    
5918
  debug_message_dispatch_v8_thread.Start();
5919
  debug_message_dispatch_debugger_thread.Start();
5920

    
5921
  debug_message_dispatch_v8_thread.Join();
5922
  debug_message_dispatch_debugger_thread.Join();
5923
}
5924

    
5925

    
5926
TEST(DebuggerAgent) {
5927
  v8::V8::Initialize();
5928
  i::Debugger* debugger = CcTest::i_isolate()->debugger();
5929
  // Make sure these ports is not used by other tests to allow tests to run in
5930
  // parallel.
5931
  const int kPort1 = 5858 + FlagDependentPortOffset();
5932
  const int kPort2 = 5857 + FlagDependentPortOffset();
5933
  const int kPort3 = 5856 + FlagDependentPortOffset();
5934

    
5935
  // Make a string with the port2 number.
5936
  const int kPortBufferLen = 6;
5937
  char port2_str[kPortBufferLen];
5938
  OS::SNPrintF(i::Vector<char>(port2_str, kPortBufferLen), "%d", kPort2);
5939

    
5940
  bool ok;
5941

    
5942
  // Test starting and stopping the agent without any client connection.
5943
  debugger->StartAgent("test", kPort1);
5944
  debugger->StopAgent();
5945
  // Test starting the agent, connecting a client and shutting down the agent
5946
  // with the client connected.
5947
  ok = debugger->StartAgent("test", kPort2);
5948
  CHECK(ok);
5949
  debugger->WaitForAgent();
5950
  i::Socket* client = new i::Socket;
5951
  ok = client->Connect("localhost", port2_str);
5952
  CHECK(ok);
5953
  // It is important to wait for a message from the agent. Otherwise,
5954
  // we can close the server socket during "accept" syscall, making it failing
5955
  // (at least on Linux), and the test will work incorrectly.
5956
  char buf;
5957
  ok = client->Receive(&buf, 1) == 1;
5958
  CHECK(ok);
5959
  debugger->StopAgent();
5960
  delete client;
5961

    
5962
  // Test starting and stopping the agent with the required port already
5963
  // occoupied.
5964
  i::Socket* server = new i::Socket;
5965
  ok = server->Bind(kPort3);
5966
  CHECK(ok);
5967

    
5968
  debugger->StartAgent("test", kPort3);
5969
  debugger->StopAgent();
5970

    
5971
  delete server;
5972
}
5973

    
5974

    
5975
class DebuggerAgentProtocolServerThread : public i::Thread {
5976
 public:
5977
  explicit DebuggerAgentProtocolServerThread(int port)
5978
      : Thread("DebuggerAgentProtocolServerThread"),
5979
        port_(port),
5980
        server_(NULL),
5981
        client_(NULL),
5982
        listening_(0) {
5983
  }
5984
  ~DebuggerAgentProtocolServerThread() {
5985
    // Close both sockets.
5986
    delete client_;
5987
    delete server_;
5988
  }
5989

    
5990
  void Run();
5991
  void WaitForListening() { listening_.Wait(); }
5992
  char* body() { return *body_; }
5993

    
5994
 private:
5995
  int port_;
5996
  i::SmartArrayPointer<char> body_;
5997
  i::Socket* server_;  // Server socket used for bind/accept.
5998
  i::Socket* client_;  // Single client connection used by the test.
5999
  i::Semaphore listening_;  // Signalled when the server is in listen mode.
6000
};
6001

    
6002

    
6003
void DebuggerAgentProtocolServerThread::Run() {
6004
  bool ok;
6005

    
6006
  // Create the server socket and bind it to the requested port.
6007
  server_ = new i::Socket;
6008
  CHECK(server_ != NULL);
6009
  ok = server_->Bind(port_);
6010
  CHECK(ok);
6011

    
6012
  // Listen for new connections.
6013
  ok = server_->Listen(1);
6014
  CHECK(ok);
6015
  listening_.Signal();
6016

    
6017
  // Accept a connection.
6018
  client_ = server_->Accept();
6019
  CHECK(client_ != NULL);
6020

    
6021
  // Receive a debugger agent protocol message.
6022
  i::DebuggerAgentUtil::ReceiveMessage(client_);
6023
}
6024

    
6025

    
6026
TEST(DebuggerAgentProtocolOverflowHeader) {
6027
  // Make sure this port is not used by other tests to allow tests to run in
6028
  // parallel.
6029
  const int kPort = 5860 + FlagDependentPortOffset();
6030
  static const char* kLocalhost = "localhost";
6031

    
6032
  // Make a string with the port number.
6033
  const int kPortBufferLen = 6;
6034
  char port_str[kPortBufferLen];
6035
  OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
6036

    
6037
  // Create a socket server to receive a debugger agent message.
6038
  DebuggerAgentProtocolServerThread* server =
6039
      new DebuggerAgentProtocolServerThread(kPort);
6040
  server->Start();
6041
  server->WaitForListening();
6042

    
6043
  // Connect.
6044
  i::Socket* client = new i::Socket;
6045
  CHECK(client != NULL);
6046
  bool ok = client->Connect(kLocalhost, port_str);
6047
  CHECK(ok);
6048

    
6049
  // Send headers which overflow the receive buffer.
6050
  static const int kBufferSize = 1000;
6051
  char buffer[kBufferSize];
6052

    
6053
  // Long key and short value: XXXX....XXXX:0\r\n.
6054
  for (int i = 0; i < kBufferSize - 4; i++) {
6055
    buffer[i] = 'X';
6056
  }
6057
  buffer[kBufferSize - 4] = ':';
6058
  buffer[kBufferSize - 3] = '0';
6059
  buffer[kBufferSize - 2] = '\r';
6060
  buffer[kBufferSize - 1] = '\n';
6061
  int result = client->Send(buffer, kBufferSize);
6062
  CHECK_EQ(kBufferSize, result);
6063

    
6064
  // Short key and long value: X:XXXX....XXXX\r\n.
6065
  buffer[0] = 'X';
6066
  buffer[1] = ':';
6067
  for (int i = 2; i < kBufferSize - 2; i++) {
6068
    buffer[i] = 'X';
6069
  }
6070
  buffer[kBufferSize - 2] = '\r';
6071
  buffer[kBufferSize - 1] = '\n';
6072
  result = client->Send(buffer, kBufferSize);
6073
  CHECK_EQ(kBufferSize, result);
6074

    
6075
  // Add empty body to request.
6076
  const char* content_length_zero_header = "Content-Length:0\r\n";
6077
  int length = StrLength(content_length_zero_header);
6078
  result = client->Send(content_length_zero_header, length);
6079
  CHECK_EQ(length, result);
6080
  result = client->Send("\r\n", 2);
6081
  CHECK_EQ(2, result);
6082

    
6083
  // Wait until data is received.
6084
  server->Join();
6085

    
6086
  // Check for empty body.
6087
  CHECK(server->body() == NULL);
6088

    
6089
  // Close the client before the server to avoid TIME_WAIT issues.
6090
  client->Shutdown();
6091
  delete client;
6092
  delete server;
6093
}
6094

    
6095

    
6096
// Test for issue http://code.google.com/p/v8/issues/detail?id=289.
6097
// Make sure that DebugGetLoadedScripts doesn't return scripts
6098
// with disposed external source.
6099
class EmptyExternalStringResource : public v8::String::ExternalStringResource {
6100
 public:
6101
  EmptyExternalStringResource() { empty_[0] = 0; }
6102
  virtual ~EmptyExternalStringResource() {}
6103
  virtual size_t length() const { return empty_.length(); }
6104
  virtual const uint16_t* data() const { return empty_.start(); }
6105
 private:
6106
  ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
6107
};
6108

    
6109

    
6110
TEST(DebugGetLoadedScripts) {
6111
  DebugLocalContext env;
6112
  v8::HandleScope scope(env->GetIsolate());
6113
  env.ExposeDebug();
6114

    
6115
  EmptyExternalStringResource source_ext_str;
6116
  v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
6117
  v8::Handle<v8::Script> evil_script(v8::Script::Compile(source));
6118
  // "use" evil_script to make the compiler happy.
6119
  (void) evil_script;
6120
  Handle<i::ExternalTwoByteString> i_source(
6121
      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
6122
  // This situation can happen if source was an external string disposed
6123
  // by its owner.
6124
  i_source->set_resource(0);
6125

    
6126
  bool allow_natives_syntax = i::FLAG_allow_natives_syntax;
6127
  i::FLAG_allow_natives_syntax = true;
6128
  CompileRun(
6129
      "var scripts = %DebugGetLoadedScripts();"
6130
      "var count = scripts.length;"
6131
      "for (var i = 0; i < count; ++i) {"
6132
      "  scripts[i].line_ends;"
6133
      "}");
6134
  // Must not crash while accessing line_ends.
6135
  i::FLAG_allow_natives_syntax = allow_natives_syntax;
6136

    
6137
  // Some scripts are retrieved - at least the number of native scripts.
6138
  CHECK_GT((*env)->Global()->Get(v8::String::New("count"))->Int32Value(), 8);
6139
}
6140

    
6141

    
6142
// Test script break points set on lines.
6143
TEST(ScriptNameAndData) {
6144
  DebugLocalContext env;
6145
  v8::HandleScope scope(env->GetIsolate());
6146
  env.ExposeDebug();
6147

    
6148
  // Create functions for retrieving script name and data for the function on
6149
  // the top frame when hitting a break point.
6150
  frame_script_name = CompileFunction(&env,
6151
                                      frame_script_name_source,
6152
                                      "frame_script_name");
6153
  frame_script_data = CompileFunction(&env,
6154
                                      frame_script_data_source,
6155
                                      "frame_script_data");
6156
  compiled_script_data = CompileFunction(&env,
6157
                                         compiled_script_data_source,
6158
                                         "compiled_script_data");
6159

    
6160
  v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
6161

    
6162
  // Test function source.
6163
  v8::Local<v8::String> script = v8::String::New(
6164
    "function f() {\n"
6165
    "  debugger;\n"
6166
    "}\n");
6167

    
6168
  v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8::String::New("name"));
6169
  v8::Handle<v8::Script> script1 = v8::Script::Compile(script, &origin1);
6170
  script1->SetData(v8::String::New("data"));
6171
  script1->Run();
6172
  v8::Local<v8::Function> f;
6173
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6174

    
6175
  f->Call(env->Global(), 0, NULL);
6176
  CHECK_EQ(1, break_point_hit_count);
6177
  CHECK_EQ("name", last_script_name_hit);
6178
  CHECK_EQ("data", last_script_data_hit);
6179

    
6180
  // Compile the same script again without setting data. As the compilation
6181
  // cache is disabled when debugging expect the data to be missing.
6182
  v8::Script::Compile(script, &origin1)->Run();
6183
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6184
  f->Call(env->Global(), 0, NULL);
6185
  CHECK_EQ(2, break_point_hit_count);
6186
  CHECK_EQ("name", last_script_name_hit);
6187
  CHECK_EQ("", last_script_data_hit);  // Undefined results in empty string.
6188

    
6189
  v8::Local<v8::String> data_obj_source = v8::String::New(
6190
    "({ a: 'abc',\n"
6191
    "  b: 123,\n"
6192
    "  toString: function() { return this.a + ' ' + this.b; }\n"
6193
    "})\n");
6194
  v8::Local<v8::Value> data_obj = v8::Script::Compile(data_obj_source)->Run();
6195
  v8::ScriptOrigin origin2 = v8::ScriptOrigin(v8::String::New("new name"));
6196
  v8::Handle<v8::Script> script2 = v8::Script::Compile(script, &origin2);
6197
  script2->Run();
6198
  script2->SetData(data_obj->ToString());
6199
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6200
  f->Call(env->Global(), 0, NULL);
6201
  CHECK_EQ(3, break_point_hit_count);
6202
  CHECK_EQ("new name", last_script_name_hit);
6203
  CHECK_EQ("abc 123", last_script_data_hit);
6204

    
6205
  v8::Handle<v8::Script> script3 =
6206
      v8::Script::Compile(script, &origin2, NULL,
6207
                          v8::String::New("in compile"));
6208
  CHECK_EQ("in compile", last_script_data_hit);
6209
  script3->Run();
6210
  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6211
  f->Call(env->Global(), 0, NULL);
6212
  CHECK_EQ(4, break_point_hit_count);
6213
  CHECK_EQ("in compile", last_script_data_hit);
6214
}
6215

    
6216

    
6217
static v8::Handle<v8::Context> expected_context;
6218
static v8::Handle<v8::Value> expected_context_data;
6219

    
6220

    
6221
// Check that the expected context is the one generating the debug event.
6222
static void ContextCheckMessageHandler(const v8::Debug::Message& message) {
6223
  CHECK(message.GetEventContext() == expected_context);
6224
  CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6225
      expected_context_data));
6226
  message_handler_hit_count++;
6227

    
6228
  static char print_buffer[1000];
6229
  v8::String::Value json(message.GetJSON());
6230
  Utf16ToAscii(*json, json.length(), print_buffer);
6231

    
6232
  // Send a continue command for break events.
6233
  if (IsBreakEventMessage(print_buffer)) {
6234
    SendContinueCommand();
6235
  }
6236
}
6237

    
6238

    
6239
// Test which creates two contexts and sets different embedder data on each.
6240
// Checks that this data is set correctly and that when the debug message
6241
// handler is called the expected context is the one active.
6242
TEST(ContextData) {
6243
  v8::Isolate* isolate = CcTest::isolate();
6244
  v8::HandleScope scope(isolate);
6245

    
6246
  // Create two contexts.
6247
  v8::Handle<v8::Context> context_1;
6248
  v8::Handle<v8::Context> context_2;
6249
  v8::Handle<v8::ObjectTemplate> global_template =
6250
      v8::Handle<v8::ObjectTemplate>();
6251
  v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>();
6252
  context_1 = v8::Context::New(isolate, NULL, global_template, global_object);
6253
  context_2 = v8::Context::New(isolate, NULL, global_template, global_object);
6254

    
6255
  v8::Debug::SetMessageHandler2(ContextCheckMessageHandler);
6256

    
6257
  // Default data value is undefined.
6258
  CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6259
  CHECK(context_2->GetEmbedderData(0)->IsUndefined());
6260

    
6261
  // Set and check different data values.
6262
  v8::Handle<v8::String> data_1 = v8::String::New("1");
6263
  v8::Handle<v8::String> data_2 = v8::String::New("2");
6264
  context_1->SetEmbedderData(0, data_1);
6265
  context_2->SetEmbedderData(0, data_2);
6266
  CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6267
  CHECK(context_2->GetEmbedderData(0)->StrictEquals(data_2));
6268

    
6269
  // Simple test function which causes a break.
6270
  const char* source = "function f() { debugger; }";
6271

    
6272
  // Enter and run function in the first context.
6273
  {
6274
    v8::Context::Scope context_scope(context_1);
6275
    expected_context = context_1;
6276
    expected_context_data = data_1;
6277
    v8::Local<v8::Function> f = CompileFunction(source, "f");
6278
    f->Call(context_1->Global(), 0, NULL);
6279
  }
6280

    
6281

    
6282
  // Enter and run function in the second context.
6283
  {
6284
    v8::Context::Scope context_scope(context_2);
6285
    expected_context = context_2;
6286
    expected_context_data = data_2;
6287
    v8::Local<v8::Function> f = CompileFunction(source, "f");
6288
    f->Call(context_2->Global(), 0, NULL);
6289
  }
6290

    
6291
  // Two times compile event and two times break event.
6292
  CHECK_GT(message_handler_hit_count, 4);
6293

    
6294
  v8::Debug::SetMessageHandler2(NULL);
6295
  CheckDebuggerUnloaded();
6296
}
6297

    
6298

    
6299
// Debug message handler which issues a debug break when it hits a break event.
6300
static int message_handler_break_hit_count = 0;
6301
static void DebugBreakMessageHandler(const v8::Debug::Message& message) {
6302
  // Schedule a debug break for break events.
6303
  if (message.IsEvent() && message.GetEvent() == v8::Break) {
6304
    message_handler_break_hit_count++;
6305
    if (message_handler_break_hit_count == 1) {
6306
      v8::Debug::DebugBreak(message.GetIsolate());
6307
    }
6308
  }
6309

    
6310
  // Issue a continue command if this event will not cause the VM to start
6311
  // running.
6312
  if (!message.WillStartRunning()) {
6313
    SendContinueCommand();
6314
  }
6315
}
6316

    
6317

    
6318
// Test that a debug break can be scheduled while in a message handler.
6319
TEST(DebugBreakInMessageHandler) {
6320
  DebugLocalContext env;
6321
  v8::HandleScope scope(env->GetIsolate());
6322

    
6323
  v8::Debug::SetMessageHandler2(DebugBreakMessageHandler);
6324

    
6325
  // Test functions.
6326
  const char* script = "function f() { debugger; g(); } function g() { }";
6327
  CompileRun(script);
6328
  v8::Local<v8::Function> f =
6329
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6330
  v8::Local<v8::Function> g =
6331
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
6332

    
6333
  // Call f then g. The debugger statement in f will casue a break which will
6334
  // cause another break.
6335
  f->Call(env->Global(), 0, NULL);
6336
  CHECK_EQ(2, message_handler_break_hit_count);
6337
  // Calling g will not cause any additional breaks.
6338
  g->Call(env->Global(), 0, NULL);
6339
  CHECK_EQ(2, message_handler_break_hit_count);
6340
}
6341

    
6342

    
6343
#ifndef V8_INTERPRETED_REGEXP
6344
// Debug event handler which gets the function on the top frame and schedules a
6345
// break a number of times.
6346
static void DebugEventDebugBreak(
6347
    const v8::Debug::EventDetails& event_details) {
6348
  v8::DebugEvent event = event_details.GetEvent();
6349
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
6350

    
6351
  if (event == v8::Break) {
6352
    break_point_hit_count++;
6353

    
6354
    // Get the name of the top frame function.
6355
    if (!frame_function_name.IsEmpty()) {
6356
      // Get the name of the function.
6357
      const int argc = 2;
6358
      v8::Handle<v8::Value> argv[argc] = { exec_state, v8::Integer::New(0) };
6359
      v8::Handle<v8::Value> result = frame_function_name->Call(exec_state,
6360
                                                               argc, argv);
6361
      if (result->IsUndefined()) {
6362
        last_function_hit[0] = '\0';
6363
      } else {
6364
        CHECK(result->IsString());
6365
        v8::Handle<v8::String> function_name(result->ToString());
6366
        function_name->WriteUtf8(last_function_hit);
6367
      }
6368
    }
6369

    
6370
    // Keep forcing breaks.
6371
    if (break_point_hit_count < 20) {
6372
      v8::Debug::DebugBreak(CcTest::isolate());
6373
    }
6374
  }
6375
}
6376

    
6377

    
6378
TEST(RegExpDebugBreak) {
6379
  // This test only applies to native regexps.
6380
  DebugLocalContext env;
6381
  v8::HandleScope scope(env->GetIsolate());
6382

    
6383
  // Create a function for checking the function when hitting a break point.
6384
  frame_function_name = CompileFunction(&env,
6385
                                        frame_function_name_source,
6386
                                        "frame_function_name");
6387

    
6388
  // Test RegExp which matches white spaces and comments at the begining of a
6389
  // source line.
6390
  const char* script =
6391
    "var sourceLineBeginningSkip = /^(?:[ \\v\\h]*(?:\\/\\*.*?\\*\\/)*)*/;\n"
6392
    "function f(s) { return s.match(sourceLineBeginningSkip)[0].length; }";
6393

    
6394
  v8::Local<v8::Function> f = CompileFunction(script, "f");
6395
  const int argc = 1;
6396
  v8::Handle<v8::Value> argv[argc] = { v8::String::New("  /* xxx */ a=0;") };
6397
  v8::Local<v8::Value> result = f->Call(env->Global(), argc, argv);
6398
  CHECK_EQ(12, result->Int32Value());
6399

    
6400
  v8::Debug::SetDebugEventListener2(DebugEventDebugBreak);
6401
  v8::Debug::DebugBreak(env->GetIsolate());
6402
  result = f->Call(env->Global(), argc, argv);
6403

    
6404
  // Check that there was only one break event. Matching RegExp should not
6405
  // cause Break events.
6406
  CHECK_EQ(1, break_point_hit_count);
6407
  CHECK_EQ("f", last_function_hit);
6408
}
6409
#endif  // V8_INTERPRETED_REGEXP
6410

    
6411

    
6412
// Common part of EvalContextData and NestedBreakEventContextData tests.
6413
static void ExecuteScriptForContextCheck(
6414
    v8::Debug::MessageHandler2 message_handler) {
6415
  // Create a context.
6416
  v8::Handle<v8::Context> context_1;
6417
  v8::Handle<v8::ObjectTemplate> global_template =
6418
      v8::Handle<v8::ObjectTemplate>();
6419
  context_1 =
6420
      v8::Context::New(CcTest::isolate(), NULL, global_template);
6421

    
6422
  v8::Debug::SetMessageHandler2(message_handler);
6423

    
6424
  // Default data value is undefined.
6425
  CHECK(context_1->GetEmbedderData(0)->IsUndefined());
6426

    
6427
  // Set and check a data value.
6428
  v8::Handle<v8::String> data_1 = v8::String::New("1");
6429
  context_1->SetEmbedderData(0, data_1);
6430
  CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
6431

    
6432
  // Simple test function with eval that causes a break.
6433
  const char* source = "function f() { eval('debugger;'); }";
6434

    
6435
  // Enter and run function in the context.
6436
  {
6437
    v8::Context::Scope context_scope(context_1);
6438
    expected_context = context_1;
6439
    expected_context_data = data_1;
6440
    v8::Local<v8::Function> f = CompileFunction(source, "f");
6441
    f->Call(context_1->Global(), 0, NULL);
6442
  }
6443

    
6444
  v8::Debug::SetMessageHandler2(NULL);
6445
}
6446

    
6447

    
6448
// Test which creates a context and sets embedder data on it. Checks that this
6449
// data is set correctly and that when the debug message handler is called for
6450
// break event in an eval statement the expected context is the one returned by
6451
// Message.GetEventContext.
6452
TEST(EvalContextData) {
6453
  v8::HandleScope scope(CcTest::isolate());
6454

    
6455
  ExecuteScriptForContextCheck(ContextCheckMessageHandler);
6456

    
6457
  // One time compile event and one time break event.
6458
  CHECK_GT(message_handler_hit_count, 2);
6459
  CheckDebuggerUnloaded();
6460
}
6461

    
6462

    
6463
static bool sent_eval = false;
6464
static int break_count = 0;
6465
static int continue_command_send_count = 0;
6466
// Check that the expected context is the one generating the debug event
6467
// including the case of nested break event.
6468
static void DebugEvalContextCheckMessageHandler(
6469
    const v8::Debug::Message& message) {
6470
  CHECK(message.GetEventContext() == expected_context);
6471
  CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals(
6472
      expected_context_data));
6473
  message_handler_hit_count++;
6474

    
6475
  static char print_buffer[1000];
6476
  v8::String::Value json(message.GetJSON());
6477
  Utf16ToAscii(*json, json.length(), print_buffer);
6478

    
6479
  v8::Isolate* isolate = message.GetIsolate();
6480
  if (IsBreakEventMessage(print_buffer)) {
6481
    break_count++;
6482
    if (!sent_eval) {
6483
      sent_eval = true;
6484

    
6485
      const int kBufferSize = 1000;
6486
      uint16_t buffer[kBufferSize];
6487
      const char* eval_command =
6488
          "{\"seq\":0,"
6489
          "\"type\":\"request\","
6490
          "\"command\":\"evaluate\","
6491
          "\"arguments\":{\"expression\":\"debugger;\","
6492
          "\"global\":true,\"disable_break\":false}}";
6493

    
6494
      // Send evaluate command.
6495
      v8::Debug::SendCommand(
6496
          isolate, buffer, AsciiToUtf16(eval_command, buffer));
6497
      return;
6498
    } else {
6499
      // It's a break event caused by the evaluation request above.
6500
      SendContinueCommand();
6501
      continue_command_send_count++;
6502
    }
6503
  } else if (IsEvaluateResponseMessage(print_buffer) &&
6504
      continue_command_send_count < 2) {
6505
    // Response to the evaluation request. We're still on the breakpoint so
6506
    // send continue.
6507
    SendContinueCommand();
6508
    continue_command_send_count++;
6509
  }
6510
}
6511

    
6512

    
6513
// Tests that context returned for break event is correct when the event occurs
6514
// in 'evaluate' debugger request.
6515
TEST(NestedBreakEventContextData) {
6516
  v8::HandleScope scope(CcTest::isolate());
6517
  break_count = 0;
6518
  message_handler_hit_count = 0;
6519

    
6520
  ExecuteScriptForContextCheck(DebugEvalContextCheckMessageHandler);
6521

    
6522
  // One time compile event and two times break event.
6523
  CHECK_GT(message_handler_hit_count, 3);
6524

    
6525
  // One break from the source and another from the evaluate request.
6526
  CHECK_EQ(break_count, 2);
6527
  CheckDebuggerUnloaded();
6528
}
6529

    
6530

    
6531
// Debug event listener which counts the script collected events.
6532
int script_collected_count = 0;
6533
static void DebugEventScriptCollectedEvent(
6534
    const v8::Debug::EventDetails& event_details) {
6535
  v8::DebugEvent event = event_details.GetEvent();
6536
  // Count the number of breaks.
6537
  if (event == v8::ScriptCollected) {
6538
    script_collected_count++;
6539
  }
6540
}
6541

    
6542

    
6543
// Test that scripts collected are reported through the debug event listener.
6544
TEST(ScriptCollectedEvent) {
6545
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
6546
  break_point_hit_count = 0;
6547
  script_collected_count = 0;
6548
  DebugLocalContext env;
6549
  v8::HandleScope scope(env->GetIsolate());
6550

    
6551
  // Request the loaded scripts to initialize the debugger script cache.
6552
  debug->GetLoadedScripts();
6553

    
6554
  // Do garbage collection to ensure that only the script in this test will be
6555
  // collected afterwards.
6556
  CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
6557

    
6558
  script_collected_count = 0;
6559
  v8::Debug::SetDebugEventListener2(DebugEventScriptCollectedEvent);
6560
  {
6561
    v8::Script::Compile(v8::String::New("eval('a=1')"))->Run();
6562
    v8::Script::Compile(v8::String::New("eval('a=2')"))->Run();
6563
  }
6564

    
6565
  // Do garbage collection to collect the script above which is no longer
6566
  // referenced.
6567
  CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
6568

    
6569
  CHECK_EQ(2, script_collected_count);
6570

    
6571
  v8::Debug::SetDebugEventListener2(NULL);
6572
  CheckDebuggerUnloaded();
6573
}
6574

    
6575

    
6576
// Debug event listener which counts the script collected events.
6577
int script_collected_message_count = 0;
6578
static void ScriptCollectedMessageHandler(const v8::Debug::Message& message) {
6579
  // Count the number of scripts collected.
6580
  if (message.IsEvent() && message.GetEvent() == v8::ScriptCollected) {
6581
    script_collected_message_count++;
6582
    v8::Handle<v8::Context> context = message.GetEventContext();
6583
    CHECK(context.IsEmpty());
6584
  }
6585
}
6586

    
6587

    
6588
// Test that GetEventContext doesn't fail and return empty handle for
6589
// ScriptCollected events.
6590
TEST(ScriptCollectedEventContext) {
6591
  i::FLAG_stress_compaction = false;
6592
  v8::Isolate* isolate = CcTest::isolate();
6593
  v8::internal::Debug* debug =
6594
      reinterpret_cast<v8::internal::Isolate*>(isolate)->debug();
6595
  script_collected_message_count = 0;
6596
  v8::HandleScope scope(isolate);
6597

    
6598
  v8::Persistent<v8::Context> context;
6599
  {
6600
    v8::HandleScope scope(isolate);
6601
    context.Reset(isolate, v8::Context::New(isolate));
6602
  }
6603

    
6604
  // Enter context.  We can't have a handle to the context in the outer
6605
  // scope, so we have to do it the hard way.
6606
  {
6607
    v8::HandleScope scope(isolate);
6608
    v8::Local<v8::Context> local_context =
6609
        v8::Local<v8::Context>::New(isolate, context);
6610
    local_context->Enter();
6611
  }
6612

    
6613
  // Request the loaded scripts to initialize the debugger script cache.
6614
  debug->GetLoadedScripts();
6615

    
6616
  // Do garbage collection to ensure that only the script in this test will be
6617
  // collected afterwards.
6618
  CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
6619

    
6620
  v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler);
6621
  v8::Script::Compile(v8::String::New("eval('a=1')"))->Run();
6622
  v8::Script::Compile(v8::String::New("eval('a=2')"))->Run();
6623

    
6624
  // Leave context
6625
  {
6626
    v8::HandleScope scope(isolate);
6627
    v8::Local<v8::Context> local_context =
6628
        v8::Local<v8::Context>::New(isolate, context);
6629
    local_context->Exit();
6630
  }
6631
  context.Dispose();
6632

    
6633
  // Do garbage collection to collect the script above which is no longer
6634
  // referenced.
6635
  CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
6636

    
6637
  CHECK_EQ(2, script_collected_message_count);
6638

    
6639
  v8::Debug::SetMessageHandler2(NULL);
6640
}
6641

    
6642

    
6643
// Debug event listener which counts the after compile events.
6644
int after_compile_message_count = 0;
6645
static void AfterCompileMessageHandler(const v8::Debug::Message& message) {
6646
  // Count the number of scripts collected.
6647
  if (message.IsEvent()) {
6648
    if (message.GetEvent() == v8::AfterCompile) {
6649
      after_compile_message_count++;
6650
    } else if (message.GetEvent() == v8::Break) {
6651
      SendContinueCommand();
6652
    }
6653
  }
6654
}
6655

    
6656

    
6657
// Tests that after compile event is sent as many times as there are scripts
6658
// compiled.
6659
TEST(AfterCompileMessageWhenMessageHandlerIsReset) {
6660
  DebugLocalContext env;
6661
  v8::HandleScope scope(env->GetIsolate());
6662
  after_compile_message_count = 0;
6663
  const char* script = "var a=1";
6664

    
6665
  v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
6666
  v8::Script::Compile(v8::String::New(script))->Run();
6667
  v8::Debug::SetMessageHandler2(NULL);
6668

    
6669
  v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
6670
  v8::Debug::DebugBreak(env->GetIsolate());
6671
  v8::Script::Compile(v8::String::New(script))->Run();
6672

    
6673
  // Setting listener to NULL should cause debugger unload.
6674
  v8::Debug::SetMessageHandler2(NULL);
6675
  CheckDebuggerUnloaded();
6676

    
6677
  // Compilation cache should be disabled when debugger is active.
6678
  CHECK_EQ(2, after_compile_message_count);
6679
}
6680

    
6681

    
6682
// Tests that break event is sent when message handler is reset.
6683
TEST(BreakMessageWhenMessageHandlerIsReset) {
6684
  DebugLocalContext env;
6685
  v8::HandleScope scope(env->GetIsolate());
6686
  after_compile_message_count = 0;
6687
  const char* script = "function f() {};";
6688

    
6689
  v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
6690
  v8::Script::Compile(v8::String::New(script))->Run();
6691
  v8::Debug::SetMessageHandler2(NULL);
6692

    
6693
  v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
6694
  v8::Debug::DebugBreak(env->GetIsolate());
6695
  v8::Local<v8::Function> f =
6696
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6697
  f->Call(env->Global(), 0, NULL);
6698

    
6699
  // Setting message handler to NULL should cause debugger unload.
6700
  v8::Debug::SetMessageHandler2(NULL);
6701
  CheckDebuggerUnloaded();
6702

    
6703
  // Compilation cache should be disabled when debugger is active.
6704
  CHECK_EQ(1, after_compile_message_count);
6705
}
6706

    
6707

    
6708
static int exception_event_count = 0;
6709
static void ExceptionMessageHandler(const v8::Debug::Message& message) {
6710
  if (message.IsEvent() && message.GetEvent() == v8::Exception) {
6711
    exception_event_count++;
6712
    SendContinueCommand();
6713
  }
6714
}
6715

    
6716

    
6717
// Tests that exception event is sent when message handler is reset.
6718
TEST(ExceptionMessageWhenMessageHandlerIsReset) {
6719
  DebugLocalContext env;
6720
  v8::HandleScope scope(env->GetIsolate());
6721

    
6722
  // For this test, we want to break on uncaught exceptions:
6723
  ChangeBreakOnException(false, true);
6724

    
6725
  exception_event_count = 0;
6726
  const char* script = "function f() {throw new Error()};";
6727

    
6728
  v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
6729
  v8::Script::Compile(v8::String::New(script))->Run();
6730
  v8::Debug::SetMessageHandler2(NULL);
6731

    
6732
  v8::Debug::SetMessageHandler2(ExceptionMessageHandler);
6733
  v8::Local<v8::Function> f =
6734
      v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
6735
  f->Call(env->Global(), 0, NULL);
6736

    
6737
  // Setting message handler to NULL should cause debugger unload.
6738
  v8::Debug::SetMessageHandler2(NULL);
6739
  CheckDebuggerUnloaded();
6740

    
6741
  CHECK_EQ(1, exception_event_count);
6742
}
6743

    
6744

    
6745
// Tests after compile event is sent when there are some provisional
6746
// breakpoints out of the scripts lines range.
6747
TEST(ProvisionalBreakpointOnLineOutOfRange) {
6748
  DebugLocalContext env;
6749
  v8::HandleScope scope(env->GetIsolate());
6750
  env.ExposeDebug();
6751
  const char* script = "function f() {};";
6752
  const char* resource_name = "test_resource";
6753

    
6754
  // Set a couple of provisional breakpoint on lines out of the script lines
6755
  // range.
6756
  int sbp1 = SetScriptBreakPointByNameFromJS(resource_name, 3,
6757
                                             -1 /* no column */);
6758
  int sbp2 = SetScriptBreakPointByNameFromJS(resource_name, 5, 5);
6759

    
6760
  after_compile_message_count = 0;
6761
  v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
6762

    
6763
  v8::ScriptOrigin origin(
6764
      v8::String::New(resource_name),
6765
      v8::Integer::New(10),
6766
      v8::Integer::New(1));
6767
  // Compile a script whose first line number is greater than the breakpoints'
6768
  // lines.
6769
  v8::Script::Compile(v8::String::New(script), &origin)->Run();
6770

    
6771
  // If the script is compiled successfully there is exactly one after compile
6772
  // event. In case of an exception in debugger code after compile event is not
6773
  // sent.
6774
  CHECK_EQ(1, after_compile_message_count);
6775

    
6776
  ClearBreakPointFromJS(sbp1);
6777
  ClearBreakPointFromJS(sbp2);
6778
  v8::Debug::SetMessageHandler2(NULL);
6779
}
6780

    
6781

    
6782
static void BreakMessageHandler(const v8::Debug::Message& message) {
6783
  i::Isolate* isolate = CcTest::i_isolate();
6784
  if (message.IsEvent() && message.GetEvent() == v8::Break) {
6785
    // Count the number of breaks.
6786
    break_point_hit_count++;
6787

    
6788
    i::HandleScope scope(isolate);
6789
    message.GetJSON();
6790

    
6791
    SendContinueCommand();
6792
  } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
6793
    i::HandleScope scope(isolate);
6794

    
6795
    bool is_debug_break = isolate->stack_guard()->IsDebugBreak();
6796
    // Force DebugBreak flag while serializer is working.
6797
    isolate->stack_guard()->DebugBreak();
6798

    
6799
    // Force serialization to trigger some internal JS execution.
6800
    message.GetJSON();
6801

    
6802
    // Restore previous state.
6803
    if (is_debug_break) {
6804
      isolate->stack_guard()->DebugBreak();
6805
    } else {
6806
      isolate->stack_guard()->Continue(i::DEBUGBREAK);
6807
    }
6808
  }
6809
}
6810

    
6811

    
6812
// Test that if DebugBreak is forced it is ignored when code from
6813
// debug-delay.js is executed.
6814
TEST(NoDebugBreakInAfterCompileMessageHandler) {
6815
  DebugLocalContext env;
6816
  v8::HandleScope scope(env->GetIsolate());
6817

    
6818
  // Register a debug event listener which sets the break flag and counts.
6819
  v8::Debug::SetMessageHandler2(BreakMessageHandler);
6820

    
6821
  // Set the debug break flag.
6822
  v8::Debug::DebugBreak(env->GetIsolate());
6823

    
6824
  // Create a function for testing stepping.
6825
  const char* src = "function f() { eval('var x = 10;'); } ";
6826
  v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
6827

    
6828
  // There should be only one break event.
6829
  CHECK_EQ(1, break_point_hit_count);
6830

    
6831
  // Set the debug break flag again.
6832
  v8::Debug::DebugBreak(env->GetIsolate());
6833
  f->Call(env->Global(), 0, NULL);
6834
  // There should be one more break event when the script is evaluated in 'f'.
6835
  CHECK_EQ(2, break_point_hit_count);
6836

    
6837
  // Get rid of the debug message handler.
6838
  v8::Debug::SetMessageHandler2(NULL);
6839
  CheckDebuggerUnloaded();
6840
}
6841

    
6842

    
6843
static int counting_message_handler_counter;
6844

    
6845
static void CountingMessageHandler(const v8::Debug::Message& message) {
6846
  counting_message_handler_counter++;
6847
}
6848

    
6849

    
6850
// Test that debug messages get processed when ProcessDebugMessages is called.
6851
TEST(ProcessDebugMessages) {
6852
  DebugLocalContext env;
6853
  v8::Isolate* isolate = env->GetIsolate();
6854
  v8::HandleScope scope(isolate);
6855

    
6856
  counting_message_handler_counter = 0;
6857

    
6858
  v8::Debug::SetMessageHandler2(CountingMessageHandler);
6859

    
6860
  const int kBufferSize = 1000;
6861
  uint16_t buffer[kBufferSize];
6862
  const char* scripts_command =
6863
    "{\"seq\":0,"
6864
     "\"type\":\"request\","
6865
     "\"command\":\"scripts\"}";
6866

    
6867
  // Send scripts command.
6868
  v8::Debug::SendCommand(
6869
      isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6870

    
6871
  CHECK_EQ(0, counting_message_handler_counter);
6872
  v8::Debug::ProcessDebugMessages();
6873
  // At least one message should come
6874
  CHECK_GE(counting_message_handler_counter, 1);
6875

    
6876
  counting_message_handler_counter = 0;
6877

    
6878
  v8::Debug::SendCommand(
6879
      isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6880
  v8::Debug::SendCommand(
6881
      isolate, buffer, AsciiToUtf16(scripts_command, buffer));
6882
  CHECK_EQ(0, counting_message_handler_counter);
6883
  v8::Debug::ProcessDebugMessages();
6884
  // At least two messages should come
6885
  CHECK_GE(counting_message_handler_counter, 2);
6886

    
6887
  // Get rid of the debug message handler.
6888
  v8::Debug::SetMessageHandler2(NULL);
6889
  CheckDebuggerUnloaded();
6890
}
6891

    
6892

    
6893
struct BacktraceData {
6894
  static int frame_counter;
6895
  static void MessageHandler(const v8::Debug::Message& message) {
6896
    char print_buffer[1000];
6897
    v8::String::Value json(message.GetJSON());
6898
    Utf16ToAscii(*json, json.length(), print_buffer, 1000);
6899

    
6900
    if (strstr(print_buffer, "backtrace") == NULL) {
6901
      return;
6902
    }
6903
    frame_counter = GetTotalFramesInt(print_buffer);
6904
  }
6905
};
6906

    
6907
int BacktraceData::frame_counter;
6908

    
6909

    
6910
// Test that debug messages get processed when ProcessDebugMessages is called.
6911
TEST(Backtrace) {
6912
  DebugLocalContext env;
6913
  v8::Isolate* isolate = env->GetIsolate();
6914
  v8::HandleScope scope(isolate);
6915

    
6916
  v8::Debug::SetMessageHandler2(BacktraceData::MessageHandler);
6917

    
6918
  const int kBufferSize = 1000;
6919
  uint16_t buffer[kBufferSize];
6920
  const char* scripts_command =
6921
    "{\"seq\":0,"
6922
     "\"type\":\"request\","
6923
     "\"command\":\"backtrace\"}";
6924

    
6925
  // Check backtrace from ProcessDebugMessages.
6926
  BacktraceData::frame_counter = -10;
6927
  v8::Debug::SendCommand(
6928
      isolate,
6929
      buffer,
6930
      AsciiToUtf16(scripts_command, buffer),
6931
      NULL);
6932
  v8::Debug::ProcessDebugMessages();
6933
  CHECK_EQ(BacktraceData::frame_counter, 0);
6934

    
6935
  v8::Handle<v8::String> void0 = v8::String::New("void(0)");
6936
  v8::Handle<v8::Script> script = v8::Script::Compile(void0, void0);
6937

    
6938
  // Check backtrace from "void(0)" script.
6939
  BacktraceData::frame_counter = -10;
6940
  v8::Debug::SendCommand(
6941
      isolate,
6942
      buffer,
6943
      AsciiToUtf16(scripts_command, buffer),
6944
      NULL);
6945
  script->Run();
6946
  CHECK_EQ(BacktraceData::frame_counter, 1);
6947

    
6948
  // Get rid of the debug message handler.
6949
  v8::Debug::SetMessageHandler2(NULL);
6950
  CheckDebuggerUnloaded();
6951
}
6952

    
6953

    
6954
TEST(GetMirror) {
6955
  DebugLocalContext env;
6956
  v8::HandleScope scope(env->GetIsolate());
6957
  v8::Handle<v8::Value> obj = v8::Debug::GetMirror(v8::String::New("hodja"));
6958
  v8::Handle<v8::Function> run_test = v8::Handle<v8::Function>::Cast(
6959
      v8::Script::New(
6960
          v8::String::New(
6961
              "function runTest(mirror) {"
6962
              "  return mirror.isString() && (mirror.length() == 5);"
6963
              "}"
6964
              ""
6965
              "runTest;"))->Run());
6966
  v8::Handle<v8::Value> result = run_test->Call(env->Global(), 1, &obj);
6967
  CHECK(result->IsTrue());
6968
}
6969

    
6970

    
6971
// Test that the debug break flag works with function.apply.
6972
TEST(DebugBreakFunctionApply) {
6973
  DebugLocalContext env;
6974
  v8::HandleScope scope(env->GetIsolate());
6975

    
6976
  // Create a function for testing breaking in apply.
6977
  v8::Local<v8::Function> foo = CompileFunction(
6978
      &env,
6979
      "function baz(x) { }"
6980
      "function bar(x) { baz(); }"
6981
      "function foo(){ bar.apply(this, [1]); }",
6982
      "foo");
6983

    
6984
  // Register a debug event listener which steps and counts.
6985
  v8::Debug::SetDebugEventListener2(DebugEventBreakMax);
6986

    
6987
  // Set the debug break flag before calling the code using function.apply.
6988
  v8::Debug::DebugBreak(env->GetIsolate());
6989

    
6990
  // Limit the number of debug breaks. This is a regression test for issue 493
6991
  // where this test would enter an infinite loop.
6992
  break_point_hit_count = 0;
6993
  max_break_point_hit_count = 10000;  // 10000 => infinite loop.
6994
  foo->Call(env->Global(), 0, NULL);
6995

    
6996
  // When keeping the debug break several break will happen.
6997
  CHECK_GT(break_point_hit_count, 1);
6998

    
6999
  v8::Debug::SetDebugEventListener2(NULL);
7000
  CheckDebuggerUnloaded();
7001
}
7002

    
7003

    
7004
v8::Handle<v8::Context> debugee_context;
7005
v8::Handle<v8::Context> debugger_context;
7006

    
7007

    
7008
// Property getter that checks that current and calling contexts
7009
// are both the debugee contexts.
7010
static void NamedGetterWithCallingContextCheck(
7011
    v8::Local<v8::String> name,
7012
    const v8::PropertyCallbackInfo<v8::Value>& info) {
7013
  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(name), "a"));
7014
  v8::Handle<v8::Context> current = info.GetIsolate()->GetCurrentContext();
7015
  CHECK(current == debugee_context);
7016
  CHECK(current != debugger_context);
7017
  v8::Handle<v8::Context> calling = info.GetIsolate()->GetCallingContext();
7018
  CHECK(calling == debugee_context);
7019
  CHECK(calling != debugger_context);
7020
  info.GetReturnValue().Set(1);
7021
}
7022

    
7023

    
7024
// Debug event listener that checks if the first argument of a function is
7025
// an object with property 'a' == 1. If the property has custom accessor
7026
// this handler will eventually invoke it.
7027
static void DebugEventGetAtgumentPropertyValue(
7028
    const v8::Debug::EventDetails& event_details) {
7029
  v8::DebugEvent event = event_details.GetEvent();
7030
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7031
  if (event == v8::Break) {
7032
    break_point_hit_count++;
7033
    CHECK(debugger_context == CcTest::isolate()->GetCurrentContext());
7034
    v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(CompileRun(
7035
        "(function(exec_state) {\n"
7036
        "    return (exec_state.frame(0).argumentValue(0).property('a').\n"
7037
        "            value().value() == 1);\n"
7038
        "})"));
7039
    const int argc = 1;
7040
    v8::Handle<v8::Value> argv[argc] = { exec_state };
7041
    v8::Handle<v8::Value> result = func->Call(exec_state, argc, argv);
7042
    CHECK(result->IsTrue());
7043
  }
7044
}
7045

    
7046

    
7047
TEST(CallingContextIsNotDebugContext) {
7048
  v8::internal::Debug* debug = CcTest::i_isolate()->debug();
7049
  // Create and enter a debugee context.
7050
  DebugLocalContext env;
7051
  v8::HandleScope scope(env->GetIsolate());
7052
  env.ExposeDebug();
7053

    
7054
  // Save handles to the debugger and debugee contexts to be used in
7055
  // NamedGetterWithCallingContextCheck.
7056
  debugee_context = env.context();
7057
  debugger_context = v8::Utils::ToLocal(debug->debug_context());
7058

    
7059
  // Create object with 'a' property accessor.
7060
  v8::Handle<v8::ObjectTemplate> named = v8::ObjectTemplate::New();
7061
  named->SetAccessor(v8::String::New("a"),
7062
                     NamedGetterWithCallingContextCheck);
7063
  env->Global()->Set(v8::String::New("obj"),
7064
                     named->NewInstance());
7065

    
7066
  // Register the debug event listener
7067
  v8::Debug::SetDebugEventListener2(DebugEventGetAtgumentPropertyValue);
7068

    
7069
  // Create a function that invokes debugger.
7070
  v8::Local<v8::Function> foo = CompileFunction(
7071
      &env,
7072
      "function bar(x) { debugger; }"
7073
      "function foo(){ bar(obj); }",
7074
      "foo");
7075

    
7076
  break_point_hit_count = 0;
7077
  foo->Call(env->Global(), 0, NULL);
7078
  CHECK_EQ(1, break_point_hit_count);
7079

    
7080
  v8::Debug::SetDebugEventListener2(NULL);
7081
  debugee_context = v8::Handle<v8::Context>();
7082
  debugger_context = v8::Handle<v8::Context>();
7083
  CheckDebuggerUnloaded();
7084
}
7085

    
7086

    
7087
TEST(DebugContextIsPreservedBetweenAccesses) {
7088
  v8::HandleScope scope(CcTest::isolate());
7089
  v8::Local<v8::Context> context1 = v8::Debug::GetDebugContext();
7090
  v8::Local<v8::Context> context2 = v8::Debug::GetDebugContext();
7091
  CHECK_EQ(*context1, *context2);
7092
}
7093

    
7094

    
7095
static v8::Handle<v8::Value> expected_callback_data;
7096
static void DebugEventContextChecker(const v8::Debug::EventDetails& details) {
7097
  CHECK(details.GetEventContext() == expected_context);
7098
  CHECK_EQ(expected_callback_data, details.GetCallbackData());
7099
}
7100

    
7101

    
7102
// Check that event details contain context where debug event occured.
7103
TEST(DebugEventContext) {
7104
  v8::Isolate* isolate = CcTest::isolate();
7105
  v8::HandleScope scope(isolate);
7106
  expected_callback_data = v8::Int32::New(2010);
7107
  expected_context = v8::Context::New(isolate);
7108
  v8::Debug::SetDebugEventListener2(DebugEventContextChecker,
7109
                                    expected_callback_data);
7110
  v8::Context::Scope context_scope(expected_context);
7111
  v8::Script::Compile(v8::String::New("(function(){debugger;})();"))->Run();
7112
  expected_context.Clear();
7113
  v8::Debug::SetDebugEventListener2(NULL);
7114
  expected_context_data = v8::Handle<v8::Value>();
7115
  CheckDebuggerUnloaded();
7116
}
7117

    
7118

    
7119
static void* expected_break_data;
7120
static bool was_debug_break_called;
7121
static bool was_debug_event_called;
7122
static void DebugEventBreakDataChecker(const v8::Debug::EventDetails& details) {
7123
  if (details.GetEvent() == v8::BreakForCommand) {
7124
    CHECK_EQ(expected_break_data, details.GetClientData());
7125
    was_debug_event_called = true;
7126
  } else if (details.GetEvent() == v8::Break) {
7127
    was_debug_break_called = true;
7128
  }
7129
}
7130

    
7131

    
7132
// Check that event details contain context where debug event occured.
7133
TEST(DebugEventBreakData) {
7134
  DebugLocalContext env;
7135
  v8::Isolate* isolate = env->GetIsolate();
7136
  v8::HandleScope scope(isolate);
7137
  v8::Debug::SetDebugEventListener2(DebugEventBreakDataChecker);
7138

    
7139
  TestClientData::constructor_call_counter = 0;
7140
  TestClientData::destructor_call_counter = 0;
7141

    
7142
  expected_break_data = NULL;
7143
  was_debug_event_called = false;
7144
  was_debug_break_called = false;
7145
  v8::Debug::DebugBreakForCommand(NULL, isolate);
7146
  v8::Script::Compile(v8::String::New("(function(x){return x;})(1);"))->Run();
7147
  CHECK(was_debug_event_called);
7148
  CHECK(!was_debug_break_called);
7149

    
7150
  TestClientData* data1 = new TestClientData();
7151
  expected_break_data = data1;
7152
  was_debug_event_called = false;
7153
  was_debug_break_called = false;
7154
  v8::Debug::DebugBreakForCommand(data1, isolate);
7155
  v8::Script::Compile(v8::String::New("(function(x){return x+1;})(1);"))->Run();
7156
  CHECK(was_debug_event_called);
7157
  CHECK(!was_debug_break_called);
7158

    
7159
  expected_break_data = NULL;
7160
  was_debug_event_called = false;
7161
  was_debug_break_called = false;
7162
  v8::Debug::DebugBreak(isolate);
7163
  v8::Script::Compile(v8::String::New("(function(x){return x+2;})(1);"))->Run();
7164
  CHECK(!was_debug_event_called);
7165
  CHECK(was_debug_break_called);
7166

    
7167
  TestClientData* data2 = new TestClientData();
7168
  expected_break_data = data2;
7169
  was_debug_event_called = false;
7170
  was_debug_break_called = false;
7171
  v8::Debug::DebugBreak(isolate);
7172
  v8::Debug::DebugBreakForCommand(data2, isolate);
7173
  v8::Script::Compile(v8::String::New("(function(x){return x+3;})(1);"))->Run();
7174
  CHECK(was_debug_event_called);
7175
  CHECK(was_debug_break_called);
7176

    
7177
  CHECK_EQ(2, TestClientData::constructor_call_counter);
7178
  CHECK_EQ(TestClientData::constructor_call_counter,
7179
           TestClientData::destructor_call_counter);
7180

    
7181
  v8::Debug::SetDebugEventListener2(NULL);
7182
  CheckDebuggerUnloaded();
7183
}
7184

    
7185
static bool debug_event_break_deoptimize_done = false;
7186

    
7187
static void DebugEventBreakDeoptimize(
7188
    const v8::Debug::EventDetails& event_details) {
7189
  v8::DebugEvent event = event_details.GetEvent();
7190
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7191
  if (event == v8::Break) {
7192
    if (!frame_function_name.IsEmpty()) {
7193
      // Get the name of the function.
7194
      const int argc = 2;
7195
      v8::Handle<v8::Value> argv[argc] = { exec_state, v8::Integer::New(0) };
7196
      v8::Handle<v8::Value> result =
7197
          frame_function_name->Call(exec_state, argc, argv);
7198
      if (!result->IsUndefined()) {
7199
        char fn[80];
7200
        CHECK(result->IsString());
7201
        v8::Handle<v8::String> function_name(result->ToString());
7202
        function_name->WriteUtf8(fn);
7203
        if (strcmp(fn, "bar") == 0) {
7204
          i::Deoptimizer::DeoptimizeAll(CcTest::i_isolate());
7205
          debug_event_break_deoptimize_done = true;
7206
        }
7207
      }
7208
    }
7209

    
7210
    v8::Debug::DebugBreak(CcTest::isolate());
7211
  }
7212
}
7213

    
7214

    
7215
// Test deoptimization when execution is broken using the debug break stack
7216
// check interrupt.
7217
TEST(DeoptimizeDuringDebugBreak) {
7218
  DebugLocalContext env;
7219
  v8::HandleScope scope(env->GetIsolate());
7220
  env.ExposeDebug();
7221

    
7222
  // Create a function for checking the function when hitting a break point.
7223
  frame_function_name = CompileFunction(&env,
7224
                                        frame_function_name_source,
7225
                                        "frame_function_name");
7226

    
7227

    
7228
  // Set a debug event listener which will keep interrupting execution until
7229
  // debug break. When inside function bar it will deoptimize all functions.
7230
  // This tests lazy deoptimization bailout for the stack check, as the first
7231
  // time in function bar when using debug break and no break points will be at
7232
  // the initial stack check.
7233
  v8::Debug::SetDebugEventListener2(DebugEventBreakDeoptimize);
7234

    
7235
  // Compile and run function bar which will optimize it for some flag settings.
7236
  v8::Script::Compile(v8::String::New("function bar(){}; bar()"))->Run();
7237

    
7238
  // Set debug break and call bar again.
7239
  v8::Debug::DebugBreak(env->GetIsolate());
7240
  v8::Script::Compile(v8::String::New("bar()"))->Run();
7241

    
7242
  CHECK(debug_event_break_deoptimize_done);
7243

    
7244
  v8::Debug::SetDebugEventListener2(NULL);
7245
}
7246

    
7247

    
7248
static void DebugEventBreakWithOptimizedStack(
7249
    const v8::Debug::EventDetails& event_details) {
7250
  v8::DebugEvent event = event_details.GetEvent();
7251
  v8::Handle<v8::Object> exec_state = event_details.GetExecutionState();
7252
  if (event == v8::Break) {
7253
    if (!frame_function_name.IsEmpty()) {
7254
      for (int i = 0; i < 2; i++) {
7255
        const int argc = 2;
7256
        v8::Handle<v8::Value> argv[argc] = { exec_state, v8::Integer::New(i) };
7257
        // Get the name of the function in frame i.
7258
        v8::Handle<v8::Value> result =
7259
            frame_function_name->Call(exec_state, argc, argv);
7260
        CHECK(result->IsString());
7261
        v8::Handle<v8::String> function_name(result->ToString());
7262
        CHECK(function_name->Equals(v8::String::New("loop")));
7263
        // Get the name of the first argument in frame i.
7264
        result = frame_argument_name->Call(exec_state, argc, argv);
7265
        CHECK(result->IsString());
7266
        v8::Handle<v8::String> argument_name(result->ToString());
7267
        CHECK(argument_name->Equals(v8::String::New("count")));
7268
        // Get the value of the first argument in frame i. If the
7269
        // funtion is optimized the value will be undefined, otherwise
7270
        // the value will be '1 - i'.
7271
        //
7272
        // TODO(3141533): We should be able to get the real value for
7273
        // optimized frames.
7274
        result = frame_argument_value->Call(exec_state, argc, argv);
7275
        CHECK(result->IsUndefined() || (result->Int32Value() == 1 - i));
7276
        // Get the name of the first local variable.
7277
        result = frame_local_name->Call(exec_state, argc, argv);
7278
        CHECK(result->IsString());
7279
        v8::Handle<v8::String> local_name(result->ToString());
7280
        CHECK(local_name->Equals(v8::String::New("local")));
7281
        // Get the value of the first local variable. If the function
7282
        // is optimized the value will be undefined, otherwise it will
7283
        // be 42.
7284
        //
7285
        // TODO(3141533): We should be able to get the real value for
7286
        // optimized frames.
7287
        result = frame_local_value->Call(exec_state, argc, argv);
7288
        CHECK(result->IsUndefined() || (result->Int32Value() == 42));
7289
      }
7290
    }
7291
  }
7292
}
7293

    
7294

    
7295
static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
7296
  v8::Debug::SetDebugEventListener2(DebugEventBreakWithOptimizedStack);
7297
  v8::Debug::DebugBreak(args.GetIsolate());
7298
}
7299

    
7300

    
7301
TEST(DebugBreakStackInspection) {
7302
  DebugLocalContext env;
7303
  v8::HandleScope scope(env->GetIsolate());
7304

    
7305
  frame_function_name =
7306
      CompileFunction(&env, frame_function_name_source, "frame_function_name");
7307
  frame_argument_name =
7308
      CompileFunction(&env, frame_argument_name_source, "frame_argument_name");
7309
  frame_argument_value = CompileFunction(&env,
7310
                                         frame_argument_value_source,
7311
                                         "frame_argument_value");
7312
  frame_local_name =
7313
      CompileFunction(&env, frame_local_name_source, "frame_local_name");
7314
  frame_local_value =
7315
      CompileFunction(&env, frame_local_value_source, "frame_local_value");
7316

    
7317
  v8::Handle<v8::FunctionTemplate> schedule_break_template =
7318
      v8::FunctionTemplate::New(ScheduleBreak);
7319
  v8::Handle<v8::Function> schedule_break =
7320
      schedule_break_template->GetFunction();
7321
  env->Global()->Set(v8_str("scheduleBreak"), schedule_break);
7322

    
7323
  const char* src =
7324
      "function loop(count) {"
7325
      "  var local = 42;"
7326
      "  if (count < 1) { scheduleBreak(); loop(count + 1); }"
7327
      "}"
7328
      "loop(0);";
7329
  v8::Script::Compile(v8::String::New(src))->Run();
7330
}
7331

    
7332

    
7333
// Test that setting the terminate execution flag during debug break processing.
7334
static void TestDebugBreakInLoop(const char* loop_head,
7335
                                 const char** loop_bodies,
7336
                                 const char* loop_tail) {
7337
  // Receive 100 breaks for each test and then terminate JavaScript execution.
7338
  static const int kBreaksPerTest = 100;
7339

    
7340
  for (int i = 0; loop_bodies[i] != NULL; i++) {
7341
    // Perform a lazy deoptimization after various numbers of breaks
7342
    // have been hit.
7343
    for (int j = 0; j < 11; j++) {
7344
      break_point_hit_count_deoptimize = j;
7345
      if (j == 10) {
7346
        break_point_hit_count_deoptimize = kBreaksPerTest;
7347
      }
7348

    
7349
      break_point_hit_count = 0;
7350
      max_break_point_hit_count = kBreaksPerTest;
7351
      terminate_after_max_break_point_hit = true;
7352

    
7353
      EmbeddedVector<char, 1024> buffer;
7354
      OS::SNPrintF(buffer,
7355
                   "function f() {%s%s%s}",
7356
                   loop_head, loop_bodies[i], loop_tail);
7357

    
7358
      // Function with infinite loop.
7359
      CompileRun(buffer.start());
7360

    
7361
      // Set the debug break to enter the debugger as soon as possible.
7362
      v8::Debug::DebugBreak(CcTest::isolate());
7363

    
7364
      // Call function with infinite loop.
7365
      CompileRun("f();");
7366
      CHECK_EQ(kBreaksPerTest, break_point_hit_count);
7367

    
7368
      CHECK(!v8::V8::IsExecutionTerminating());
7369
    }
7370
  }
7371
}
7372

    
7373

    
7374
TEST(DebugBreakLoop) {
7375
  DebugLocalContext env;
7376
  v8::HandleScope scope(env->GetIsolate());
7377

    
7378
  // Register a debug event listener which sets the break flag and counts.
7379
  v8::Debug::SetDebugEventListener2(DebugEventBreakMax);
7380

    
7381
  // Create a function for getting the frame count when hitting the break.
7382
  frame_count = CompileFunction(&env, frame_count_source, "frame_count");
7383

    
7384
  CompileRun("var a = 1;");
7385
  CompileRun("function g() { }");
7386
  CompileRun("function h() { }");
7387

    
7388
  const char* loop_bodies[] = {
7389
      "",
7390
      "g()",
7391
      "if (a == 0) { g() }",
7392
      "if (a == 1) { g() }",
7393
      "if (a == 0) { g() } else { h() }",
7394
      "if (a == 0) { continue }",
7395
      "if (a == 1) { continue }",
7396
      "switch (a) { case 1: g(); }",
7397
      "switch (a) { case 1: continue; }",
7398
      "switch (a) { case 1: g(); break; default: h() }",
7399
      "switch (a) { case 1: continue; break; default: h() }",
7400
      NULL
7401
  };
7402

    
7403
  TestDebugBreakInLoop("while (true) {", loop_bodies, "}");
7404
  TestDebugBreakInLoop("while (a == 1) {", loop_bodies, "}");
7405

    
7406
  TestDebugBreakInLoop("do {", loop_bodies, "} while (true)");
7407
  TestDebugBreakInLoop("do {", loop_bodies, "} while (a == 1)");
7408

    
7409
  TestDebugBreakInLoop("for (;;) {", loop_bodies, "}");
7410
  TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}");
7411

    
7412
  // Get rid of the debug event listener.
7413
  v8::Debug::SetDebugEventListener2(NULL);
7414
  CheckDebuggerUnloaded();
7415
}
7416

    
7417

    
7418
v8::Local<v8::Script> inline_script;
7419

    
7420
static void DebugBreakInlineListener(
7421
    const v8::Debug::EventDetails& event_details) {
7422
  v8::DebugEvent event = event_details.GetEvent();
7423
  if (event != v8::Break) return;
7424

    
7425
  int expected_frame_count = 4;
7426
  int expected_line_number[] = {1, 4, 7, 12};
7427

    
7428
  i::Handle<i::Object> compiled_script = v8::Utils::OpenHandle(*inline_script);
7429
  i::Handle<i::Script> source_script = i::Handle<i::Script>(i::Script::cast(
7430
      i::JSFunction::cast(*compiled_script)->shared()->script()));
7431

    
7432
  int break_id = CcTest::i_isolate()->debug()->break_id();
7433
  char script[128];
7434
  i::Vector<char> script_vector(script, sizeof(script));
7435
  OS::SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
7436
  v8::Local<v8::Value> result = CompileRun(script);
7437

    
7438
  int frame_count = result->Int32Value();
7439
  CHECK_EQ(expected_frame_count, frame_count);
7440

    
7441
  for (int i = 0; i < frame_count; i++) {
7442
    // The 5. element in the returned array of GetFrameDetails contains the
7443
    // source position of that frame.
7444
    OS::SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
7445
    v8::Local<v8::Value> result = CompileRun(script);
7446
    CHECK_EQ(expected_line_number[i],
7447
             i::GetScriptLineNumber(source_script, result->Int32Value()));
7448
  }
7449
  v8::Debug::SetDebugEventListener2(NULL);
7450
  v8::V8::TerminateExecution(CcTest::isolate());
7451
}
7452

    
7453

    
7454
TEST(DebugBreakInline) {
7455
  i::FLAG_allow_natives_syntax = true;
7456
  DebugLocalContext env;
7457
  v8::HandleScope scope(env->GetIsolate());
7458
  const char* source =
7459
      "function debug(b) {             \n"
7460
      "  if (b) debugger;              \n"
7461
      "}                               \n"
7462
      "function f(b) {                 \n"
7463
      "  debug(b)                      \n"
7464
      "};                              \n"
7465
      "function g(b) {                 \n"
7466
      "  f(b);                         \n"
7467
      "};                              \n"
7468
      "g(false);                       \n"
7469
      "g(false);                       \n"
7470
      "%OptimizeFunctionOnNextCall(g); \n"
7471
      "g(true);";
7472
  v8::Debug::SetDebugEventListener2(DebugBreakInlineListener);
7473
  inline_script = v8::Script::Compile(v8::String::New(source));
7474
  inline_script->Run();
7475
}
7476

    
7477

    
7478
static void DebugEventStepNext(
7479
    const v8::Debug::EventDetails& event_details) {
7480
  v8::DebugEvent event = event_details.GetEvent();
7481
  if (event == v8::Break) {
7482
    PrepareStep(StepNext);
7483
  }
7484
}
7485

    
7486

    
7487
static void RunScriptInANewCFrame(const char* source) {
7488
  v8::TryCatch try_catch;
7489
  CompileRun(source);
7490
  CHECK(try_catch.HasCaught());
7491
}
7492

    
7493

    
7494
TEST(Regress131642) {
7495
  // Bug description:
7496
  // When doing StepNext through the first script, the debugger is not reset
7497
  // after exiting through exception.  A flawed implementation enabling the
7498
  // debugger to step into Array.prototype.forEach breaks inside the callback
7499
  // for forEach in the second script under the assumption that we are in a
7500
  // recursive call.  In an attempt to step out, we crawl the stack using the
7501
  // recorded frame pointer from the first script and fail when not finding it
7502
  // on the stack.
7503
  DebugLocalContext env;
7504
  v8::HandleScope scope(env->GetIsolate());
7505
  v8::Debug::SetDebugEventListener2(DebugEventStepNext);
7506

    
7507
  // We step through the first script.  It exits through an exception.  We run
7508
  // this inside a new frame to record a different FP than the second script
7509
  // would expect.
7510
  const char* script_1 = "debugger; throw new Error();";
7511
  RunScriptInANewCFrame(script_1);
7512

    
7513
  // The second script uses forEach.
7514
  const char* script_2 = "[0].forEach(function() { });";
7515
  CompileRun(script_2);
7516

    
7517
  v8::Debug::SetDebugEventListener2(NULL);
7518
}
7519

    
7520

    
7521
// Import from test-heap.cc
7522
int CountNativeContexts();
7523

    
7524

    
7525
static void NopListener(const v8::Debug::EventDetails& event_details) {
7526
}
7527

    
7528

    
7529
TEST(DebuggerCreatesContextIffActive) {
7530
  DebugLocalContext env;
7531
  v8::HandleScope scope(env->GetIsolate());
7532
  CHECK_EQ(1, CountNativeContexts());
7533

    
7534
  v8::Debug::SetDebugEventListener2(NULL);
7535
  CompileRun("debugger;");
7536
  CHECK_EQ(1, CountNativeContexts());
7537

    
7538
  v8::Debug::SetDebugEventListener2(NopListener);
7539
  CompileRun("debugger;");
7540
  CHECK_EQ(2, CountNativeContexts());
7541

    
7542
  v8::Debug::SetDebugEventListener2(NULL);
7543
}
7544

    
7545

    
7546
TEST(LiveEditEnabled) {
7547
  v8::internal::FLAG_allow_natives_syntax = true;
7548
  LocalContext env;
7549
  v8::HandleScope scope(env->GetIsolate());
7550
  v8::Debug::SetLiveEditEnabled(true, env->GetIsolate());
7551
  CompileRun("%LiveEditCompareStrings('', '')");
7552
}
7553

    
7554

    
7555
TEST(LiveEditDisabled) {
7556
  v8::internal::FLAG_allow_natives_syntax = true;
7557
  LocalContext env;
7558
  v8::HandleScope scope(env->GetIsolate());
7559
  v8::Debug::SetLiveEditEnabled(false), env->GetIsolate();
7560
  CompileRun("%LiveEditCompareStrings('', '')");
7561
}
7562

    
7563

    
7564
#endif  // ENABLE_DEBUGGER_SUPPORT