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