LCOV - code coverage report
Current view: top level - test/cctest - test-debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2954 2986 98.9 %
Date: 2017-10-20 Functions: 201 209 96.2 %

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

Generated by: LCOV version 1.10