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