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