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