LCOV - code coverage report
Current view: top level - test/cctest - test-debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 2076 2110 98.4 %
Date: 2019-01-20 Functions: 148 189 78.3 %

          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             : 
      30             : #include "src/v8.h"
      31             : 
      32             : #include "src/api-inl.h"
      33             : #include "src/compilation-cache.h"
      34             : #include "src/debug/debug-interface.h"
      35             : #include "src/debug/debug.h"
      36             : #include "src/deoptimizer.h"
      37             : #include "src/frames.h"
      38             : #include "src/objects-inl.h"
      39             : #include "src/snapshot/natives.h"
      40             : #include "src/snapshot/snapshot.h"
      41             : #include "src/utils.h"
      42             : #include "test/cctest/cctest.h"
      43             : 
      44             : using ::v8::internal::Handle;
      45             : using ::v8::internal::StepNone;  // From StepAction enum
      46             : using ::v8::internal::StepIn;  // From StepAction enum
      47             : using ::v8::internal::StepNext;  // From StepAction enum
      48             : using ::v8::internal::StepOut;  // From StepAction enum
      49             : 
      50             : // --- H e l p e r   F u n c t i o n s
      51             : 
      52             : // Compile and run the supplied source and return the requested function.
      53         320 : static v8::Local<v8::Function> CompileFunction(v8::Isolate* isolate,
      54             :                                                const char* source,
      55             :                                                const char* function_name) {
      56         320 :   CompileRunChecked(isolate, source);
      57         320 :   v8::Local<v8::String> name = v8_str(isolate, function_name);
      58         320 :   v8::Local<v8::Context> context = isolate->GetCurrentContext();
      59             :   v8::MaybeLocal<v8::Value> maybe_function =
      60         640 :       context->Global()->Get(context, name);
      61         320 :   return v8::Local<v8::Function>::Cast(maybe_function.ToLocalChecked());
      62             : }
      63             : 
      64             : 
      65             : // Compile and run the supplied source and return the requested function.
      66         280 : static v8::Local<v8::Function> CompileFunction(LocalContext* env,
      67             :                                                const char* source,
      68             :                                                const char* function_name) {
      69         280 :   return CompileFunction((*env)->GetIsolate(), source, function_name);
      70             : }
      71             : 
      72             : // Is there any debug info for the function?
      73          50 : static bool HasBreakInfo(v8::Local<v8::Function> fun) {
      74             :   Handle<v8::internal::JSFunction> f =
      75          50 :       Handle<v8::internal::JSFunction>::cast(v8::Utils::OpenHandle(*fun));
      76         100 :   Handle<v8::internal::SharedFunctionInfo> shared(f->shared(), f->GetIsolate());
      77          50 :   return shared->HasBreakInfo();
      78             : }
      79             : 
      80             : // Set a break point in a function with a position relative to function start,
      81             : // and return the associated break point number.
      82         350 : static i::Handle<i::BreakPoint> SetBreakPoint(v8::Local<v8::Function> fun,
      83             :                                               int position,
      84             :                                               const char* condition = nullptr) {
      85             :   i::Handle<i::JSFunction> function =
      86         350 :       i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*fun));
      87         350 :   position += function->shared()->StartPosition();
      88             :   static int break_point_index = 0;
      89         350 :   i::Isolate* isolate = function->GetIsolate();
      90             :   i::Handle<i::String> condition_string =
      91             :       condition ? isolate->factory()->NewStringFromAsciiChecked(condition)
      92         655 :                 : isolate->factory()->empty_string();
      93             :   i::Debug* debug = isolate->debug();
      94             :   i::Handle<i::BreakPoint> break_point =
      95         350 :       isolate->factory()->NewBreakPoint(++break_point_index, condition_string);
      96             : 
      97         350 :   debug->SetBreakPoint(function, break_point, &position);
      98         350 :   return break_point;
      99             : }
     100             : 
     101             : 
     102         175 : static void ClearBreakPoint(i::Handle<i::BreakPoint> break_point) {
     103         175 :   v8::internal::Isolate* isolate = CcTest::i_isolate();
     104             :   v8::internal::Debug* debug = isolate->debug();
     105         175 :   debug->ClearBreakPoint(break_point);
     106         175 : }
     107             : 
     108             : 
     109             : // Change break on exception.
     110          15 : static void ChangeBreakOnException(bool caught, bool uncaught) {
     111          15 :   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
     112          15 :   debug->ChangeBreakOnException(v8::internal::BreakException, caught);
     113          15 :   debug->ChangeBreakOnException(v8::internal::BreakUncaughtException, uncaught);
     114          15 : }
     115             : 
     116             : 
     117             : // Prepare to step to next break location.
     118       11980 : static void PrepareStep(i::StepAction step_action) {
     119       11980 :   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
     120       11980 :   debug->PrepareStep(step_action);
     121       11980 : }
     122             : 
     123             : // This function is in namespace v8::internal to be friend with class
     124             : // v8::internal::Debug.
     125             : namespace v8 {
     126             : namespace internal {
     127             : 
     128             : // Collect the currently debugged functions.
     129          25 : Handle<FixedArray> GetDebuggedFunctions() {
     130          25 :   Debug* debug = CcTest::i_isolate()->debug();
     131             : 
     132          45 :   v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
     133             : 
     134             :   // Find the number of debugged functions.
     135             :   int count = 0;
     136          70 :   while (node) {
     137          20 :     count++;
     138             :     node = node->next();
     139             :   }
     140             : 
     141             :   // Allocate array for the debugged functions
     142             :   Handle<FixedArray> debugged_functions =
     143          25 :       CcTest::i_isolate()->factory()->NewFixedArray(count);
     144             : 
     145             :   // Run through the debug info objects and collect all functions.
     146             :   count = 0;
     147          50 :   while (node) {
     148           0 :     debugged_functions->set(count++, *node->debug_info());
     149             :     node = node->next();
     150             :   }
     151             : 
     152          25 :   return debugged_functions;
     153             : }
     154             : 
     155             : 
     156             : // Check that the debugger has been fully unloaded.
     157         410 : void CheckDebuggerUnloaded() {
     158             :   // Check that the debugger context is cleared and that there is no debug
     159             :   // information stored for the debugger.
     160         410 :   CHECK(!CcTest::i_isolate()->debug()->debug_info_list_);
     161             : 
     162             :   // Collect garbage to ensure weak handles are cleared.
     163         410 :   CcTest::CollectAllGarbage();
     164         410 :   CcTest::CollectAllGarbage();
     165             : 
     166             :   // Iterate the heap and check that there are no debugger related objects left.
     167         410 :   HeapIterator iterator(CcTest::heap());
     168     5579546 :   for (HeapObject obj = iterator.next(); !obj.is_null();
     169             :        obj = iterator.next()) {
     170     2789363 :     CHECK(!obj->IsDebugInfo());
     171         410 :   }
     172         410 : }
     173             : 
     174             : 
     175             : }  // namespace internal
     176             : }  // namespace v8
     177             : 
     178             : 
     179             : // Check that the debugger has been fully unloaded.
     180         410 : static void CheckDebuggerUnloaded() { v8::internal::CheckDebuggerUnloaded(); }
     181             : 
     182             : // --- D e b u g   E v e n t   H a n d l e r s
     183             : // ---
     184             : // --- The different tests uses a number of debug event handlers.
     185             : // ---
     186             : 
     187             : // Debug event handler which counts a number of events.
     188             : int break_point_hit_count = 0;
     189             : int break_point_hit_count_deoptimize = 0;
     190         300 : class DebugEventCounter : public v8::debug::DebugDelegate {
     191             :  public:
     192       12765 :   void BreakProgramRequested(
     193             :       v8::Local<v8::Context>,
     194             :       const std::vector<v8::debug::BreakpointId>&) override {
     195       12765 :     break_point_hit_count++;
     196             :     // Perform a full deoptimization when the specified number of
     197             :     // breaks have been hit.
     198       12765 :     if (break_point_hit_count == break_point_hit_count_deoptimize) {
     199           0 :       i::Deoptimizer::DeoptimizeAll(CcTest::i_isolate());
     200             :     }
     201       12765 :     if (step_action_ != StepNone) PrepareStep(step_action_);
     202       12765 :   }
     203             : 
     204             :   void set_step_action(i::StepAction step_action) {
     205         180 :     step_action_ = step_action;
     206             :   }
     207             : 
     208             :  private:
     209             :   i::StepAction step_action_ = StepNone;
     210             : };
     211             : 
     212             : // Debug event handler which performs a garbage collection.
     213          15 : class DebugEventBreakPointCollectGarbage : public v8::debug::DebugDelegate {
     214             :  public:
     215         420 :   void BreakProgramRequested(
     216             :       v8::Local<v8::Context>,
     217             :       const std::vector<v8::debug::BreakpointId>&) override {
     218             :     // Perform a garbage collection when break point is hit and continue. Based
     219             :     // on the number of break points hit either scavenge or mark compact
     220             :     // collector is used.
     221         420 :     break_point_hit_count++;
     222         420 :     if (break_point_hit_count % 2 == 0) {
     223             :       // Scavenge.
     224         205 :       CcTest::CollectGarbage(v8::internal::NEW_SPACE);
     225             :     } else {
     226             :       // Mark sweep compact.
     227         215 :       CcTest::CollectAllGarbage();
     228             :     }
     229         420 :   }
     230             : };
     231             : 
     232             : // Debug event handler which re-issues a debug break and calls the garbage
     233             : // collector to have the heap verified.
     234          10 : class DebugEventBreak : public v8::debug::DebugDelegate {
     235             :  public:
     236          85 :   void BreakProgramRequested(
     237             :       v8::Local<v8::Context>,
     238             :       const std::vector<v8::debug::BreakpointId>&) override {
     239             :     // Count the number of breaks.
     240          85 :     break_point_hit_count++;
     241             : 
     242             :     // Run the garbage collector to enforce heap verification if option
     243             :     // --verify-heap is set.
     244          85 :     CcTest::CollectGarbage(v8::internal::NEW_SPACE);
     245             : 
     246             :     // Set the break flag again to come back here as soon as possible.
     247          85 :     v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
     248          85 :   }
     249             : };
     250             : 
     251       59905 : static void BreakRightNow(v8::Isolate* isolate, void*) {
     252       59905 :   v8::debug::BreakRightNow(isolate);
     253       59905 : }
     254             : 
     255             : // Debug event handler which re-issues a debug break until a limit has been
     256             : // reached.
     257             : int max_break_point_hit_count = 0;
     258             : bool terminate_after_max_break_point_hit = false;
     259          65 : class DebugEventBreakMax : public v8::debug::DebugDelegate {
     260             :  public:
     261       60895 :   void BreakProgramRequested(
     262             :       v8::Local<v8::Context>,
     263             :       const std::vector<v8::debug::BreakpointId>&) override {
     264       60895 :     v8::Isolate* v8_isolate = CcTest::isolate();
     265             :     v8::internal::Isolate* isolate = CcTest::i_isolate();
     266       60895 :     if (break_point_hit_count < max_break_point_hit_count) {
     267             :       // Count the number of breaks.
     268       59900 :       break_point_hit_count++;
     269             : 
     270             :       // Set the break flag again to come back here as soon as possible.
     271       59900 :       v8_isolate->RequestInterrupt(BreakRightNow, nullptr);
     272             : 
     273         995 :     } else if (terminate_after_max_break_point_hit) {
     274             :       // Terminate execution after the last break if requested.
     275         990 :       v8_isolate->TerminateExecution();
     276             :     }
     277             : 
     278             :     // Perform a full deoptimization when the specified number of
     279             :     // breaks have been hit.
     280       60895 :     if (break_point_hit_count == break_point_hit_count_deoptimize) {
     281         990 :       i::Deoptimizer::DeoptimizeAll(isolate);
     282             :     }
     283       60895 :   }
     284             : };
     285             : 
     286             : // --- T h e   A c t u a l   T e s t s
     287             : 
     288             : // Test that the debug info in the VM is in sync with the functions being
     289             : // debugged.
     290       28342 : TEST(DebugInfo) {
     291           5 :   LocalContext env;
     292          10 :   v8::HandleScope scope(env->GetIsolate());
     293             :   // Create a couple of functions for the test.
     294             :   v8::Local<v8::Function> foo =
     295           5 :       CompileFunction(&env, "function foo(){}", "foo");
     296             :   v8::Local<v8::Function> bar =
     297           5 :       CompileFunction(&env, "function bar(){}", "bar");
     298             :   // Initially no functions are debugged.
     299          10 :   CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
     300           5 :   CHECK(!HasBreakInfo(foo));
     301           5 :   CHECK(!HasBreakInfo(bar));
     302           5 :   EnableDebugger(env->GetIsolate());
     303             :   // One function (foo) is debugged.
     304           5 :   i::Handle<i::BreakPoint> bp1 = SetBreakPoint(foo, 0);
     305          10 :   CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
     306           5 :   CHECK(HasBreakInfo(foo));
     307           5 :   CHECK(!HasBreakInfo(bar));
     308             :   // Two functions are debugged.
     309           5 :   i::Handle<i::BreakPoint> bp2 = SetBreakPoint(bar, 0);
     310          10 :   CHECK_EQ(2, v8::internal::GetDebuggedFunctions()->length());
     311           5 :   CHECK(HasBreakInfo(foo));
     312           5 :   CHECK(HasBreakInfo(bar));
     313             :   // One function (bar) is debugged.
     314           5 :   ClearBreakPoint(bp1);
     315          10 :   CHECK_EQ(1, v8::internal::GetDebuggedFunctions()->length());
     316           5 :   CHECK(!HasBreakInfo(foo));
     317           5 :   CHECK(HasBreakInfo(bar));
     318             :   // No functions are debugged.
     319           5 :   ClearBreakPoint(bp2);
     320           5 :   DisableDebugger(env->GetIsolate());
     321          10 :   CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
     322           5 :   CHECK(!HasBreakInfo(foo));
     323          10 :   CHECK(!HasBreakInfo(bar));
     324           5 : }
     325             : 
     326             : 
     327             : // Test that a break point can be set at an IC store location.
     328       28342 : TEST(BreakPointICStore) {
     329           5 :   break_point_hit_count = 0;
     330           5 :   LocalContext env;
     331          10 :   v8::HandleScope scope(env->GetIsolate());
     332             : 
     333           5 :   DebugEventCounter delegate;
     334           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     335             :   v8::Local<v8::Function> foo =
     336           5 :       CompileFunction(&env, "function foo(){bar=0;}", "foo");
     337             : 
     338             :   // Run without breakpoints.
     339          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     340           5 :   CHECK_EQ(0, break_point_hit_count);
     341             : 
     342             :   // Run with breakpoint
     343           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
     344          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     345           5 :   CHECK_EQ(1, break_point_hit_count);
     346          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     347           5 :   CHECK_EQ(2, break_point_hit_count);
     348             : 
     349             :   // Run without breakpoints.
     350           5 :   ClearBreakPoint(bp);
     351          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     352           5 :   CHECK_EQ(2, break_point_hit_count);
     353             : 
     354           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     355           5 :   CheckDebuggerUnloaded();
     356           5 : }
     357             : 
     358             : // Test that a break point can be set at an IC store location.
     359       28342 : TEST(BreakPointCondition) {
     360           5 :   break_point_hit_count = 0;
     361           5 :   LocalContext env;
     362          10 :   v8::HandleScope scope(env->GetIsolate());
     363             : 
     364           5 :   DebugEventCounter delegate;
     365           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     366             :   CompileRun("var a = false");
     367             :   v8::Local<v8::Function> foo =
     368           5 :       CompileFunction(&env, "function foo() { return 1 }", "foo");
     369             :   // Run without breakpoints.
     370             :   CompileRun("foo()");
     371           5 :   CHECK_EQ(0, break_point_hit_count);
     372             : 
     373             :   // Run with breakpoint
     374           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0, "a == true");
     375             :   CompileRun("foo()");
     376           5 :   CHECK_EQ(0, break_point_hit_count);
     377             : 
     378             :   CompileRun("a = true");
     379             :   CompileRun("foo()");
     380           5 :   CHECK_EQ(1, break_point_hit_count);
     381             : 
     382             :   // Run without breakpoints.
     383           5 :   ClearBreakPoint(bp);
     384             :   CompileRun("foo()");
     385           5 :   CHECK_EQ(1, break_point_hit_count);
     386             : 
     387           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     388           5 :   CheckDebuggerUnloaded();
     389           5 : }
     390             : 
     391             : // Test that a break point can be set at an IC load location.
     392       28342 : TEST(BreakPointICLoad) {
     393           5 :   break_point_hit_count = 0;
     394           5 :   LocalContext env;
     395          10 :   v8::HandleScope scope(env->GetIsolate());
     396           5 :   DebugEventCounter delegate;
     397           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     398             : 
     399           5 :   CompileRunChecked(env->GetIsolate(), "bar=1");
     400             :   v8::Local<v8::Function> foo =
     401           5 :       CompileFunction(&env, "function foo(){var x=bar;}", "foo");
     402             : 
     403             :   // Run without breakpoints.
     404          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     405           5 :   CHECK_EQ(0, break_point_hit_count);
     406             : 
     407             :   // Run with breakpoint.
     408           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
     409          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     410           5 :   CHECK_EQ(1, break_point_hit_count);
     411          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     412           5 :   CHECK_EQ(2, break_point_hit_count);
     413             : 
     414             :   // Run without breakpoints.
     415           5 :   ClearBreakPoint(bp);
     416          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     417           5 :   CHECK_EQ(2, break_point_hit_count);
     418             : 
     419           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     420           5 :   CheckDebuggerUnloaded();
     421           5 : }
     422             : 
     423             : 
     424             : // Test that a break point can be set at an IC call location.
     425       28342 : TEST(BreakPointICCall) {
     426           5 :   break_point_hit_count = 0;
     427           5 :   LocalContext env;
     428          10 :   v8::HandleScope scope(env->GetIsolate());
     429           5 :   DebugEventCounter delegate;
     430           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     431           5 :   CompileRunChecked(env->GetIsolate(), "function bar(){}");
     432             :   v8::Local<v8::Function> foo =
     433           5 :       CompileFunction(&env, "function foo(){bar();}", "foo");
     434             : 
     435             :   // Run without breakpoints.
     436          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     437           5 :   CHECK_EQ(0, break_point_hit_count);
     438             : 
     439             :   // Run with breakpoint
     440           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
     441          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     442           5 :   CHECK_EQ(1, break_point_hit_count);
     443          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     444           5 :   CHECK_EQ(2, break_point_hit_count);
     445             : 
     446             :   // Run without breakpoints.
     447           5 :   ClearBreakPoint(bp);
     448          15 :   foo->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
     449           5 :   CHECK_EQ(2, break_point_hit_count);
     450             : 
     451           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     452           5 :   CheckDebuggerUnloaded();
     453           5 : }
     454             : 
     455             : 
     456             : // Test that a break point can be set at an IC call location and survive a GC.
     457       28342 : TEST(BreakPointICCallWithGC) {
     458           5 :   break_point_hit_count = 0;
     459           5 :   LocalContext env;
     460          10 :   v8::HandleScope scope(env->GetIsolate());
     461           5 :   DebugEventBreakPointCollectGarbage delegate;
     462           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     463           5 :   CompileRunChecked(env->GetIsolate(), "function bar(){return 1;}");
     464             :   v8::Local<v8::Function> foo =
     465           5 :       CompileFunction(&env, "function foo(){return bar();}", "foo");
     466           5 :   v8::Local<v8::Context> context = env.local();
     467             : 
     468             :   // Run without breakpoints.
     469          20 :   CHECK_EQ(1, foo->Call(context, env->Global(), 0, nullptr)
     470             :                   .ToLocalChecked()
     471             :                   ->Int32Value(context)
     472             :                   .FromJust());
     473           5 :   CHECK_EQ(0, break_point_hit_count);
     474             : 
     475             :   // Run with breakpoint.
     476           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
     477          20 :   CHECK_EQ(1, foo->Call(context, env->Global(), 0, nullptr)
     478             :                   .ToLocalChecked()
     479             :                   ->Int32Value(context)
     480             :                   .FromJust());
     481           5 :   CHECK_EQ(1, break_point_hit_count);
     482          20 :   CHECK_EQ(1, foo->Call(context, env->Global(), 0, nullptr)
     483             :                   .ToLocalChecked()
     484             :                   ->Int32Value(context)
     485             :                   .FromJust());
     486           5 :   CHECK_EQ(2, break_point_hit_count);
     487             : 
     488             :   // Run without breakpoints.
     489           5 :   ClearBreakPoint(bp);
     490          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
     491           5 :   CHECK_EQ(2, break_point_hit_count);
     492             : 
     493           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     494           5 :   CheckDebuggerUnloaded();
     495           5 : }
     496             : 
     497             : 
     498             : // Test that a break point can be set at an IC call location and survive a GC.
     499       28342 : TEST(BreakPointConstructCallWithGC) {
     500           5 :   break_point_hit_count = 0;
     501           5 :   LocalContext env;
     502          10 :   v8::HandleScope scope(env->GetIsolate());
     503           5 :   DebugEventBreakPointCollectGarbage delegate;
     504           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     505           5 :   CompileRunChecked(env->GetIsolate(), "function bar(){ this.x = 1;}");
     506             :   v8::Local<v8::Function> foo =
     507           5 :       CompileFunction(&env, "function foo(){return new bar(1).x;}", "foo");
     508           5 :   v8::Local<v8::Context> context = env.local();
     509             : 
     510             :   // Run without breakpoints.
     511          20 :   CHECK_EQ(1, foo->Call(context, env->Global(), 0, nullptr)
     512             :                   .ToLocalChecked()
     513             :                   ->Int32Value(context)
     514             :                   .FromJust());
     515           5 :   CHECK_EQ(0, break_point_hit_count);
     516             : 
     517             :   // Run with breakpoint.
     518           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
     519          20 :   CHECK_EQ(1, foo->Call(context, env->Global(), 0, nullptr)
     520             :                   .ToLocalChecked()
     521             :                   ->Int32Value(context)
     522             :                   .FromJust());
     523           5 :   CHECK_EQ(1, break_point_hit_count);
     524          20 :   CHECK_EQ(1, foo->Call(context, env->Global(), 0, nullptr)
     525             :                   .ToLocalChecked()
     526             :                   ->Int32Value(context)
     527             :                   .FromJust());
     528           5 :   CHECK_EQ(2, break_point_hit_count);
     529             : 
     530             :   // Run without breakpoints.
     531           5 :   ClearBreakPoint(bp);
     532          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
     533           5 :   CHECK_EQ(2, break_point_hit_count);
     534             : 
     535           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     536           5 :   CheckDebuggerUnloaded();
     537           5 : }
     538             : 
     539             : 
     540       28342 : TEST(BreakPointBuiltin) {
     541           5 :   LocalContext env;
     542          10 :   v8::HandleScope scope(env->GetIsolate());
     543             : 
     544           5 :   DebugEventCounter delegate;
     545           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     546             : 
     547             :   v8::Local<v8::Function> builtin;
     548             :   i::Handle<i::BreakPoint> bp;
     549             : 
     550             :   // === Test simple builtin ===
     551           5 :   break_point_hit_count = 0;
     552           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
     553             : 
     554             :   // Run with breakpoint.
     555           5 :   bp = SetBreakPoint(builtin, 0);
     556           5 :   ExpectString("'b'.repeat(10)", "bbbbbbbbbb");
     557           5 :   CHECK_EQ(1, break_point_hit_count);
     558             : 
     559           5 :   ExpectString("'b'.repeat(10)", "bbbbbbbbbb");
     560           5 :   CHECK_EQ(2, break_point_hit_count);
     561             : 
     562             :   // Run without breakpoints.
     563           5 :   ClearBreakPoint(bp);
     564           5 :   ExpectString("'b'.repeat(10)", "bbbbbbbbbb");
     565           5 :   CHECK_EQ(2, break_point_hit_count);
     566             : 
     567           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     568           5 :   CheckDebuggerUnloaded();
     569           5 : }
     570             : 
     571       28342 : TEST(BreakPointJSBuiltin) {
     572           5 :   LocalContext env;
     573          10 :   v8::HandleScope scope(env->GetIsolate());
     574             : 
     575           5 :   DebugEventCounter delegate;
     576           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     577             : 
     578             :   v8::Local<v8::Function> builtin;
     579             :   i::Handle<i::BreakPoint> bp;
     580             : 
     581             :   // === Test JS builtin ===
     582           5 :   break_point_hit_count = 0;
     583           5 :   builtin = CompileRun("Array.prototype.sort").As<v8::Function>();
     584             : 
     585             :   // Run with breakpoint.
     586           5 :   bp = SetBreakPoint(builtin, 0);
     587             :   CompileRun("[1,2,3].sort()");
     588           5 :   CHECK_EQ(1, break_point_hit_count);
     589             : 
     590             :   CompileRun("[1,2,3].sort()");
     591           5 :   CHECK_EQ(2, break_point_hit_count);
     592             : 
     593             :   // Run without breakpoints.
     594           5 :   ClearBreakPoint(bp);
     595             :   CompileRun("[1,2,3].sort()");
     596           5 :   CHECK_EQ(2, break_point_hit_count);
     597             : 
     598           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     599           5 :   CheckDebuggerUnloaded();
     600           5 : }
     601             : 
     602       28342 : TEST(BreakPointBoundBuiltin) {
     603           5 :   LocalContext env;
     604          10 :   v8::HandleScope scope(env->GetIsolate());
     605             : 
     606           5 :   DebugEventCounter delegate;
     607           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     608             : 
     609             :   v8::Local<v8::Function> builtin;
     610             :   i::Handle<i::BreakPoint> bp;
     611             : 
     612             :   // === Test bound function from a builtin ===
     613           5 :   break_point_hit_count = 0;
     614             :   builtin = CompileRun(
     615             :                 "var boundrepeat = String.prototype.repeat.bind('a');"
     616             :                 "String.prototype.repeat")
     617           5 :                 .As<v8::Function>();
     618           5 :   ExpectString("boundrepeat(10)", "aaaaaaaaaa");
     619           5 :   CHECK_EQ(0, break_point_hit_count);
     620             : 
     621             :   // Run with breakpoint.
     622           5 :   bp = SetBreakPoint(builtin, 0);
     623           5 :   ExpectString("boundrepeat(10)", "aaaaaaaaaa");
     624           5 :   CHECK_EQ(1, break_point_hit_count);
     625             : 
     626             :   // Run without breakpoints.
     627           5 :   ClearBreakPoint(bp);
     628           5 :   ExpectString("boundrepeat(10)", "aaaaaaaaaa");
     629           5 :   CHECK_EQ(1, break_point_hit_count);
     630             : 
     631           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     632           5 :   CheckDebuggerUnloaded();
     633           5 : }
     634             : 
     635       28342 : TEST(BreakPointConstructorBuiltin) {
     636           5 :   LocalContext env;
     637          10 :   v8::HandleScope scope(env->GetIsolate());
     638             : 
     639           5 :   DebugEventCounter delegate;
     640           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     641             : 
     642             :   v8::Local<v8::Function> builtin;
     643             :   i::Handle<i::BreakPoint> bp;
     644             : 
     645             :   // === Test Promise constructor ===
     646           5 :   break_point_hit_count = 0;
     647           5 :   builtin = CompileRun("Promise").As<v8::Function>();
     648           5 :   ExpectString("(new Promise(()=>{})).toString()", "[object Promise]");
     649           5 :   CHECK_EQ(0, break_point_hit_count);
     650             : 
     651             :   // Run with breakpoint.
     652           5 :   bp = SetBreakPoint(builtin, 0);
     653           5 :   ExpectString("(new Promise(()=>{})).toString()", "[object Promise]");
     654           5 :   CHECK_EQ(1, break_point_hit_count);
     655             : 
     656             :   // Run without breakpoints.
     657           5 :   ClearBreakPoint(bp);
     658           5 :   ExpectString("(new Promise(()=>{})).toString()", "[object Promise]");
     659           5 :   CHECK_EQ(1, break_point_hit_count);
     660             : 
     661             :   // === Test Object constructor ===
     662           5 :   break_point_hit_count = 0;
     663           5 :   builtin = CompileRun("Object").As<v8::Function>();
     664             :   CompileRun("new Object()");
     665           5 :   CHECK_EQ(0, break_point_hit_count);
     666             : 
     667             :   // Run with breakpoint.
     668           5 :   bp = SetBreakPoint(builtin, 0);
     669             :   CompileRun("new Object()");
     670           5 :   CHECK_EQ(1, break_point_hit_count);
     671             : 
     672             :   // Run without breakpoints.
     673           5 :   ClearBreakPoint(bp);
     674             :   CompileRun("new Object()");
     675           5 :   CHECK_EQ(1, break_point_hit_count);
     676             : 
     677             :   // === Test Number constructor ===
     678           5 :   break_point_hit_count = 0;
     679           5 :   builtin = CompileRun("Number").As<v8::Function>();
     680             :   CompileRun("new Number()");
     681           5 :   CHECK_EQ(0, break_point_hit_count);
     682             : 
     683             :   // Run with breakpoint.
     684           5 :   bp = SetBreakPoint(builtin, 0);
     685             :   CompileRun("new Number()");
     686           5 :   CHECK_EQ(1, break_point_hit_count);
     687             : 
     688             :   // Run without breakpoints.
     689           5 :   ClearBreakPoint(bp);
     690             :   CompileRun("new Number()");
     691           5 :   CHECK_EQ(1, break_point_hit_count);
     692             : 
     693           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     694           5 :   CheckDebuggerUnloaded();
     695           5 : }
     696             : 
     697       28342 : TEST(BreakPointInlinedBuiltin) {
     698           5 :   i::FLAG_allow_natives_syntax = true;
     699           5 :   LocalContext env;
     700          10 :   v8::HandleScope scope(env->GetIsolate());
     701             : 
     702           5 :   DebugEventCounter delegate;
     703           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     704             : 
     705             :   v8::Local<v8::Function> builtin;
     706             :   i::Handle<i::BreakPoint> bp;
     707             : 
     708             :   // === Test inlined builtin ===
     709           5 :   break_point_hit_count = 0;
     710           5 :   builtin = CompileRun("Math.sin").As<v8::Function>();
     711             :   CompileRun("function test(x) { return 1 + Math.sin(x) }");
     712             :   CompileRun(
     713             :       "test(0.5); test(0.6);"
     714             :       "%OptimizeFunctionOnNextCall(test); test(0.7);");
     715           5 :   CHECK_EQ(0, break_point_hit_count);
     716             : 
     717             :   // Run with breakpoint.
     718           5 :   bp = SetBreakPoint(builtin, 0);
     719             :   CompileRun("Math.sin(0.1);");
     720           5 :   CHECK_EQ(1, break_point_hit_count);
     721             :   CompileRun("test(0.2);");
     722           5 :   CHECK_EQ(2, break_point_hit_count);
     723             : 
     724             :   // Re-optimize.
     725             :   CompileRun("%OptimizeFunctionOnNextCall(test);");
     726           5 :   ExpectBoolean("test(0.3) < 2", true);
     727           5 :   CHECK_EQ(3, break_point_hit_count);
     728             : 
     729             :   // Run without breakpoints.
     730           5 :   ClearBreakPoint(bp);
     731             :   CompileRun("test(0.3);");
     732           5 :   CHECK_EQ(3, break_point_hit_count);
     733             : 
     734           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     735           5 :   CheckDebuggerUnloaded();
     736           5 : }
     737             : 
     738       28342 : TEST(BreakPointInlineBoundBuiltin) {
     739           5 :   i::FLAG_allow_natives_syntax = true;
     740           5 :   LocalContext env;
     741          10 :   v8::HandleScope scope(env->GetIsolate());
     742             : 
     743           5 :   DebugEventCounter delegate;
     744           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     745             : 
     746             :   v8::Local<v8::Function> builtin;
     747             :   i::Handle<i::BreakPoint> bp;
     748             : 
     749             :   // === Test inlined bound builtin ===
     750           5 :   break_point_hit_count = 0;
     751             : 
     752             :   builtin = CompileRun(
     753             :                 "var boundrepeat = String.prototype.repeat.bind('a');"
     754             :                 "String.prototype.repeat")
     755           5 :                 .As<v8::Function>();
     756             :   CompileRun("function test(x) { return 'a' + boundrepeat(x) }");
     757             :   CompileRun(
     758             :       "test(4); test(5);"
     759             :       "%OptimizeFunctionOnNextCall(test); test(6);");
     760           5 :   CHECK_EQ(0, break_point_hit_count);
     761             : 
     762             :   // Run with breakpoint.
     763           5 :   bp = SetBreakPoint(builtin, 0);
     764             :   CompileRun("'a'.repeat(2);");
     765           5 :   CHECK_EQ(1, break_point_hit_count);
     766             :   CompileRun("test(7);");
     767           5 :   CHECK_EQ(2, break_point_hit_count);
     768             : 
     769             :   // Re-optimize.
     770             :   CompileRun("%OptimizeFunctionOnNextCall(test);");
     771             :   CompileRun("test(8);");
     772           5 :   CHECK_EQ(3, break_point_hit_count);
     773             : 
     774             :   // Run without breakpoints.
     775           5 :   ClearBreakPoint(bp);
     776             :   CompileRun("test(9);");
     777           5 :   CHECK_EQ(3, break_point_hit_count);
     778             : 
     779           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     780           5 :   CheckDebuggerUnloaded();
     781           5 : }
     782             : 
     783       28342 : TEST(BreakPointInlinedConstructorBuiltin) {
     784           5 :   i::FLAG_allow_natives_syntax = true;
     785           5 :   i::FLAG_experimental_inline_promise_constructor = true;
     786           5 :   LocalContext env;
     787          10 :   v8::HandleScope scope(env->GetIsolate());
     788             : 
     789           5 :   DebugEventCounter delegate;
     790           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     791             : 
     792             :   v8::Local<v8::Function> builtin;
     793             :   i::Handle<i::BreakPoint> bp;
     794             : 
     795             :   // === Test inlined constructor builtin (regular construct builtin) ===
     796           5 :   break_point_hit_count = 0;
     797           5 :   builtin = CompileRun("Promise").As<v8::Function>();
     798             :   CompileRun("function test(x) { return new Promise(()=>x); }");
     799             :   CompileRun(
     800             :       "test(4); test(5);"
     801             :       "%OptimizeFunctionOnNextCall(test); test(6);");
     802           5 :   CHECK_EQ(0, break_point_hit_count);
     803             : 
     804             :   // Run with breakpoint.
     805           5 :   bp = SetBreakPoint(builtin, 0);
     806             :   CompileRun("new Promise(()=>{});");
     807           5 :   CHECK_EQ(1, break_point_hit_count);
     808             :   CompileRun("test(7);");
     809           5 :   CHECK_EQ(2, break_point_hit_count);
     810             : 
     811             :   // Re-optimize.
     812             :   CompileRun("%OptimizeFunctionOnNextCall(test);");
     813             :   CompileRun("test(8);");
     814           5 :   CHECK_EQ(3, break_point_hit_count);
     815             : 
     816             :   // Run without breakpoints.
     817           5 :   ClearBreakPoint(bp);
     818             :   CompileRun("test(9);");
     819           5 :   CHECK_EQ(3, break_point_hit_count);
     820             : 
     821           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     822           5 :   CheckDebuggerUnloaded();
     823           5 : }
     824             : 
     825       28342 : TEST(BreakPointBuiltinConcurrentOpt) {
     826           5 :   i::FLAG_allow_natives_syntax = true;
     827           5 :   i::FLAG_block_concurrent_recompilation = true;
     828           5 :   LocalContext env;
     829          10 :   v8::HandleScope scope(env->GetIsolate());
     830             : 
     831           5 :   DebugEventCounter delegate;
     832           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     833             : 
     834             :   v8::Local<v8::Function> builtin;
     835             :   i::Handle<i::BreakPoint> bp;
     836             : 
     837             :   // === Test concurrent optimization ===
     838           5 :   break_point_hit_count = 0;
     839           5 :   builtin = CompileRun("Math.sin").As<v8::Function>();
     840             :   CompileRun("function test(x) { return 1 + Math.sin(x) }");
     841             :   // Trigger concurrent compile job. It is suspended until unblock.
     842             :   CompileRun(
     843             :       "test(0.5); test(0.6);"
     844             :       "%OptimizeFunctionOnNextCall(test, 'concurrent'); test(0.7);");
     845           5 :   CHECK_EQ(0, break_point_hit_count);
     846             : 
     847             :   // Run with breakpoint.
     848           5 :   bp = SetBreakPoint(builtin, 0);
     849             :   // Have the concurrent compile job finish now.
     850             :   CompileRun(
     851             :       "%UnblockConcurrentRecompilation();"
     852             :       "%GetOptimizationStatus(test, 'sync');");
     853             :   CompileRun("test(0.2);");
     854           5 :   CHECK_EQ(1, break_point_hit_count);
     855             : 
     856             :   // Run without breakpoints.
     857           5 :   ClearBreakPoint(bp);
     858             :   CompileRun("test(0.3);");
     859           5 :   CHECK_EQ(1, break_point_hit_count);
     860             : 
     861           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     862           5 :   CheckDebuggerUnloaded();
     863           5 : }
     864             : 
     865       28342 : TEST(BreakPointBuiltinTFOperator) {
     866           5 :   i::FLAG_allow_natives_syntax = true;
     867           5 :   LocalContext env;
     868          10 :   v8::HandleScope scope(env->GetIsolate());
     869             : 
     870           5 :   DebugEventCounter delegate;
     871           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     872             : 
     873             :   v8::Local<v8::Function> builtin;
     874             :   i::Handle<i::BreakPoint> bp;
     875             : 
     876             :   // === Test builtin represented as operator ===
     877           5 :   break_point_hit_count = 0;
     878           5 :   builtin = CompileRun("String.prototype.indexOf").As<v8::Function>();
     879             :   CompileRun("function test(x) { return 1 + 'foo'.indexOf(x) }");
     880             :   CompileRun(
     881             :       "test('a'); test('b');"
     882             :       "%OptimizeFunctionOnNextCall(test); test('c');");
     883           5 :   CHECK_EQ(0, break_point_hit_count);
     884             : 
     885             :   // Run with breakpoint.
     886           5 :   bp = SetBreakPoint(builtin, 0);
     887             :   CompileRun("'bar'.indexOf('x');");
     888           5 :   CHECK_EQ(1, break_point_hit_count);
     889             :   CompileRun("test('d');");
     890           5 :   CHECK_EQ(2, break_point_hit_count);
     891             : 
     892             :   // Re-optimize.
     893             :   CompileRun("%OptimizeFunctionOnNextCall(test);");
     894             :   CompileRun("test('e');");
     895           5 :   CHECK_EQ(3, break_point_hit_count);
     896             : 
     897             :   // Run without breakpoints.
     898           5 :   ClearBreakPoint(bp);
     899             :   CompileRun("test('f');");
     900           5 :   CHECK_EQ(3, break_point_hit_count);
     901             : 
     902           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     903           5 :   CheckDebuggerUnloaded();
     904           5 : }
     905             : 
     906       28342 : TEST(BreakPointBuiltinNewContext) {
     907           5 :   LocalContext env;
     908          10 :   v8::HandleScope scope(env->GetIsolate());
     909             : 
     910           5 :   DebugEventCounter delegate;
     911           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     912             : 
     913             :   v8::Local<v8::Function> builtin;
     914             :   i::Handle<i::BreakPoint> bp;
     915             : 
     916             : // === Test builtin from a new context ===
     917             : // This does not work with no-snapshot build.
     918             : #ifdef V8_USE_SNAPSHOT
     919           5 :   break_point_hit_count = 0;
     920           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
     921             :   CompileRun("'a'.repeat(10)");
     922           5 :   CHECK_EQ(0, break_point_hit_count);
     923             :   // Set breakpoint.
     924           5 :   bp = SetBreakPoint(builtin, 0);
     925             : 
     926             :   {
     927             :     // Create and use new context after breakpoint has been set.
     928           5 :     v8::HandleScope handle_scope(env->GetIsolate());
     929           5 :     v8::Local<v8::Context> new_context = v8::Context::New(env->GetIsolate());
     930             :     v8::Context::Scope context_scope(new_context);
     931             : 
     932             :     // Run with breakpoint.
     933             :     CompileRun("'b'.repeat(10)");
     934           5 :     CHECK_EQ(1, break_point_hit_count);
     935             : 
     936             :     CompileRun("'b'.repeat(10)");
     937           5 :     CHECK_EQ(2, break_point_hit_count);
     938             : 
     939             :     // Run without breakpoints.
     940           5 :     ClearBreakPoint(bp);
     941             :     CompileRun("'b'.repeat(10)");
     942          10 :     CHECK_EQ(2, break_point_hit_count);
     943             :   }
     944             : #endif
     945             : 
     946           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     947           5 :   CheckDebuggerUnloaded();
     948           5 : }
     949             : 
     950         810 : void NoOpFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
     951         405 :   args.GetReturnValue().Set(v8_num(2));
     952         405 : }
     953             : 
     954       28342 : TEST(BreakPointApiFunction) {
     955           5 :   LocalContext env;
     956          10 :   v8::HandleScope scope(env->GetIsolate());
     957             : 
     958           5 :   DebugEventCounter delegate;
     959           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
     960             : 
     961             :   i::Handle<i::BreakPoint> bp;
     962             : 
     963             :   v8::Local<v8::FunctionTemplate> function_template =
     964           5 :       v8::FunctionTemplate::New(env->GetIsolate(), NoOpFunctionCallback);
     965             : 
     966             :   v8::Local<v8::Function> function =
     967          10 :       function_template->GetFunction(env.local()).ToLocalChecked();
     968             : 
     969          25 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
     970             : 
     971             :   // === Test simple builtin ===
     972           5 :   break_point_hit_count = 0;
     973             : 
     974             :   // Run with breakpoint.
     975           5 :   bp = SetBreakPoint(function, 0);
     976           5 :   ExpectInt32("f()", 2);
     977           5 :   CHECK_EQ(1, break_point_hit_count);
     978             : 
     979           5 :   ExpectInt32("f()", 2);
     980           5 :   CHECK_EQ(2, break_point_hit_count);
     981             : 
     982             :   // Run without breakpoints.
     983           5 :   ClearBreakPoint(bp);
     984           5 :   ExpectInt32("f()", 2);
     985           5 :   CHECK_EQ(2, break_point_hit_count);
     986             : 
     987           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     988           5 :   CheckDebuggerUnloaded();
     989           5 : }
     990             : 
     991          30 : void GetWrapperCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
     992             :   args.GetReturnValue().Set(
     993             :       args[0]
     994             :           .As<v8::Object>()
     995          10 :           ->Get(args.GetIsolate()->GetCurrentContext(), args[1])
     996          10 :           .ToLocalChecked());
     997          10 : }
     998             : 
     999       28342 : TEST(BreakPointApiGetter) {
    1000           5 :   LocalContext env;
    1001          10 :   v8::HandleScope scope(env->GetIsolate());
    1002             : 
    1003           5 :   DebugEventCounter delegate;
    1004           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1005             : 
    1006             :   i::Handle<i::BreakPoint> bp;
    1007             : 
    1008             :   v8::Local<v8::FunctionTemplate> function_template =
    1009           5 :       v8::FunctionTemplate::New(env->GetIsolate(), NoOpFunctionCallback);
    1010             :   v8::Local<v8::FunctionTemplate> get_template =
    1011           5 :       v8::FunctionTemplate::New(env->GetIsolate(), GetWrapperCallback);
    1012             : 
    1013             :   v8::Local<v8::Function> function =
    1014          10 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1015             :   v8::Local<v8::Function> get =
    1016          10 :       get_template->GetFunction(env.local()).ToLocalChecked();
    1017             : 
    1018          25 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
    1019          25 :   env->Global()->Set(env.local(), v8_str("get_wrapper"), get).ToChecked();
    1020             :   CompileRun(
    1021             :       "var o = {};"
    1022             :       "Object.defineProperty(o, 'f', { get: f, enumerable: true });");
    1023             : 
    1024             :   // === Test API builtin as getter ===
    1025           5 :   break_point_hit_count = 0;
    1026             : 
    1027             :   // Run with breakpoint.
    1028           5 :   bp = SetBreakPoint(function, 0);
    1029             :   CompileRun("get_wrapper(o, 'f')");
    1030           5 :   CHECK_EQ(1, break_point_hit_count);
    1031             : 
    1032             :   CompileRun("o.f");
    1033           5 :   CHECK_EQ(2, break_point_hit_count);
    1034             : 
    1035             :   // Run without breakpoints.
    1036           5 :   ClearBreakPoint(bp);
    1037             :   CompileRun("get_wrapper(o, 'f', 2)");
    1038           5 :   CHECK_EQ(2, break_point_hit_count);
    1039             : 
    1040           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1041           5 :   CheckDebuggerUnloaded();
    1042           5 : }
    1043             : 
    1044          40 : void SetWrapperCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
    1045          60 :   CHECK(args[0]
    1046             :             .As<v8::Object>()
    1047             :             ->Set(args.GetIsolate()->GetCurrentContext(), args[1], args[2])
    1048             :             .FromJust());
    1049          20 : }
    1050             : 
    1051       28342 : TEST(BreakPointApiSetter) {
    1052           5 :   LocalContext env;
    1053          10 :   v8::HandleScope scope(env->GetIsolate());
    1054             : 
    1055           5 :   DebugEventCounter delegate;
    1056           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1057             : 
    1058             :   i::Handle<i::BreakPoint> bp;
    1059             : 
    1060             :   v8::Local<v8::FunctionTemplate> function_template =
    1061           5 :       v8::FunctionTemplate::New(env->GetIsolate(), NoOpFunctionCallback);
    1062             :   v8::Local<v8::FunctionTemplate> set_template =
    1063           5 :       v8::FunctionTemplate::New(env->GetIsolate(), SetWrapperCallback);
    1064             : 
    1065             :   v8::Local<v8::Function> function =
    1066          10 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1067             :   v8::Local<v8::Function> set =
    1068          10 :       set_template->GetFunction(env.local()).ToLocalChecked();
    1069             : 
    1070          25 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
    1071          25 :   env->Global()->Set(env.local(), v8_str("set_wrapper"), set).ToChecked();
    1072             : 
    1073             :   CompileRun(
    1074             :       "var o = {};"
    1075             :       "Object.defineProperty(o, 'f', { set: f, enumerable: true });");
    1076             : 
    1077             :   // === Test API builtin as setter ===
    1078           5 :   break_point_hit_count = 0;
    1079             : 
    1080             :   // Run with breakpoint.
    1081           5 :   bp = SetBreakPoint(function, 0);
    1082             : 
    1083             :   CompileRun("o.f = 3");
    1084           5 :   CHECK_EQ(1, break_point_hit_count);
    1085             : 
    1086             :   CompileRun("set_wrapper(o, 'f', 2)");
    1087           5 :   CHECK_EQ(2, break_point_hit_count);
    1088             : 
    1089             :   // Run without breakpoints.
    1090           5 :   ClearBreakPoint(bp);
    1091             :   CompileRun("o.f = 3");
    1092           5 :   CHECK_EQ(2, break_point_hit_count);
    1093             : 
    1094             :   // === Test API builtin as setter, with condition ===
    1095           5 :   break_point_hit_count = 0;
    1096             : 
    1097             :   // Run with breakpoint.
    1098           5 :   bp = SetBreakPoint(function, 0, "arguments[0] == 3");
    1099             :   CompileRun("set_wrapper(o, 'f', 2)");
    1100           5 :   CHECK_EQ(0, break_point_hit_count);
    1101             : 
    1102             :   CompileRun("set_wrapper(o, 'f', 3)");
    1103           5 :   CHECK_EQ(1, break_point_hit_count);
    1104             : 
    1105             :   CompileRun("o.f = 3");
    1106           5 :   CHECK_EQ(2, break_point_hit_count);
    1107             : 
    1108             :   // Run without breakpoints.
    1109           5 :   ClearBreakPoint(bp);
    1110             :   CompileRun("set_wrapper(o, 'f', 2)");
    1111           5 :   CHECK_EQ(2, break_point_hit_count);
    1112             : 
    1113           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1114           5 :   CheckDebuggerUnloaded();
    1115           5 : }
    1116             : 
    1117       28342 : TEST(BreakPointApiAccessor) {
    1118           5 :   LocalContext env;
    1119          10 :   v8::HandleScope scope(env->GetIsolate());
    1120             : 
    1121           5 :   DebugEventCounter delegate;
    1122           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1123             : 
    1124             :   i::Handle<i::BreakPoint> bp;
    1125             : 
    1126             :   // Create 'foo' class, with a hidden property.
    1127             :   v8::Local<v8::ObjectTemplate> obj_template =
    1128           5 :       v8::ObjectTemplate::New(env->GetIsolate());
    1129             :   v8::Local<v8::FunctionTemplate> accessor_template =
    1130           5 :       v8::FunctionTemplate::New(env->GetIsolate(), NoOpFunctionCallback);
    1131             :   obj_template->SetAccessorProperty(v8_str("f"), accessor_template,
    1132          10 :                                     accessor_template);
    1133             :   v8::Local<v8::Object> obj =
    1134           5 :       obj_template->NewInstance(env.local()).ToLocalChecked();
    1135          25 :   env->Global()->Set(env.local(), v8_str("o"), obj).ToChecked();
    1136             : 
    1137             :   v8::Local<v8::Function> function =
    1138             :       CompileRun("Object.getOwnPropertyDescriptor(o, 'f').set")
    1139           5 :           .As<v8::Function>();
    1140             : 
    1141             :   // === Test API accessor ===
    1142           5 :   break_point_hit_count = 0;
    1143             : 
    1144             :   CompileRun("function get_loop() { for (var i = 0; i < 10; i++) o.f }");
    1145             :   CompileRun("function set_loop() { for (var i = 0; i < 10; i++) o.f = 2 }");
    1146             : 
    1147             :   CompileRun("get_loop(); set_loop();");  // Initialize ICs.
    1148             : 
    1149             :   // Run with breakpoint.
    1150           5 :   bp = SetBreakPoint(function, 0);
    1151             : 
    1152             :   CompileRun("o.f = 3");
    1153           5 :   CHECK_EQ(1, break_point_hit_count);
    1154             : 
    1155             :   CompileRun("o.f");
    1156           5 :   CHECK_EQ(2, break_point_hit_count);
    1157             : 
    1158             :   CompileRun("for (var i = 0; i < 10; i++) o.f");
    1159           5 :   CHECK_EQ(12, break_point_hit_count);
    1160             : 
    1161             :   CompileRun("get_loop();");
    1162           5 :   CHECK_EQ(22, break_point_hit_count);
    1163             : 
    1164             :   CompileRun("for (var i = 0; i < 10; i++) o.f = 2");
    1165           5 :   CHECK_EQ(32, break_point_hit_count);
    1166             : 
    1167             :   CompileRun("set_loop();");
    1168           5 :   CHECK_EQ(42, break_point_hit_count);
    1169             : 
    1170             :   // Run without breakpoints.
    1171           5 :   ClearBreakPoint(bp);
    1172             :   CompileRun("o.f = 3");
    1173             :   CompileRun("o.f");
    1174           5 :   CHECK_EQ(42, break_point_hit_count);
    1175             : 
    1176           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1177           5 :   CheckDebuggerUnloaded();
    1178           5 : }
    1179             : 
    1180       28342 : TEST(BreakPointInlineApiFunction) {
    1181           5 :   i::FLAG_allow_natives_syntax = true;
    1182           5 :   LocalContext env;
    1183          10 :   v8::HandleScope scope(env->GetIsolate());
    1184             : 
    1185           5 :   DebugEventCounter delegate;
    1186           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1187             : 
    1188             :   i::Handle<i::BreakPoint> bp;
    1189             : 
    1190             :   v8::Local<v8::FunctionTemplate> function_template =
    1191           5 :       v8::FunctionTemplate::New(env->GetIsolate(), NoOpFunctionCallback);
    1192             : 
    1193             :   v8::Local<v8::Function> function =
    1194          10 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1195             : 
    1196          25 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
    1197             :   CompileRun("function g() { return 1 +  f(); }");
    1198             : 
    1199             :   // === Test simple builtin ===
    1200           5 :   break_point_hit_count = 0;
    1201             : 
    1202             :   // Run with breakpoint.
    1203           5 :   bp = SetBreakPoint(function, 0);
    1204           5 :   ExpectInt32("g()", 3);
    1205           5 :   CHECK_EQ(1, break_point_hit_count);
    1206             : 
    1207           5 :   ExpectInt32("g()", 3);
    1208           5 :   CHECK_EQ(2, break_point_hit_count);
    1209             : 
    1210             :   CompileRun("%OptimizeFunctionOnNextCall(g)");
    1211           5 :   ExpectInt32("g()", 3);
    1212           5 :   CHECK_EQ(3, break_point_hit_count);
    1213             : 
    1214             :   // Run without breakpoints.
    1215           5 :   ClearBreakPoint(bp);
    1216           5 :   ExpectInt32("g()", 3);
    1217           5 :   CHECK_EQ(3, break_point_hit_count);
    1218             : 
    1219           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1220           5 :   CheckDebuggerUnloaded();
    1221           5 : }
    1222             : 
    1223             : // Test that a break point can be set at a return store location.
    1224       28342 : TEST(BreakPointConditionBuiltin) {
    1225           5 :   i::FLAG_allow_natives_syntax = true;
    1226           5 :   i::FLAG_block_concurrent_recompilation = true;
    1227           5 :   LocalContext env;
    1228          10 :   v8::HandleScope scope(env->GetIsolate());
    1229             : 
    1230           5 :   DebugEventCounter delegate;
    1231           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1232             :   v8::Local<v8::Function> builtin;
    1233             :   i::Handle<i::BreakPoint> bp;
    1234             : 
    1235             :   // === Test global variable ===
    1236           5 :   break_point_hit_count = 0;
    1237           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1238             :   CompileRun("var condition = false");
    1239             :   CompileRun("'a'.repeat(10)");
    1240           5 :   CHECK_EQ(0, break_point_hit_count);
    1241             : 
    1242             :   // Run with breakpoint.
    1243           5 :   bp = SetBreakPoint(builtin, 0, "condition == true");
    1244             :   CompileRun("'b'.repeat(10)");
    1245           5 :   CHECK_EQ(0, break_point_hit_count);
    1246             : 
    1247             :   CompileRun("condition = true");
    1248             :   CompileRun("'b'.repeat(10)");
    1249           5 :   CHECK_EQ(1, break_point_hit_count);
    1250             : 
    1251             :   // Run without breakpoints.
    1252           5 :   ClearBreakPoint(bp);
    1253             :   CompileRun("'b'.repeat(10)");
    1254           5 :   CHECK_EQ(1, break_point_hit_count);
    1255             : 
    1256             :   // === Test arguments ===
    1257           5 :   break_point_hit_count = 0;
    1258           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1259             :   CompileRun("function f(x) { return 'a'.repeat(x * 2); }");
    1260           5 :   CHECK_EQ(0, break_point_hit_count);
    1261             : 
    1262             :   // Run with breakpoint.
    1263           5 :   bp = SetBreakPoint(builtin, 0, "arguments[0] == 20");
    1264           5 :   ExpectString("f(5)", "aaaaaaaaaa");
    1265           5 :   CHECK_EQ(0, break_point_hit_count);
    1266             : 
    1267           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1268           5 :   CHECK_EQ(1, break_point_hit_count);
    1269             : 
    1270             :   // Run without breakpoints.
    1271           5 :   ClearBreakPoint(bp);
    1272           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1273           5 :   CHECK_EQ(1, break_point_hit_count);
    1274             : 
    1275             :   // === Test adapted arguments ===
    1276           5 :   break_point_hit_count = 0;
    1277           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1278             :   CompileRun("function f(x) { return 'a'.repeat(x * 2, x); }");
    1279           5 :   CHECK_EQ(0, break_point_hit_count);
    1280             : 
    1281             :   // Run with breakpoint.
    1282             :   bp = SetBreakPoint(builtin, 0,
    1283           5 :                      "arguments[1] == 10 && arguments[2] == undefined");
    1284           5 :   ExpectString("f(5)", "aaaaaaaaaa");
    1285           5 :   CHECK_EQ(0, break_point_hit_count);
    1286             : 
    1287           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1288           5 :   CHECK_EQ(1, break_point_hit_count);
    1289             : 
    1290             :   // Run without breakpoints.
    1291           5 :   ClearBreakPoint(bp);
    1292           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1293           5 :   CHECK_EQ(1, break_point_hit_count);
    1294             : 
    1295             :   // === Test var-arg builtins ===
    1296           5 :   break_point_hit_count = 0;
    1297           5 :   builtin = CompileRun("String.fromCharCode").As<v8::Function>();
    1298             :   CompileRun("function f() { return String.fromCharCode(1, 2, 3); }");
    1299           5 :   CHECK_EQ(0, break_point_hit_count);
    1300             : 
    1301             :   // Run with breakpoint.
    1302           5 :   bp = SetBreakPoint(builtin, 0, "arguments.length == 3 && arguments[1] == 2");
    1303             :   CompileRun("f(1, 2, 3)");
    1304           5 :   CHECK_EQ(1, break_point_hit_count);
    1305             : 
    1306             :   // Run without breakpoints.
    1307           5 :   ClearBreakPoint(bp);
    1308             :   CompileRun("f(1, 2, 3)");
    1309           5 :   CHECK_EQ(1, break_point_hit_count);
    1310             : 
    1311             :   // === Test rest arguments ===
    1312           5 :   break_point_hit_count = 0;
    1313           5 :   builtin = CompileRun("String.fromCharCode").As<v8::Function>();
    1314             :   CompileRun("function f(...args) { return String.fromCharCode(...args); }");
    1315           5 :   CHECK_EQ(0, break_point_hit_count);
    1316             : 
    1317             :   // Run with breakpoint.
    1318           5 :   bp = SetBreakPoint(builtin, 0, "arguments.length == 3 && arguments[1] == 2");
    1319             :   CompileRun("f(1, 2, 3)");
    1320           5 :   CHECK_EQ(1, break_point_hit_count);
    1321             : 
    1322           5 :   ClearBreakPoint(bp);
    1323             :   CompileRun("f(1, 3, 3)");
    1324           5 :   CHECK_EQ(1, break_point_hit_count);
    1325             : 
    1326             :   // Run without breakpoints.
    1327           5 :   ClearBreakPoint(bp);
    1328             :   CompileRun("f(1, 2, 3)");
    1329           5 :   CHECK_EQ(1, break_point_hit_count);
    1330             : 
    1331             :   // === Test receiver ===
    1332           5 :   break_point_hit_count = 0;
    1333           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1334             :   CompileRun("function f(x) { return x.repeat(10); }");
    1335           5 :   CHECK_EQ(0, break_point_hit_count);
    1336             : 
    1337             :   // Run with breakpoint.
    1338           5 :   bp = SetBreakPoint(builtin, 0, "this == 'a'");
    1339           5 :   ExpectString("f('b')", "bbbbbbbbbb");
    1340           5 :   CHECK_EQ(0, break_point_hit_count);
    1341             : 
    1342           5 :   ExpectString("f('a')", "aaaaaaaaaa");
    1343           5 :   CHECK_EQ(1, break_point_hit_count);
    1344             : 
    1345             :   // Run without breakpoints.
    1346           5 :   ClearBreakPoint(bp);
    1347           5 :   ExpectString("f('a')", "aaaaaaaaaa");
    1348           5 :   CHECK_EQ(1, break_point_hit_count);
    1349             : 
    1350           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1351           5 :   CheckDebuggerUnloaded();
    1352           5 : }
    1353             : 
    1354       28342 : TEST(BreakPointInlining) {
    1355           5 :   i::FLAG_allow_natives_syntax = true;
    1356           5 :   break_point_hit_count = 0;
    1357           5 :   LocalContext env;
    1358          10 :   v8::HandleScope scope(env->GetIsolate());
    1359             : 
    1360           5 :   DebugEventCounter delegate;
    1361           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1362             : 
    1363           5 :   break_point_hit_count = 0;
    1364             :   v8::Local<v8::Function> inlinee =
    1365           5 :       CompileRun("function f(x) { return x*2; } f").As<v8::Function>();
    1366             :   CompileRun("function test(x) { return 1 + f(x) }");
    1367             :   CompileRun(
    1368             :       "test(0.5); test(0.6);"
    1369             :       "%OptimizeFunctionOnNextCall(test); test(0.7);");
    1370           5 :   CHECK_EQ(0, break_point_hit_count);
    1371             : 
    1372             :   // Run with breakpoint.
    1373           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(inlinee, 0);
    1374             :   CompileRun("f(0.1);");
    1375           5 :   CHECK_EQ(1, break_point_hit_count);
    1376             :   CompileRun("test(0.2);");
    1377           5 :   CHECK_EQ(2, break_point_hit_count);
    1378             : 
    1379             :   // Re-optimize.
    1380             :   CompileRun("%OptimizeFunctionOnNextCall(test);");
    1381             :   CompileRun("test(0.3);");
    1382           5 :   CHECK_EQ(3, break_point_hit_count);
    1383             : 
    1384             :   // Run without breakpoints.
    1385           5 :   ClearBreakPoint(bp);
    1386             :   CompileRun("test(0.3);");
    1387           5 :   CHECK_EQ(3, break_point_hit_count);
    1388             : 
    1389           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1390           5 :   CheckDebuggerUnloaded();
    1391           5 : }
    1392             : 
    1393          25 : static void CallWithBreakPoints(v8::Local<v8::Context> context,
    1394             :                                 v8::Local<v8::Object> recv,
    1395             :                                 v8::Local<v8::Function> f,
    1396             :                                 int break_point_count, int call_count) {
    1397          25 :   break_point_hit_count = 0;
    1398         450 :   for (int i = 0; i < call_count; i++) {
    1399         800 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1400         400 :     CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
    1401             :   }
    1402          25 : }
    1403             : 
    1404             : 
    1405             : // Test GC during break point processing.
    1406       28342 : TEST(GCDuringBreakPointProcessing) {
    1407           5 :   break_point_hit_count = 0;
    1408           5 :   LocalContext env;
    1409          10 :   v8::HandleScope scope(env->GetIsolate());
    1410           5 :   v8::Local<v8::Context> context = env.local();
    1411             : 
    1412           5 :   DebugEventBreakPointCollectGarbage delegate;
    1413           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1414             :   v8::Local<v8::Function> foo;
    1415             : 
    1416             :   // Test IC store break point with garbage collection.
    1417           5 :   foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
    1418           5 :   SetBreakPoint(foo, 0);
    1419           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 10);
    1420             : 
    1421             :   // Test IC load break point with garbage collection.
    1422           5 :   foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
    1423           5 :   SetBreakPoint(foo, 0);
    1424           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 10);
    1425             : 
    1426             :   // Test IC call break point with garbage collection.
    1427           5 :   foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
    1428           5 :   SetBreakPoint(foo, 0);
    1429           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 10);
    1430             : 
    1431             :   // Test return break point with garbage collection.
    1432           5 :   foo = CompileFunction(&env, "function foo(){}", "foo");
    1433           5 :   SetBreakPoint(foo, 0);
    1434           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 25);
    1435             : 
    1436             :   // Test debug break slot break point with garbage collection.
    1437           5 :   foo = CompileFunction(&env, "function foo(){var a;}", "foo");
    1438           5 :   SetBreakPoint(foo, 0);
    1439           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 25);
    1440             : 
    1441           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1442           5 :   CheckDebuggerUnloaded();
    1443           5 : }
    1444             : 
    1445             : 
    1446             : // Call the function three times with different garbage collections in between
    1447             : // and make sure that the break point survives.
    1448          25 : static void CallAndGC(v8::Local<v8::Context> context,
    1449             :                       v8::Local<v8::Object> recv, v8::Local<v8::Function> f) {
    1450          25 :   break_point_hit_count = 0;
    1451             : 
    1452         125 :   for (int i = 0; i < 3; i++) {
    1453             :     // Call function.
    1454         150 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1455          75 :     CHECK_EQ(1 + i * 3, break_point_hit_count);
    1456             : 
    1457             :     // Scavenge and call function.
    1458          75 :     CcTest::CollectGarbage(v8::internal::NEW_SPACE);
    1459         150 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1460          75 :     CHECK_EQ(2 + i * 3, break_point_hit_count);
    1461             : 
    1462             :     // Mark sweep (and perhaps compact) and call function.
    1463          75 :     CcTest::CollectAllGarbage();
    1464         150 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1465          75 :     CHECK_EQ(3 + i * 3, break_point_hit_count);
    1466             :   }
    1467          25 : }
    1468             : 
    1469             : 
    1470             : // Test that a break point can be set at a return store location.
    1471       28342 : TEST(BreakPointSurviveGC) {
    1472           5 :   break_point_hit_count = 0;
    1473           5 :   LocalContext env;
    1474          10 :   v8::HandleScope scope(env->GetIsolate());
    1475           5 :   v8::Local<v8::Context> context = env.local();
    1476             : 
    1477           5 :   DebugEventCounter delegate;
    1478           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1479             :   v8::Local<v8::Function> foo;
    1480             : 
    1481             :   // Test IC store break point with garbage collection.
    1482             :   {
    1483           5 :     CompileFunction(&env, "function foo(){}", "foo");
    1484           5 :     foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
    1485           5 :     SetBreakPoint(foo, 0);
    1486             :   }
    1487           5 :   CallAndGC(context, env->Global(), foo);
    1488             : 
    1489             :   // Test IC load break point with garbage collection.
    1490             :   {
    1491           5 :     CompileFunction(&env, "function foo(){}", "foo");
    1492           5 :     foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
    1493           5 :     SetBreakPoint(foo, 0);
    1494             :   }
    1495           5 :   CallAndGC(context, env->Global(), foo);
    1496             : 
    1497             :   // Test IC call break point with garbage collection.
    1498             :   {
    1499           5 :     CompileFunction(&env, "function foo(){}", "foo");
    1500             :     foo = CompileFunction(&env,
    1501             :                           "function bar(){};function foo(){bar();}",
    1502           5 :                           "foo");
    1503           5 :     SetBreakPoint(foo, 0);
    1504             :   }
    1505           5 :   CallAndGC(context, env->Global(), foo);
    1506             : 
    1507             :   // Test return break point with garbage collection.
    1508             :   {
    1509           5 :     CompileFunction(&env, "function foo(){}", "foo");
    1510           5 :     foo = CompileFunction(&env, "function foo(){}", "foo");
    1511           5 :     SetBreakPoint(foo, 0);
    1512             :   }
    1513           5 :   CallAndGC(context, env->Global(), foo);
    1514             : 
    1515             :   // Test non IC break point with garbage collection.
    1516             :   {
    1517           5 :     CompileFunction(&env, "function foo(){}", "foo");
    1518           5 :     foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
    1519           5 :     SetBreakPoint(foo, 0);
    1520             :   }
    1521           5 :   CallAndGC(context, env->Global(), foo);
    1522             : 
    1523           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1524           5 :   CheckDebuggerUnloaded();
    1525           5 : }
    1526             : 
    1527             : // Test that the debugger statement causes a break.
    1528       28342 : TEST(DebuggerStatement) {
    1529           5 :   break_point_hit_count = 0;
    1530           5 :   LocalContext env;
    1531          10 :   v8::HandleScope scope(env->GetIsolate());
    1532           5 :   DebugEventCounter delegate;
    1533           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1534           5 :   v8::Local<v8::Context> context = env.local();
    1535             :   v8::Script::Compile(context,
    1536           5 :                       v8_str(env->GetIsolate(), "function bar(){debugger}"))
    1537           5 :       .ToLocalChecked()
    1538             :       ->Run(context)
    1539           5 :       .ToLocalChecked();
    1540             :   v8::Script::Compile(
    1541           5 :       context, v8_str(env->GetIsolate(), "function foo(){debugger;debugger;}"))
    1542           5 :       .ToLocalChecked()
    1543             :       ->Run(context)
    1544           5 :       .ToLocalChecked();
    1545             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
    1546             :       env->Global()
    1547          15 :           ->Get(context, v8_str(env->GetIsolate(), "foo"))
    1548           5 :           .ToLocalChecked());
    1549             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
    1550             :       env->Global()
    1551          15 :           ->Get(context, v8_str(env->GetIsolate(), "bar"))
    1552           5 :           .ToLocalChecked());
    1553             : 
    1554             :   // Run function with debugger statement
    1555          15 :   bar->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1556           5 :   CHECK_EQ(1, break_point_hit_count);
    1557             : 
    1558             :   // Run function with two debugger statement
    1559          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1560           5 :   CHECK_EQ(3, break_point_hit_count);
    1561             : 
    1562           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1563           5 :   CheckDebuggerUnloaded();
    1564           5 : }
    1565             : 
    1566             : 
    1567             : // Test setting a breakpoint on the debugger statement.
    1568       28342 : TEST(DebuggerStatementBreakpoint) {
    1569           5 :     break_point_hit_count = 0;
    1570           5 :     LocalContext env;
    1571          10 :     v8::HandleScope scope(env->GetIsolate());
    1572           5 :     v8::Local<v8::Context> context = env.local();
    1573           5 :     DebugEventCounter delegate;
    1574           5 :     v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1575             :     v8::Script::Compile(context,
    1576           5 :                         v8_str(env->GetIsolate(), "function foo(){debugger;}"))
    1577           5 :         .ToLocalChecked()
    1578             :         ->Run(context)
    1579           5 :         .ToLocalChecked();
    1580             :     v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
    1581             :         env->Global()
    1582          15 :             ->Get(context, v8_str(env->GetIsolate(), "foo"))
    1583           5 :             .ToLocalChecked());
    1584             : 
    1585             :     // The debugger statement triggers breakpoint hit
    1586          15 :     foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1587           5 :     CHECK_EQ(1, break_point_hit_count);
    1588             : 
    1589           5 :     i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
    1590             : 
    1591             :     // Set breakpoint does not duplicate hits
    1592          15 :     foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1593           5 :     CHECK_EQ(2, break_point_hit_count);
    1594             : 
    1595           5 :     ClearBreakPoint(bp);
    1596           5 :     v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1597           5 :     CheckDebuggerUnloaded();
    1598           5 : }
    1599             : 
    1600             : 
    1601             : // Test that the conditional breakpoints work event if code generation from
    1602             : // strings is prohibited in the debugee context.
    1603       28342 : TEST(ConditionalBreakpointWithCodeGenerationDisallowed) {
    1604           5 :   LocalContext env;
    1605          10 :   v8::HandleScope scope(env->GetIsolate());
    1606             : 
    1607           5 :   DebugEventCounter delegate;
    1608           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1609             : 
    1610           5 :   v8::Local<v8::Context> context = env.local();
    1611             :   v8::Local<v8::Function> foo = CompileFunction(&env,
    1612             :     "function foo(x) {\n"
    1613             :     "  var s = 'String value2';\n"
    1614             :     "  return s + x;\n"
    1615             :     "}",
    1616           5 :     "foo");
    1617             : 
    1618             :   // Set conditional breakpoint with condition 'true'.
    1619           5 :   SetBreakPoint(foo, 4, "true");
    1620             : 
    1621           5 :   break_point_hit_count = 0;
    1622           5 :   env->AllowCodeGenerationFromStrings(false);
    1623          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1624           5 :   CHECK_EQ(1, break_point_hit_count);
    1625             : 
    1626           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1627           5 :   CheckDebuggerUnloaded();
    1628           5 : }
    1629             : 
    1630             : 
    1631             : // Simple test of the stepping mechanism using only store ICs.
    1632       28342 : TEST(DebugStepLinear) {
    1633           5 :   LocalContext env;
    1634          10 :   v8::HandleScope scope(env->GetIsolate());
    1635             : 
    1636             :   // Create a function for testing stepping.
    1637             :   v8::Local<v8::Function> foo = CompileFunction(&env,
    1638             :                                                 "function foo(){a=1;b=1;c=1;}",
    1639           5 :                                                 "foo");
    1640             : 
    1641             :   // Run foo to allow it to get optimized.
    1642             :   CompileRun("a=0; b=0; c=0; foo();");
    1643             : 
    1644             :   // Register a debug event listener which steps and counts.
    1645           5 :   DebugEventCounter run_step;
    1646           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1647             : 
    1648           5 :   SetBreakPoint(foo, 3);
    1649             : 
    1650             :   run_step.set_step_action(StepIn);
    1651           5 :   break_point_hit_count = 0;
    1652           5 :   v8::Local<v8::Context> context = env.local();
    1653          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1654             : 
    1655             :   // With stepping all break locations are hit.
    1656           5 :   CHECK_EQ(4, break_point_hit_count);
    1657             : 
    1658           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1659             :   CheckDebuggerUnloaded();
    1660             : 
    1661             :   // Register a debug event listener which just counts.
    1662           5 :   DebugEventCounter delegate;
    1663           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1664             : 
    1665           5 :   SetBreakPoint(foo, 3);
    1666           5 :   break_point_hit_count = 0;
    1667          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1668             : 
    1669             :   // Without stepping only active break points are hit.
    1670           5 :   CHECK_EQ(1, break_point_hit_count);
    1671             : 
    1672           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1673           5 :   CheckDebuggerUnloaded();
    1674           5 : }
    1675             : 
    1676             : 
    1677             : // Test of the stepping mechanism for keyed load in a loop.
    1678       28342 : TEST(DebugStepKeyedLoadLoop) {
    1679           5 :   LocalContext env;
    1680          10 :   v8::HandleScope scope(env->GetIsolate());
    1681             : 
    1682             :   // Register a debug event listener which steps and counts.
    1683           5 :   DebugEventCounter run_step;
    1684           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1685             : 
    1686             :   // Create a function for testing stepping of keyed load. The statement 'y=1'
    1687             :   // is there to have more than one breakable statement in the loop, TODO(315).
    1688             :   v8::Local<v8::Function> foo = CompileFunction(
    1689             :       &env,
    1690             :       "function foo(a) {\n"
    1691             :       "  var x;\n"
    1692             :       "  var len = a.length;\n"
    1693             :       "  for (var i = 0; i < len; i++) {\n"
    1694             :       "    y = 1;\n"
    1695             :       "    x = a[i];\n"
    1696             :       "  }\n"
    1697             :       "}\n"
    1698             :       "y=0\n",
    1699           5 :       "foo");
    1700             : 
    1701           5 :   v8::Local<v8::Context> context = env.local();
    1702             :   // Create array [0,1,2,3,4,5,6,7,8,9]
    1703           5 :   v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
    1704          55 :   for (int i = 0; i < 10; i++) {
    1705         250 :     CHECK(a->Set(context, v8::Number::New(env->GetIsolate(), i),
    1706             :                  v8::Number::New(env->GetIsolate(), i))
    1707             :               .FromJust());
    1708             :   }
    1709             : 
    1710             :   // Call function without any break points to ensure inlining is in place.
    1711             :   const int kArgc = 1;
    1712             :   v8::Local<v8::Value> args[kArgc] = {a};
    1713          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1714             : 
    1715             :   // Set up break point and step through the function.
    1716           5 :   SetBreakPoint(foo, 3);
    1717             :   run_step.set_step_action(StepNext);
    1718           5 :   break_point_hit_count = 0;
    1719          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1720             : 
    1721             :   // With stepping all break locations are hit.
    1722           5 :   CHECK_EQ(44, break_point_hit_count);
    1723             : 
    1724           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1725           5 :   CheckDebuggerUnloaded();
    1726           5 : }
    1727             : 
    1728             : 
    1729             : // Test of the stepping mechanism for keyed store in a loop.
    1730       28342 : TEST(DebugStepKeyedStoreLoop) {
    1731           5 :   LocalContext env;
    1732          10 :   v8::HandleScope scope(env->GetIsolate());
    1733             : 
    1734             :   // Register a debug event listener which steps and counts.
    1735           5 :   DebugEventCounter run_step;
    1736           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1737             : 
    1738             :   // Create a function for testing stepping of keyed store. The statement 'y=1'
    1739             :   // is there to have more than one breakable statement in the loop, TODO(315).
    1740             :   v8::Local<v8::Function> foo = CompileFunction(
    1741             :       &env,
    1742             :       "function foo(a) {\n"
    1743             :       "  var len = a.length;\n"
    1744             :       "  for (var i = 0; i < len; i++) {\n"
    1745             :       "    y = 1;\n"
    1746             :       "    a[i] = 42;\n"
    1747             :       "  }\n"
    1748             :       "}\n"
    1749             :       "y=0\n",
    1750           5 :       "foo");
    1751             : 
    1752           5 :   v8::Local<v8::Context> context = env.local();
    1753             :   // Create array [0,1,2,3,4,5,6,7,8,9]
    1754           5 :   v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
    1755          55 :   for (int i = 0; i < 10; i++) {
    1756         250 :     CHECK(a->Set(context, v8::Number::New(env->GetIsolate(), i),
    1757             :                  v8::Number::New(env->GetIsolate(), i))
    1758             :               .FromJust());
    1759             :   }
    1760             : 
    1761             :   // Call function without any break points to ensure inlining is in place.
    1762             :   const int kArgc = 1;
    1763             :   v8::Local<v8::Value> args[kArgc] = {a};
    1764          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1765             : 
    1766             :   // Set up break point and step through the function.
    1767           5 :   SetBreakPoint(foo, 3);
    1768             :   run_step.set_step_action(StepNext);
    1769           5 :   break_point_hit_count = 0;
    1770          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1771             : 
    1772             :   // With stepping all break locations are hit.
    1773           5 :   CHECK_EQ(44, break_point_hit_count);
    1774             : 
    1775           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1776           5 :   CheckDebuggerUnloaded();
    1777           5 : }
    1778             : 
    1779             : 
    1780             : // Test of the stepping mechanism for named load in a loop.
    1781       28342 : TEST(DebugStepNamedLoadLoop) {
    1782           5 :   LocalContext env;
    1783          10 :   v8::HandleScope scope(env->GetIsolate());
    1784             : 
    1785             :   // Register a debug event listener which steps and counts.
    1786           5 :   DebugEventCounter run_step;
    1787           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1788             : 
    1789           5 :   v8::Local<v8::Context> context = env.local();
    1790             :   // Create a function for testing stepping of named load.
    1791             :   v8::Local<v8::Function> foo = CompileFunction(
    1792             :       &env,
    1793             :       "function foo() {\n"
    1794             :           "  var a = [];\n"
    1795             :           "  var s = \"\";\n"
    1796             :           "  for (var i = 0; i < 10; i++) {\n"
    1797             :           "    var v = new V(i, i + 1);\n"
    1798             :           "    v.y;\n"
    1799             :           "    a.length;\n"  // Special case: array length.
    1800             :           "    s.length;\n"  // Special case: string length.
    1801             :           "  }\n"
    1802             :           "}\n"
    1803             :           "function V(x, y) {\n"
    1804             :           "  this.x = x;\n"
    1805             :           "  this.y = y;\n"
    1806             :           "}\n",
    1807           5 :           "foo");
    1808             : 
    1809             :   // Call function without any break points to ensure inlining is in place.
    1810          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1811             : 
    1812             :   // Set up break point and step through the function.
    1813           5 :   SetBreakPoint(foo, 4);
    1814             :   run_step.set_step_action(StepNext);
    1815           5 :   break_point_hit_count = 0;
    1816          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1817             : 
    1818             :   // With stepping all break locations are hit.
    1819           5 :   CHECK_EQ(65, break_point_hit_count);
    1820             : 
    1821           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1822           5 :   CheckDebuggerUnloaded();
    1823           5 : }
    1824             : 
    1825             : 
    1826           5 : static void DoDebugStepNamedStoreLoop(int expected) {
    1827           5 :   LocalContext env;
    1828          10 :   v8::HandleScope scope(env->GetIsolate());
    1829             : 
    1830             :   // Register a debug event listener which steps and counts.
    1831           5 :   DebugEventCounter run_step;
    1832           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1833             : 
    1834             :   // Create a function for testing stepping of named store.
    1835           5 :   v8::Local<v8::Context> context = env.local();
    1836             :   v8::Local<v8::Function> foo = CompileFunction(
    1837             :       &env,
    1838             :       "function foo() {\n"
    1839             :           "  var a = {a:1};\n"
    1840             :           "  for (var i = 0; i < 10; i++) {\n"
    1841             :           "    a.a = 2\n"
    1842             :           "  }\n"
    1843             :           "}\n",
    1844           5 :           "foo");
    1845             : 
    1846             :   // Call function without any break points to ensure inlining is in place.
    1847          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1848             : 
    1849             :   // Set up break point and step through the function.
    1850           5 :   SetBreakPoint(foo, 3);
    1851             :   run_step.set_step_action(StepNext);
    1852           5 :   break_point_hit_count = 0;
    1853          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1854             : 
    1855             :   // With stepping all expected break locations are hit.
    1856           5 :   CHECK_EQ(expected, break_point_hit_count);
    1857             : 
    1858           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1859           5 :   CheckDebuggerUnloaded();
    1860           5 : }
    1861             : 
    1862             : 
    1863             : // Test of the stepping mechanism for named load in a loop.
    1864       28342 : TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(34); }
    1865             : 
    1866             : // Test the stepping mechanism with different ICs.
    1867       28342 : TEST(DebugStepLinearMixedICs) {
    1868           5 :   LocalContext env;
    1869          10 :   v8::HandleScope scope(env->GetIsolate());
    1870             : 
    1871             :   // Register a debug event listener which steps and counts.
    1872           5 :   DebugEventCounter run_step;
    1873           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1874             : 
    1875           5 :   v8::Local<v8::Context> context = env.local();
    1876             :   // Create a function for testing stepping.
    1877             :   v8::Local<v8::Function> foo = CompileFunction(&env,
    1878             :       "function bar() {};"
    1879             :       "function foo() {"
    1880             :       "  var x;"
    1881             :       "  var index='name';"
    1882             :       "  var y = {};"
    1883           5 :       "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
    1884             : 
    1885             :   // Run functions to allow them to get optimized.
    1886             :   CompileRun("a=0; b=0; bar(); foo();");
    1887             : 
    1888           5 :   SetBreakPoint(foo, 0);
    1889             : 
    1890             :   run_step.set_step_action(StepIn);
    1891           5 :   break_point_hit_count = 0;
    1892          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1893             : 
    1894             :   // With stepping all break locations are hit.
    1895           5 :   CHECK_EQ(10, break_point_hit_count);
    1896             : 
    1897           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1898             :   CheckDebuggerUnloaded();
    1899             : 
    1900             :   // Register a debug event listener which just counts.
    1901           5 :   DebugEventCounter delegate;
    1902           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1903             : 
    1904           5 :   SetBreakPoint(foo, 0);
    1905           5 :   break_point_hit_count = 0;
    1906          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1907             : 
    1908             :   // Without stepping only active break points are hit.
    1909           5 :   CHECK_EQ(1, break_point_hit_count);
    1910             : 
    1911           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1912           5 :   CheckDebuggerUnloaded();
    1913           5 : }
    1914             : 
    1915             : 
    1916       28342 : TEST(DebugStepDeclarations) {
    1917           5 :   LocalContext env;
    1918          10 :   v8::HandleScope scope(env->GetIsolate());
    1919             : 
    1920             :   // Register a debug event listener which steps and counts.
    1921           5 :   DebugEventCounter run_step;
    1922           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1923             : 
    1924           5 :   v8::Local<v8::Context> context = env.local();
    1925             :   // Create a function for testing stepping. Run it to allow it to get
    1926             :   // optimized.
    1927             :   const char* src = "function foo() { "
    1928             :                     "  var a;"
    1929             :                     "  var b = 1;"
    1930             :                     "  var c = foo;"
    1931             :                     "  var d = Math.floor;"
    1932             :                     "  var e = b + d(1.2);"
    1933             :                     "}"
    1934             :                     "foo()";
    1935           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    1936             : 
    1937           5 :   SetBreakPoint(foo, 0);
    1938             : 
    1939             :   // Stepping through the declarations.
    1940             :   run_step.set_step_action(StepIn);
    1941           5 :   break_point_hit_count = 0;
    1942          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1943           5 :   CHECK_EQ(5, break_point_hit_count);
    1944             : 
    1945             :   // Get rid of the debug event listener.
    1946           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1947           5 :   CheckDebuggerUnloaded();
    1948           5 : }
    1949             : 
    1950             : 
    1951       28342 : TEST(DebugStepLocals) {
    1952           5 :   LocalContext env;
    1953          10 :   v8::HandleScope scope(env->GetIsolate());
    1954             : 
    1955             :   // Register a debug event listener which steps and counts.
    1956           5 :   DebugEventCounter run_step;
    1957           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1958             : 
    1959           5 :   v8::Local<v8::Context> context = env.local();
    1960             :   // Create a function for testing stepping. Run it to allow it to get
    1961             :   // optimized.
    1962             :   const char* src = "function foo() { "
    1963             :                     "  var a,b;"
    1964             :                     "  a = 1;"
    1965             :                     "  b = a + 2;"
    1966             :                     "  b = 1 + 2 + 3;"
    1967             :                     "  a = Math.floor(b);"
    1968             :                     "}"
    1969             :                     "foo()";
    1970           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    1971             : 
    1972           5 :   SetBreakPoint(foo, 0);
    1973             : 
    1974             :   // Stepping through the declarations.
    1975             :   run_step.set_step_action(StepIn);
    1976           5 :   break_point_hit_count = 0;
    1977          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1978           5 :   CHECK_EQ(5, break_point_hit_count);
    1979             : 
    1980             :   // Get rid of the debug event listener.
    1981           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1982           5 :   CheckDebuggerUnloaded();
    1983           5 : }
    1984             : 
    1985             : 
    1986       28342 : TEST(DebugStepIf) {
    1987           5 :   LocalContext env;
    1988           5 :   v8::Isolate* isolate = env->GetIsolate();
    1989          10 :   v8::HandleScope scope(isolate);
    1990             : 
    1991             :   // Register a debug event listener which steps and counts.
    1992           5 :   DebugEventCounter run_step;
    1993           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1994             : 
    1995           5 :   v8::Local<v8::Context> context = env.local();
    1996             :   // Create a function for testing stepping. Run it to allow it to get
    1997             :   // optimized.
    1998             :   const int argc = 1;
    1999             :   const char* src = "function foo(x) { "
    2000             :                     "  a = 1;"
    2001             :                     "  if (x) {"
    2002             :                     "    b = 1;"
    2003             :                     "  } else {"
    2004             :                     "    c = 1;"
    2005             :                     "    d = 1;"
    2006             :                     "  }"
    2007             :                     "}"
    2008             :                     "a=0; b=0; c=0; d=0; foo()";
    2009           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2010           5 :   SetBreakPoint(foo, 0);
    2011             : 
    2012             :   // Stepping through the true part.
    2013             :   run_step.set_step_action(StepIn);
    2014           5 :   break_point_hit_count = 0;
    2015             :   v8::Local<v8::Value> argv_true[argc] = {v8::True(isolate)};
    2016          15 :   foo->Call(context, env->Global(), argc, argv_true).ToLocalChecked();
    2017           5 :   CHECK_EQ(4, break_point_hit_count);
    2018             : 
    2019             :   // Stepping through the false part.
    2020             :   run_step.set_step_action(StepIn);
    2021           5 :   break_point_hit_count = 0;
    2022             :   v8::Local<v8::Value> argv_false[argc] = {v8::False(isolate)};
    2023          15 :   foo->Call(context, env->Global(), argc, argv_false).ToLocalChecked();
    2024           5 :   CHECK_EQ(5, break_point_hit_count);
    2025             : 
    2026             :   // Get rid of the debug event listener.
    2027           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2028           5 :   CheckDebuggerUnloaded();
    2029           5 : }
    2030             : 
    2031             : 
    2032       28342 : TEST(DebugStepSwitch) {
    2033           5 :   LocalContext env;
    2034           5 :   v8::Isolate* isolate = env->GetIsolate();
    2035          10 :   v8::HandleScope scope(isolate);
    2036             : 
    2037             :   // Register a debug event listener which steps and counts.
    2038           5 :   DebugEventCounter run_step;
    2039           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2040             : 
    2041           5 :   v8::Local<v8::Context> context = env.local();
    2042             :   // Create a function for testing stepping. Run it to allow it to get
    2043             :   // optimized.
    2044             :   const int argc = 1;
    2045             :   const char* src = "function foo(x) { "
    2046             :                     "  a = 1;"
    2047             :                     "  switch (x) {"
    2048             :                     "    case 1:"
    2049             :                     "      b = 1;"
    2050             :                     "    case 2:"
    2051             :                     "      c = 1;"
    2052             :                     "      break;"
    2053             :                     "    case 3:"
    2054             :                     "      d = 1;"
    2055             :                     "      e = 1;"
    2056             :                     "      f = 1;"
    2057             :                     "      break;"
    2058             :                     "  }"
    2059             :                     "}"
    2060             :                     "a=0; b=0; c=0; d=0; e=0; f=0; foo()";
    2061           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2062           5 :   SetBreakPoint(foo, 0);
    2063             : 
    2064             :   // One case with fall-through.
    2065             :   run_step.set_step_action(StepIn);
    2066           5 :   break_point_hit_count = 0;
    2067           5 :   v8::Local<v8::Value> argv_1[argc] = {v8::Number::New(isolate, 1)};
    2068          15 :   foo->Call(context, env->Global(), argc, argv_1).ToLocalChecked();
    2069           5 :   CHECK_EQ(6, break_point_hit_count);
    2070             : 
    2071             :   // Another case.
    2072             :   run_step.set_step_action(StepIn);
    2073           5 :   break_point_hit_count = 0;
    2074           5 :   v8::Local<v8::Value> argv_2[argc] = {v8::Number::New(isolate, 2)};
    2075          15 :   foo->Call(context, env->Global(), argc, argv_2).ToLocalChecked();
    2076           5 :   CHECK_EQ(5, break_point_hit_count);
    2077             : 
    2078             :   // Last case.
    2079             :   run_step.set_step_action(StepIn);
    2080           5 :   break_point_hit_count = 0;
    2081           5 :   v8::Local<v8::Value> argv_3[argc] = {v8::Number::New(isolate, 3)};
    2082          15 :   foo->Call(context, env->Global(), argc, argv_3).ToLocalChecked();
    2083           5 :   CHECK_EQ(7, break_point_hit_count);
    2084             : 
    2085             :   // Get rid of the debug event listener.
    2086           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2087           5 :   CheckDebuggerUnloaded();
    2088           5 : }
    2089             : 
    2090             : 
    2091       28342 : TEST(DebugStepWhile) {
    2092           5 :   LocalContext env;
    2093           5 :   v8::Isolate* isolate = env->GetIsolate();
    2094          10 :   v8::HandleScope scope(isolate);
    2095             : 
    2096             :   // Register a debug event listener which steps and counts.
    2097           5 :   DebugEventCounter run_step;
    2098           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2099             : 
    2100           5 :   v8::Local<v8::Context> context = env.local();
    2101             :   // Create a function for testing stepping. Run it to allow it to get
    2102             :   // optimized.
    2103             :   const int argc = 1;
    2104             :   const char* src = "function foo(x) { "
    2105             :                     "  var a = 0;"
    2106             :                     "  while (a < x) {"
    2107             :                     "    a++;"
    2108             :                     "  }"
    2109             :                     "}"
    2110             :                     "foo()";
    2111           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2112           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2113             : 
    2114             :   // Looping 0 times.  We still should break at the while-condition once.
    2115             :   run_step.set_step_action(StepIn);
    2116           5 :   break_point_hit_count = 0;
    2117           5 :   v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
    2118          15 :   foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
    2119           5 :   CHECK_EQ(3, break_point_hit_count);
    2120             : 
    2121             :   // Looping 10 times.
    2122             :   run_step.set_step_action(StepIn);
    2123           5 :   break_point_hit_count = 0;
    2124           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2125          15 :   foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2126           5 :   CHECK_EQ(23, break_point_hit_count);
    2127             : 
    2128             :   // Looping 100 times.
    2129             :   run_step.set_step_action(StepIn);
    2130           5 :   break_point_hit_count = 0;
    2131           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2132          15 :   foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2133           5 :   CHECK_EQ(203, break_point_hit_count);
    2134             : 
    2135             :   // Get rid of the debug event listener.
    2136           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2137           5 :   CheckDebuggerUnloaded();
    2138           5 : }
    2139             : 
    2140             : 
    2141       28342 : TEST(DebugStepDoWhile) {
    2142           5 :   LocalContext env;
    2143           5 :   v8::Isolate* isolate = env->GetIsolate();
    2144          10 :   v8::HandleScope scope(isolate);
    2145             : 
    2146             :   // Register a debug event listener which steps and counts.
    2147           5 :   DebugEventCounter run_step;
    2148           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2149             : 
    2150           5 :   v8::Local<v8::Context> context = env.local();
    2151             :   // Create a function for testing stepping. Run it to allow it to get
    2152             :   // optimized.
    2153             :   const int argc = 1;
    2154             :   const char* src = "function foo(x) { "
    2155             :                     "  var a = 0;"
    2156             :                     "  do {"
    2157             :                     "    a++;"
    2158             :                     "  } while (a < x)"
    2159             :                     "}"
    2160             :                     "foo()";
    2161           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2162           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2163             : 
    2164             :   // Looping 0 times.
    2165             :   run_step.set_step_action(StepIn);
    2166           5 :   break_point_hit_count = 0;
    2167           5 :   v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
    2168          15 :   foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
    2169           5 :   CHECK_EQ(4, break_point_hit_count);
    2170             : 
    2171             :   // Looping 10 times.
    2172             :   run_step.set_step_action(StepIn);
    2173           5 :   break_point_hit_count = 0;
    2174           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2175          15 :   foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2176           5 :   CHECK_EQ(22, break_point_hit_count);
    2177             : 
    2178             :   // Looping 100 times.
    2179             :   run_step.set_step_action(StepIn);
    2180           5 :   break_point_hit_count = 0;
    2181           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2182          15 :   foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2183           5 :   CHECK_EQ(202, break_point_hit_count);
    2184             : 
    2185             :   // Get rid of the debug event listener.
    2186           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2187           5 :   CheckDebuggerUnloaded();
    2188           5 : }
    2189             : 
    2190             : 
    2191       28342 : TEST(DebugStepFor) {
    2192           5 :   LocalContext env;
    2193           5 :   v8::Isolate* isolate = env->GetIsolate();
    2194          10 :   v8::HandleScope scope(isolate);
    2195             : 
    2196             :   // Register a debug event listener which steps and counts.
    2197           5 :   DebugEventCounter run_step;
    2198           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2199             : 
    2200           5 :   v8::Local<v8::Context> context = env.local();
    2201             :   // Create a function for testing stepping. Run it to allow it to get
    2202             :   // optimized.
    2203             :   const int argc = 1;
    2204             :   const char* src = "function foo(x) { "
    2205             :                     "  a = 1;"
    2206             :                     "  for (i = 0; i < x; i++) {"
    2207             :                     "    b = 1;"
    2208             :                     "  }"
    2209             :                     "}"
    2210             :                     "a=0; b=0; i=0; foo()";
    2211           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2212             : 
    2213           5 :   SetBreakPoint(foo, 8);  // "a = 1;"
    2214             : 
    2215             :   // Looping 0 times.
    2216             :   run_step.set_step_action(StepIn);
    2217           5 :   break_point_hit_count = 0;
    2218           5 :   v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
    2219          15 :   foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
    2220           5 :   CHECK_EQ(4, break_point_hit_count);
    2221             : 
    2222             :   // Looping 10 times.
    2223             :   run_step.set_step_action(StepIn);
    2224           5 :   break_point_hit_count = 0;
    2225           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2226          15 :   foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2227           5 :   CHECK_EQ(34, break_point_hit_count);
    2228             : 
    2229             :   // Looping 100 times.
    2230             :   run_step.set_step_action(StepIn);
    2231           5 :   break_point_hit_count = 0;
    2232           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2233          15 :   foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2234           5 :   CHECK_EQ(304, break_point_hit_count);
    2235             : 
    2236             :   // Get rid of the debug event listener.
    2237           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2238           5 :   CheckDebuggerUnloaded();
    2239           5 : }
    2240             : 
    2241             : 
    2242       28342 : TEST(DebugStepForContinue) {
    2243           5 :   LocalContext env;
    2244           5 :   v8::Isolate* isolate = env->GetIsolate();
    2245          10 :   v8::HandleScope scope(isolate);
    2246             : 
    2247             :   // Register a debug event listener which steps and counts.
    2248           5 :   DebugEventCounter run_step;
    2249           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2250             : 
    2251           5 :   v8::Local<v8::Context> context = env.local();
    2252             :   // Create a function for testing stepping. Run it to allow it to get
    2253             :   // optimized.
    2254             :   const int argc = 1;
    2255             :   const char* src = "function foo(x) { "
    2256             :                     "  var a = 0;"
    2257             :                     "  var b = 0;"
    2258             :                     "  var c = 0;"
    2259             :                     "  for (var i = 0; i < x; i++) {"
    2260             :                     "    a++;"
    2261             :                     "    if (a % 2 == 0) continue;"
    2262             :                     "    b++;"
    2263             :                     "    c++;"
    2264             :                     "  }"
    2265             :                     "  return b;"
    2266             :                     "}"
    2267             :                     "foo()";
    2268           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2269             :   v8::Local<v8::Value> result;
    2270           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2271             : 
    2272             :   // Each loop generates 4 or 5 steps depending on whether a is equal.
    2273             : 
    2274             :   // Looping 10 times.
    2275             :   run_step.set_step_action(StepIn);
    2276           5 :   break_point_hit_count = 0;
    2277           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2278          15 :   result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2279          10 :   CHECK_EQ(5, result->Int32Value(context).FromJust());
    2280           5 :   CHECK_EQ(62, break_point_hit_count);
    2281             : 
    2282             :   // Looping 100 times.
    2283             :   run_step.set_step_action(StepIn);
    2284           5 :   break_point_hit_count = 0;
    2285           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2286          15 :   result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2287          10 :   CHECK_EQ(50, result->Int32Value(context).FromJust());
    2288           5 :   CHECK_EQ(557, break_point_hit_count);
    2289             : 
    2290             :   // Get rid of the debug event listener.
    2291           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2292           5 :   CheckDebuggerUnloaded();
    2293           5 : }
    2294             : 
    2295             : 
    2296       28342 : TEST(DebugStepForBreak) {
    2297           5 :   LocalContext env;
    2298           5 :   v8::Isolate* isolate = env->GetIsolate();
    2299          10 :   v8::HandleScope scope(isolate);
    2300             : 
    2301             :   // Register a debug event listener which steps and counts.
    2302           5 :   DebugEventCounter run_step;
    2303           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2304             : 
    2305           5 :   v8::Local<v8::Context> context = env.local();
    2306             :   // Create a function for testing stepping. Run it to allow it to get
    2307             :   // optimized.
    2308             :   const int argc = 1;
    2309             :   const char* src = "function foo(x) { "
    2310             :                     "  var a = 0;"
    2311             :                     "  var b = 0;"
    2312             :                     "  var c = 0;"
    2313             :                     "  for (var i = 0; i < 1000; i++) {"
    2314             :                     "    a++;"
    2315             :                     "    if (a == x) break;"
    2316             :                     "    b++;"
    2317             :                     "    c++;"
    2318             :                     "  }"
    2319             :                     "  return b;"
    2320             :                     "}"
    2321             :                     "foo()";
    2322           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2323             :   v8::Local<v8::Value> result;
    2324           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2325             : 
    2326             :   // Each loop generates 5 steps except for the last (when break is executed)
    2327             :   // which only generates 4.
    2328             : 
    2329             :   // Looping 10 times.
    2330             :   run_step.set_step_action(StepIn);
    2331           5 :   break_point_hit_count = 0;
    2332           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2333          15 :   result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2334          10 :   CHECK_EQ(9, result->Int32Value(context).FromJust());
    2335           5 :   CHECK_EQ(64, break_point_hit_count);
    2336             : 
    2337             :   // Looping 100 times.
    2338             :   run_step.set_step_action(StepIn);
    2339           5 :   break_point_hit_count = 0;
    2340           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2341          15 :   result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2342          10 :   CHECK_EQ(99, result->Int32Value(context).FromJust());
    2343           5 :   CHECK_EQ(604, break_point_hit_count);
    2344             : 
    2345             :   // Get rid of the debug event listener.
    2346           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2347           5 :   CheckDebuggerUnloaded();
    2348           5 : }
    2349             : 
    2350             : 
    2351       28342 : TEST(DebugStepForIn) {
    2352           5 :   LocalContext env;
    2353          10 :   v8::HandleScope scope(env->GetIsolate());
    2354             : 
    2355             :   // Register a debug event listener which steps and counts.
    2356           5 :   DebugEventCounter run_step;
    2357           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2358             : 
    2359           5 :   v8::Local<v8::Context> context = env.local();
    2360             :   // Create a function for testing stepping. Run it to allow it to get
    2361             :   // optimized.
    2362             :   v8::Local<v8::Function> foo;
    2363             :   const char* src_1 = "function foo() { "
    2364             :                       "  var a = [1, 2];"
    2365             :                       "  for (x in a) {"
    2366             :                       "    b = 0;"
    2367             :                       "  }"
    2368             :                       "}"
    2369             :                       "foo()";
    2370           5 :   foo = CompileFunction(&env, src_1, "foo");
    2371           5 :   SetBreakPoint(foo, 0);  // "var a = ..."
    2372             : 
    2373             :   run_step.set_step_action(StepIn);
    2374           5 :   break_point_hit_count = 0;
    2375          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2376           5 :   CHECK_EQ(8, break_point_hit_count);
    2377             : 
    2378             :   // Create a function for testing stepping. Run it to allow it to get
    2379             :   // optimized.
    2380             :   const char* src_2 = "function foo() { "
    2381             :                       "  var a = {a:[1, 2, 3]};"
    2382             :                       "  for (x in a.a) {"
    2383             :                       "    b = 0;"
    2384             :                       "  }"
    2385             :                       "}"
    2386             :                       "foo()";
    2387           5 :   foo = CompileFunction(&env, src_2, "foo");
    2388           5 :   SetBreakPoint(foo, 0);  // "var a = ..."
    2389             : 
    2390             :   run_step.set_step_action(StepIn);
    2391           5 :   break_point_hit_count = 0;
    2392          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2393           5 :   CHECK_EQ(10, break_point_hit_count);
    2394             : 
    2395             :   // Get rid of the debug event listener.
    2396           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2397           5 :   CheckDebuggerUnloaded();
    2398           5 : }
    2399             : 
    2400             : 
    2401       28342 : TEST(DebugStepWith) {
    2402           5 :   LocalContext env;
    2403          10 :   v8::HandleScope scope(env->GetIsolate());
    2404             : 
    2405             :   // Register a debug event listener which steps and counts.
    2406           5 :   DebugEventCounter run_step;
    2407           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2408             : 
    2409           5 :   v8::Local<v8::Context> context = env.local();
    2410             :   // Create a function for testing stepping. Run it to allow it to get
    2411             :   // optimized.
    2412             :   const char* src = "function foo(x) { "
    2413             :                     "  var a = {};"
    2414             :                     "  with (a) {}"
    2415             :                     "  with (b) {}"
    2416             :                     "}"
    2417             :                     "foo()";
    2418          25 :   CHECK(env->Global()
    2419             :             ->Set(context, v8_str(env->GetIsolate(), "b"),
    2420             :                   v8::Object::New(env->GetIsolate()))
    2421             :             .FromJust());
    2422           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2423             :   v8::Local<v8::Value> result;
    2424           5 :   SetBreakPoint(foo, 8);  // "var a = {};"
    2425             : 
    2426             :   run_step.set_step_action(StepIn);
    2427           5 :   break_point_hit_count = 0;
    2428          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2429           5 :   CHECK_EQ(4, break_point_hit_count);
    2430             : 
    2431             :   // Get rid of the debug event listener.
    2432           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2433           5 :   CheckDebuggerUnloaded();
    2434           5 : }
    2435             : 
    2436             : 
    2437       28342 : TEST(DebugConditional) {
    2438           5 :   LocalContext env;
    2439           5 :   v8::Isolate* isolate = env->GetIsolate();
    2440          10 :   v8::HandleScope scope(isolate);
    2441             : 
    2442             :   // Register a debug event listener which steps and counts.
    2443           5 :   DebugEventCounter run_step;
    2444           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2445             : 
    2446           5 :   v8::Local<v8::Context> context = env.local();
    2447             :   // Create a function for testing stepping. Run it to allow it to get
    2448             :   // optimized.
    2449             :   const char* src =
    2450             :       "function foo(x) { "
    2451             :       "  return x ? 1 : 2;"
    2452             :       "}"
    2453             :       "foo()";
    2454           5 :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2455           5 :   SetBreakPoint(foo, 0);  // "var a;"
    2456             : 
    2457             :   run_step.set_step_action(StepIn);
    2458           5 :   break_point_hit_count = 0;
    2459          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2460           5 :   CHECK_EQ(2, break_point_hit_count);
    2461             : 
    2462             :   run_step.set_step_action(StepIn);
    2463           5 :   break_point_hit_count = 0;
    2464             :   const int argc = 1;
    2465             :   v8::Local<v8::Value> argv_true[argc] = {v8::True(isolate)};
    2466          15 :   foo->Call(context, env->Global(), argc, argv_true).ToLocalChecked();
    2467           5 :   CHECK_EQ(2, break_point_hit_count);
    2468             : 
    2469             :   // Get rid of the debug event listener.
    2470           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2471           5 :   CheckDebuggerUnloaded();
    2472           5 : }
    2473             : 
    2474             : // Test that step in does not step into native functions.
    2475       28342 : TEST(DebugStepNatives) {
    2476           5 :   LocalContext env;
    2477          10 :   v8::HandleScope scope(env->GetIsolate());
    2478             : 
    2479             :   // Create a function for testing stepping.
    2480             :   v8::Local<v8::Function> foo =
    2481           5 :       CompileFunction(&env, "function foo(){debugger;Math.sin(1);}", "foo");
    2482             : 
    2483             :   // Register a debug event listener which steps and counts.
    2484           5 :   DebugEventCounter run_step;
    2485           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2486             : 
    2487           5 :   v8::Local<v8::Context> context = env.local();
    2488             :   run_step.set_step_action(StepIn);
    2489           5 :   break_point_hit_count = 0;
    2490          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2491             : 
    2492             :   // With stepping all break locations are hit.
    2493           5 :   CHECK_EQ(3, break_point_hit_count);
    2494             : 
    2495           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2496             :   CheckDebuggerUnloaded();
    2497             : 
    2498             :   // Register a debug event listener which just counts.
    2499           5 :   DebugEventCounter delegate;
    2500           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2501             : 
    2502           5 :   break_point_hit_count = 0;
    2503          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2504             : 
    2505             :   // Without stepping only active break points are hit.
    2506           5 :   CHECK_EQ(1, break_point_hit_count);
    2507             : 
    2508           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2509           5 :   CheckDebuggerUnloaded();
    2510           5 : }
    2511             : 
    2512             : // Test that step in works with function.apply.
    2513       28342 : TEST(DebugStepFunctionApply) {
    2514           5 :   LocalContext env;
    2515          10 :   v8::HandleScope scope(env->GetIsolate());
    2516             : 
    2517             :   // Create a function for testing stepping.
    2518             :   v8::Local<v8::Function> foo =
    2519             :       CompileFunction(&env,
    2520             :                       "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
    2521             :                       "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
    2522           5 :                       "foo");
    2523             : 
    2524             :   // Register a debug event listener which steps and counts.
    2525           5 :   DebugEventCounter run_step;
    2526           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2527             : 
    2528           5 :   v8::Local<v8::Context> context = env.local();
    2529             :   run_step.set_step_action(StepIn);
    2530           5 :   break_point_hit_count = 0;
    2531          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2532             : 
    2533             :   // With stepping all break locations are hit.
    2534           5 :   CHECK_EQ(7, break_point_hit_count);
    2535             : 
    2536           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2537             :   CheckDebuggerUnloaded();
    2538             : 
    2539             :   // Register a debug event listener which just counts.
    2540           5 :   DebugEventCounter delegate;
    2541           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2542             : 
    2543           5 :   break_point_hit_count = 0;
    2544          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2545             : 
    2546             :   // Without stepping only the debugger statement is hit.
    2547           5 :   CHECK_EQ(1, break_point_hit_count);
    2548             : 
    2549           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2550           5 :   CheckDebuggerUnloaded();
    2551           5 : }
    2552             : 
    2553             : 
    2554             : // Test that step in works with function.call.
    2555       28342 : TEST(DebugStepFunctionCall) {
    2556           5 :   LocalContext env;
    2557           5 :   v8::Isolate* isolate = env->GetIsolate();
    2558          10 :   v8::HandleScope scope(isolate);
    2559             : 
    2560           5 :   v8::Local<v8::Context> context = env.local();
    2561             :   // Create a function for testing stepping.
    2562             :   v8::Local<v8::Function> foo = CompileFunction(
    2563             :       &env,
    2564             :       "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
    2565             :       "function foo(a){ debugger;"
    2566             :       "                 if (a) {"
    2567             :       "                   bar.call(this, 1, 2, 3);"
    2568             :       "                 } else {"
    2569             :       "                   bar.call(this, 0);"
    2570             :       "                 }"
    2571             :       "}",
    2572           5 :       "foo");
    2573             : 
    2574             :   // Register a debug event listener which steps and counts.
    2575           5 :   DebugEventCounter run_step;
    2576           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2577             :   run_step.set_step_action(StepIn);
    2578             : 
    2579             :   // Check stepping where the if condition in bar is false.
    2580           5 :   break_point_hit_count = 0;
    2581          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2582           5 :   CHECK_EQ(6, break_point_hit_count);
    2583             : 
    2584             :   // Check stepping where the if condition in bar is true.
    2585           5 :   break_point_hit_count = 0;
    2586             :   const int argc = 1;
    2587             :   v8::Local<v8::Value> argv[argc] = {v8::True(isolate)};
    2588          15 :   foo->Call(context, env->Global(), argc, argv).ToLocalChecked();
    2589           5 :   CHECK_EQ(8, break_point_hit_count);
    2590             : 
    2591           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2592             :   CheckDebuggerUnloaded();
    2593             : 
    2594             :   // Register a debug event listener which just counts.
    2595           5 :   DebugEventCounter delegate;
    2596           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2597             : 
    2598           5 :   break_point_hit_count = 0;
    2599          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2600             : 
    2601             :   // Without stepping only the debugger statement is hit.
    2602           5 :   CHECK_EQ(1, break_point_hit_count);
    2603             : 
    2604           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    2605           5 :   CheckDebuggerUnloaded();
    2606           5 : }
    2607             : 
    2608             : 
    2609             : // Test that step in works with Function.call.apply.
    2610       28342 : TEST(DebugStepFunctionCallApply) {
    2611           5 :   LocalContext env;
    2612           5 :   v8::Isolate* isolate = env->GetIsolate();
    2613          10 :   v8::HandleScope scope(isolate);
    2614             : 
    2615           5 :   v8::Local<v8::Context> context = env.local();
    2616             :   // Create a function for testing stepping.
    2617             :   v8::Local<v8::Function> foo =
    2618             :       CompileFunction(&env,
    2619             :                       "function bar() { }"
    2620             :                       "function foo(){ debugger;"
    2621             :                       "                Function.call.apply(bar);"
    2622             :                       "                Function.call.apply(Function.call, "
    2623             :                       "[Function.call, bar]);"
    2624             :                       "}",
    2625           5 :                       "foo");
    2626             : 
    2627             :   // Register a debug event listener which steps and counts.
    2628           5 :   DebugEventCounter run_step;
    2629           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2630             :   run_step.set_step_action(StepIn);
    2631             : 
    2632           5 :   break_point_hit_count = 0;
    2633          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2634           5 :   CHECK_EQ(6, break_point_hit_count);
    2635             : 
    2636           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2637             :   CheckDebuggerUnloaded();
    2638             : 
    2639             :   // Register a debug event listener which just counts.
    2640           5 :   DebugEventCounter delegate;
    2641           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2642             : 
    2643           5 :   break_point_hit_count = 0;
    2644          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2645             : 
    2646             :   // Without stepping only the debugger statement is hit.
    2647           5 :   CHECK_EQ(1, break_point_hit_count);
    2648             : 
    2649           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    2650           5 :   CheckDebuggerUnloaded();
    2651           5 : }
    2652             : 
    2653             : 
    2654             : // Tests that breakpoint will be hit if it's set in script.
    2655       28342 : TEST(PauseInScript) {
    2656           5 :   LocalContext env;
    2657          10 :   v8::HandleScope scope(env->GetIsolate());
    2658          10 :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
    2659             : 
    2660             :   // Register a debug event listener which counts.
    2661           5 :   DebugEventCounter event_counter;
    2662           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &event_counter);
    2663             : 
    2664           5 :   v8::Local<v8::Context> context = env.local();
    2665             :   // Create a script that returns a function.
    2666             :   const char* src = "(function (evt) {})";
    2667             :   const char* script_name = "StepInHandlerTest";
    2668             : 
    2669             :   v8::ScriptOrigin origin(v8_str(env->GetIsolate(), script_name),
    2670          10 :                           v8::Integer::New(env->GetIsolate(), 0));
    2671             :   v8::Local<v8::Script> script =
    2672           5 :       v8::Script::Compile(context, v8_str(env->GetIsolate(), src), &origin)
    2673           5 :           .ToLocalChecked();
    2674             : 
    2675             :   // Set breakpoint in the script.
    2676             :   i::Handle<i::Script> i_script(
    2677          10 :       i::Script::cast(v8::Utils::OpenHandle(*script)->shared()->script()),
    2678          10 :       isolate);
    2679           5 :   i::Handle<i::String> condition = isolate->factory()->empty_string();
    2680           5 :   int position = 0;
    2681             :   int id;
    2682           5 :   isolate->debug()->SetBreakPointForScript(i_script, condition, &position, &id);
    2683           5 :   break_point_hit_count = 0;
    2684             : 
    2685           5 :   v8::Local<v8::Value> r = script->Run(context).ToLocalChecked();
    2686             : 
    2687           5 :   CHECK(r->IsFunction());
    2688           5 :   CHECK_EQ(1, break_point_hit_count);
    2689             : 
    2690             :   // Get rid of the debug delegate.
    2691           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2692           5 :   CheckDebuggerUnloaded();
    2693           5 : }
    2694             : 
    2695             : int message_callback_count = 0;
    2696             : 
    2697       28342 : TEST(DebugBreak) {
    2698           5 :   i::FLAG_stress_compaction = false;
    2699             : #ifdef VERIFY_HEAP
    2700             :   i::FLAG_verify_heap = true;
    2701             : #endif
    2702           5 :   LocalContext env;
    2703           5 :   v8::Isolate* isolate = env->GetIsolate();
    2704          10 :   v8::HandleScope scope(isolate);
    2705             : 
    2706             :   // Register a debug event listener which sets the break flag and counts.
    2707           5 :   DebugEventBreak delegate;
    2708           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2709             : 
    2710           5 :   v8::Local<v8::Context> context = env.local();
    2711             :   // Create a function for testing stepping.
    2712             :   const char* src = "function f0() {}"
    2713             :                     "function f1(x1) {}"
    2714             :                     "function f2(x1,x2) {}"
    2715             :                     "function f3(x1,x2,x3) {}";
    2716           5 :   v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
    2717           5 :   v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
    2718           5 :   v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
    2719           5 :   v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
    2720             : 
    2721             :   // Call the function to make sure it is compiled.
    2722             :   v8::Local<v8::Value> argv[] = {
    2723             :       v8::Number::New(isolate, 1), v8::Number::New(isolate, 1),
    2724          20 :       v8::Number::New(isolate, 1), v8::Number::New(isolate, 1)};
    2725             : 
    2726             :   // Call all functions to make sure that they are compiled.
    2727          15 :   f0->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2728          15 :   f1->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2729          15 :   f2->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2730          15 :   f3->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2731             : 
    2732             :   // Set the debug break flag.
    2733           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2734             : 
    2735             :   // Call all functions with different argument count.
    2736           5 :   break_point_hit_count = 0;
    2737          25 :   for (unsigned int i = 0; i < arraysize(argv); i++) {
    2738          80 :     f0->Call(context, env->Global(), i, argv).ToLocalChecked();
    2739          60 :     f1->Call(context, env->Global(), i, argv).ToLocalChecked();
    2740          60 :     f2->Call(context, env->Global(), i, argv).ToLocalChecked();
    2741          60 :     f3->Call(context, env->Global(), i, argv).ToLocalChecked();
    2742             :   }
    2743             : 
    2744             :   // One break for each function called.
    2745          10 :   CHECK_EQ(4 * arraysize(argv), break_point_hit_count);
    2746             : 
    2747             :   // Get rid of the debug event listener.
    2748           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2749           5 :   CheckDebuggerUnloaded();
    2750           5 : }
    2751             : 
    2752           5 : class DebugScopingListener : public v8::debug::DebugDelegate {
    2753             :  public:
    2754           0 :   void BreakProgramRequested(
    2755             :       v8::Local<v8::Context>,
    2756             :       const std::vector<v8::debug::BreakpointId>&) override {
    2757             :     auto stack_traces =
    2758           0 :         v8::debug::StackTraceIterator::Create(CcTest::isolate());
    2759           0 :     v8::debug::Location location = stack_traces->GetSourceLocation();
    2760           0 :     CHECK_EQ(26, location.GetColumnNumber());
    2761           0 :     CHECK_EQ(0, location.GetLineNumber());
    2762             : 
    2763           0 :     auto scopes = stack_traces->GetScopeIterator();
    2764           0 :     CHECK_EQ(v8::debug::ScopeIterator::ScopeTypeWith, scopes->GetType());
    2765           0 :     CHECK_EQ(20, scopes->GetStartLocation().GetColumnNumber());
    2766           0 :     CHECK_EQ(31, scopes->GetEndLocation().GetColumnNumber());
    2767             : 
    2768           0 :     scopes->Advance();
    2769           0 :     CHECK_EQ(v8::debug::ScopeIterator::ScopeTypeLocal, scopes->GetType());
    2770           0 :     CHECK_EQ(0, scopes->GetStartLocation().GetColumnNumber());
    2771           0 :     CHECK_EQ(68, scopes->GetEndLocation().GetColumnNumber());
    2772             : 
    2773           0 :     scopes->Advance();
    2774           0 :     CHECK_EQ(v8::debug::ScopeIterator::ScopeTypeGlobal, scopes->GetType());
    2775             : 
    2776           0 :     scopes->Advance();
    2777           0 :     CHECK(scopes->Done());
    2778           0 :   }
    2779             : };
    2780             : 
    2781       28342 : TEST(DebugBreakInWrappedScript) {
    2782           5 :   i::FLAG_stress_compaction = false;
    2783             : #ifdef VERIFY_HEAP
    2784             :   i::FLAG_verify_heap = true;
    2785             : #endif
    2786           5 :   LocalContext env;
    2787           5 :   v8::Isolate* isolate = env->GetIsolate();
    2788          10 :   v8::HandleScope scope(isolate);
    2789             : 
    2790             :   // Register a debug event listener which sets the break flag and counts.
    2791           5 :   DebugScopingListener delegate;
    2792           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2793             : 
    2794             :   static const char* source =
    2795             :       //   0         1         2         3         4         5         6 7
    2796             :       "try { with({o : []}){ o[0](); } } catch (e) { return e.toString(); }";
    2797             :   static const char* expect = "TypeError: o[0] is not a function";
    2798             : 
    2799             :   // For this test, we want to break on uncaught exceptions:
    2800           5 :   ChangeBreakOnException(true, true);
    2801             : 
    2802             :   {
    2803           5 :     v8::ScriptCompiler::Source script_source(v8_str(source));
    2804             :     v8::Local<v8::Function> fun =
    2805             :         v8::ScriptCompiler::CompileFunctionInContext(
    2806           5 :             env.local(), &script_source, 0, nullptr, 0, nullptr)
    2807           5 :             .ToLocalChecked();
    2808             :     v8::Local<v8::Value> result =
    2809          15 :         fun->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
    2810           5 :     CHECK(result->IsString());
    2811          15 :     CHECK(v8::Local<v8::String>::Cast(result)
    2812             :               ->Equals(env.local(), v8_str(expect))
    2813             :               .FromJust());
    2814             :   }
    2815             : 
    2816             :   // Get rid of the debug event listener.
    2817           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2818           5 :   CheckDebuggerUnloaded();
    2819           5 : }
    2820             : 
    2821           0 : static void EmptyHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {}
    2822             : 
    2823       28342 : TEST(DebugScopeIteratorWithFunctionTemplate) {
    2824           5 :   LocalContext env;
    2825          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    2826           5 :   v8::Isolate* isolate = env->GetIsolate();
    2827             :   EnableDebugger(isolate);
    2828             :   v8::Local<v8::Function> func =
    2829          10 :       v8::Function::New(env.local(), EmptyHandler).ToLocalChecked();
    2830             :   std::unique_ptr<v8::debug::ScopeIterator> iterator =
    2831           5 :       v8::debug::ScopeIterator::CreateForFunction(isolate, func);
    2832           5 :   CHECK(iterator->Done());
    2833           5 :   DisableDebugger(isolate);
    2834           5 : }
    2835             : 
    2836       28342 : TEST(DebugBreakWithoutJS) {
    2837           5 :   i::FLAG_stress_compaction = false;
    2838             : #ifdef VERIFY_HEAP
    2839             :   i::FLAG_verify_heap = true;
    2840             : #endif
    2841           5 :   LocalContext env;
    2842           5 :   v8::Isolate* isolate = env->GetIsolate();
    2843          10 :   v8::HandleScope scope(isolate);
    2844           5 :   v8::Local<v8::Context> context = env.local();
    2845             : 
    2846             :   // Register a debug event listener which sets the break flag and counts.
    2847           5 :   DebugEventBreak delegate;
    2848           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2849             : 
    2850             :   // Set the debug break flag.
    2851           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2852             : 
    2853           5 :   v8::Local<v8::String> json = v8_str("[1]");
    2854          10 :   v8::Local<v8::Value> parsed = v8::JSON::Parse(context, json).ToLocalChecked();
    2855          15 :   CHECK(v8::JSON::Stringify(context, parsed)
    2856             :             .ToLocalChecked()
    2857             :             ->Equals(context, json)
    2858             :             .FromJust());
    2859           5 :   CHECK_EQ(0, break_point_hit_count);
    2860             :   CompileRun("");
    2861           5 :   CHECK_EQ(1, break_point_hit_count);
    2862             : 
    2863             :   // Get rid of the debug event listener.
    2864           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2865           5 :   CheckDebuggerUnloaded();
    2866           5 : }
    2867             : 
    2868             : // Test to ensure that JavaScript code keeps running while the debug break
    2869             : // through the stack limit flag is set but breaks are disabled.
    2870       28342 : TEST(DisableBreak) {
    2871           5 :   LocalContext env;
    2872          10 :   v8::HandleScope scope(env->GetIsolate());
    2873             : 
    2874             :   // Register a debug event listener which sets the break flag and counts.
    2875           5 :   DebugEventCounter delegate;
    2876           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2877             : 
    2878           5 :   v8::Local<v8::Context> context = env.local();
    2879             :   // Create a function for testing stepping.
    2880             :   const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
    2881           5 :   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
    2882             : 
    2883             :   // Set, test and cancel debug break.
    2884           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2885           5 :   v8::debug::ClearBreakOnNextFunctionCall(env->GetIsolate());
    2886             : 
    2887             :   // Set the debug break flag.
    2888           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2889             : 
    2890             :   // Call all functions with different argument count.
    2891           5 :   break_point_hit_count = 0;
    2892          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2893           5 :   CHECK_EQ(1, break_point_hit_count);
    2894             : 
    2895             :   {
    2896           5 :     v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2897           5 :     i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
    2898             :     v8::internal::DisableBreak disable_break(isolate->debug());
    2899          15 :     f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2900           5 :     CHECK_EQ(1, break_point_hit_count);
    2901             :   }
    2902             : 
    2903          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2904           5 :   CHECK_EQ(2, break_point_hit_count);
    2905             : 
    2906             :   // Get rid of the debug event listener.
    2907           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2908           5 :   CheckDebuggerUnloaded();
    2909           5 : }
    2910             : 
    2911       28342 : TEST(DisableDebuggerStatement) {
    2912           5 :   LocalContext env;
    2913          10 :   v8::HandleScope scope(env->GetIsolate());
    2914             : 
    2915             :   // Register a debug event listener which sets the break flag and counts.
    2916           5 :   DebugEventCounter delegate;
    2917           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2918             : 
    2919             :   CompileRun("debugger;");
    2920           5 :   CHECK_EQ(1, break_point_hit_count);
    2921             : 
    2922             :   // Check that we ignore debugger statement when breakpoints aren't active.
    2923           5 :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
    2924             :   isolate->debug()->set_break_points_active(false);
    2925             :   CompileRun("debugger;");
    2926           5 :   CHECK_EQ(1, break_point_hit_count);
    2927             : 
    2928          10 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2929           5 : }
    2930             : 
    2931             : static const char* kSimpleExtensionSource =
    2932             :   "(function Foo() {"
    2933             :   "  return 4;"
    2934             :   "})() ";
    2935             : 
    2936             : // http://crbug.com/28933
    2937             : // Test that debug break is disabled when bootstrapper is active.
    2938       28342 : TEST(NoBreakWhenBootstrapping) {
    2939           5 :   v8::Isolate* isolate = CcTest::isolate();
    2940           5 :   v8::HandleScope scope(isolate);
    2941             : 
    2942             :   // Register a debug event listener which sets the break flag and counts.
    2943           5 :   DebugEventCounter delegate;
    2944           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2945             : 
    2946             :   // Set the debug break flag.
    2947           5 :   v8::debug::SetBreakOnNextFunctionCall(isolate);
    2948           5 :   break_point_hit_count = 0;
    2949             :   {
    2950             :     // Create a context with an extension to make sure that some JavaScript
    2951             :     // code is executed during bootstrapping.
    2952             :     v8::RegisterExtension(new v8::Extension("simpletest",
    2953           5 :                                             kSimpleExtensionSource));
    2954           5 :     const char* extension_names[] = { "simpletest" };
    2955             :     v8::ExtensionConfiguration extensions(1, extension_names);
    2956           5 :     v8::HandleScope handle_scope(isolate);
    2957           5 :     v8::Context::New(isolate, &extensions);
    2958             :   }
    2959             :   // Check that no DebugBreak events occurred during the context creation.
    2960           5 :   CHECK_EQ(0, break_point_hit_count);
    2961             : 
    2962             :   // Get rid of the debug event listener.
    2963           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    2964           5 :   CheckDebuggerUnloaded();
    2965           5 : }
    2966             : 
    2967       28342 : TEST(SetDebugEventListenerOnUninitializedVM) {
    2968           5 :   v8::HandleScope scope(CcTest::isolate());
    2969          10 :   EnableDebugger(CcTest::isolate());
    2970           5 : }
    2971             : 
    2972             : // Test that clearing the debug event listener actually clears all break points
    2973             : // and related information.
    2974       28342 : TEST(DebuggerUnload) {
    2975           5 :   LocalContext env;
    2976          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    2977             :   // Check debugger is unloaded before it is used.
    2978             :   CheckDebuggerUnloaded();
    2979             : 
    2980             :   // Set a debug event listener.
    2981           5 :   break_point_hit_count = 0;
    2982           5 :   DebugEventCounter delegate;
    2983           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2984           5 :   v8::Local<v8::Context> context = env.local();
    2985             :   {
    2986           5 :     v8::HandleScope scope(env->GetIsolate());
    2987             :     // Create a couple of functions for the test.
    2988             :     v8::Local<v8::Function> foo =
    2989           5 :         CompileFunction(&env, "function foo(){x=1}", "foo");
    2990             :     v8::Local<v8::Function> bar =
    2991           5 :         CompileFunction(&env, "function bar(){y=2}", "bar");
    2992             : 
    2993             :     // Set some break points.
    2994           5 :     SetBreakPoint(foo, 0);
    2995           5 :     SetBreakPoint(foo, 4);
    2996           5 :     SetBreakPoint(bar, 0);
    2997           5 :     SetBreakPoint(bar, 4);
    2998             : 
    2999             :     // Make sure that the break points are there.
    3000           5 :     break_point_hit_count = 0;
    3001          15 :     foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3002           5 :     CHECK_EQ(2, break_point_hit_count);
    3003          15 :     bar->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3004           5 :     CHECK_EQ(4, break_point_hit_count);
    3005             :   }
    3006             : 
    3007             :   // Remove the debug event listener without clearing breakpoints. Do this
    3008             :   // outside a handle scope.
    3009           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3010           5 :   CheckDebuggerUnloaded();
    3011           5 : }
    3012             : 
    3013             : int event_listener_hit_count = 0;
    3014             : 
    3015             : // Test for issue http://code.google.com/p/v8/issues/detail?id=289.
    3016             : // Make sure that DebugGetLoadedScripts doesn't return scripts
    3017             : // with disposed external source.
    3018             : class EmptyExternalStringResource : public v8::String::ExternalStringResource {
    3019             :  public:
    3020             :   EmptyExternalStringResource() { empty_[0] = 0; }
    3021           0 :   ~EmptyExternalStringResource() override = default;
    3022           0 :   size_t length() const override { return empty_.length(); }
    3023           0 :   const uint16_t* data() const override { return empty_.start(); }
    3024             : 
    3025             :  private:
    3026             :   ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
    3027             : };
    3028             : 
    3029       28342 : TEST(DebugScriptLineEndsAreAscending) {
    3030           5 :   LocalContext env;
    3031           5 :   v8::Isolate* isolate = env->GetIsolate();
    3032          10 :   v8::HandleScope scope(isolate);
    3033             : 
    3034             :   // Compile a test script.
    3035             :   v8::Local<v8::String> script = v8_str(isolate,
    3036             :                                         "function f() {\n"
    3037             :                                         "  debugger;\n"
    3038           5 :                                         "}\n");
    3039             : 
    3040           5 :   v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8_str(isolate, "name"));
    3041             :   v8::Local<v8::Script> script1 =
    3042           5 :       v8::Script::Compile(env.local(), script, &origin1).ToLocalChecked();
    3043             :   USE(script1);
    3044             : 
    3045             :   Handle<v8::internal::FixedArray> instances;
    3046             :   {
    3047           5 :     v8::internal::Debug* debug = CcTest::i_isolate()->debug();
    3048           5 :     instances = debug->GetLoadedScripts();
    3049             :   }
    3050             : 
    3051           5 :   CHECK_GT(instances->length(), 0);
    3052          45 :   for (int i = 0; i < instances->length(); i++) {
    3053             :     Handle<v8::internal::Script> script = Handle<v8::internal::Script>(
    3054             :         v8::internal::Script::cast(instances->get(i)), CcTest::i_isolate());
    3055             : 
    3056          20 :     v8::internal::Script::InitLineEnds(script);
    3057             :     v8::internal::FixedArray ends =
    3058          40 :         v8::internal::FixedArray::cast(script->line_ends());
    3059          20 :     CHECK_GT(ends->length(), 0);
    3060             : 
    3061             :     int prev_end = -1;
    3062        1030 :     for (int j = 0; j < ends->length(); j++) {
    3063         505 :       const int curr_end = v8::internal::Smi::ToInt(ends->get(j));
    3064         505 :       CHECK_GT(curr_end, prev_end);
    3065             :       prev_end = curr_end;
    3066             :     }
    3067           5 :   }
    3068           5 : }
    3069             : 
    3070             : static v8::Local<v8::Context> expected_context;
    3071             : static v8::Local<v8::Value> expected_context_data;
    3072             : 
    3073          10 : class ContextCheckEventListener : public v8::debug::DebugDelegate {
    3074             :  public:
    3075          15 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3076             :                              const std::vector<v8::debug::BreakpointId>&
    3077             :                                  inspector_break_points_hit) override {
    3078          15 :     CheckContext();
    3079          15 :   }
    3080          20 :   void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
    3081             :                       bool has_compile_error) override {
    3082          20 :     CheckContext();
    3083          20 :   }
    3084           0 :   void ExceptionThrown(v8::Local<v8::Context> paused_context,
    3085             :                        v8::Local<v8::Value> exception,
    3086             :                        v8::Local<v8::Value> promise, bool is_uncaught,
    3087             :                        v8::debug::ExceptionType) override {
    3088           0 :     CheckContext();
    3089           0 :   }
    3090          15 :   bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
    3091             :                             const v8::debug::Location& start,
    3092             :                             const v8::debug::Location& end) override {
    3093          15 :     CheckContext();
    3094          15 :     return false;
    3095             :   }
    3096             : 
    3097             :  private:
    3098          50 :   void CheckContext() {
    3099          50 :     v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
    3100          50 :     CHECK(context == expected_context);
    3101          50 :     CHECK(context->GetEmbedderData(0)->StrictEquals(expected_context_data));
    3102          50 :     event_listener_hit_count++;
    3103          50 :   }
    3104             : };
    3105             : 
    3106             : // Test which creates two contexts and sets different embedder data on each.
    3107             : // Checks that this data is set correctly and that when the debug event
    3108             : // listener is called the expected context is the one active.
    3109       28342 : TEST(ContextData) {
    3110           5 :   v8::Isolate* isolate = CcTest::isolate();
    3111           5 :   v8::HandleScope scope(isolate);
    3112             : 
    3113             :   // Create two contexts.
    3114             :   v8::Local<v8::Context> context_1;
    3115             :   v8::Local<v8::Context> context_2;
    3116             :   v8::Local<v8::ObjectTemplate> global_template =
    3117             :       v8::Local<v8::ObjectTemplate>();
    3118             :   v8::Local<v8::Value> global_object = v8::Local<v8::Value>();
    3119             :   context_1 =
    3120           5 :       v8::Context::New(isolate, nullptr, global_template, global_object);
    3121             :   context_2 =
    3122           5 :       v8::Context::New(isolate, nullptr, global_template, global_object);
    3123             : 
    3124           5 :   ContextCheckEventListener delegate;
    3125           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3126             : 
    3127             :   // Default data value is undefined.
    3128           5 :   CHECK_EQ(0, context_1->GetNumberOfEmbedderDataFields());
    3129           5 :   CHECK_EQ(0, context_2->GetNumberOfEmbedderDataFields());
    3130             : 
    3131             :   // Set and check different data values.
    3132           5 :   v8::Local<v8::String> data_1 = v8_str(isolate, "1");
    3133           5 :   v8::Local<v8::String> data_2 = v8_str(isolate, "2");
    3134           5 :   context_1->SetEmbedderData(0, data_1);
    3135           5 :   context_2->SetEmbedderData(0, data_2);
    3136           5 :   CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
    3137           5 :   CHECK(context_2->GetEmbedderData(0)->StrictEquals(data_2));
    3138             : 
    3139             :   // Simple test function which causes a break.
    3140             :   const char* source = "function f() { debugger; }";
    3141             : 
    3142             :   // Enter and run function in the first context.
    3143             :   {
    3144             :     v8::Context::Scope context_scope(context_1);
    3145           5 :     expected_context = context_1;
    3146           5 :     expected_context_data = data_1;
    3147           5 :     v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
    3148          15 :     f->Call(context_1, context_1->Global(), 0, nullptr).ToLocalChecked();
    3149             :   }
    3150             : 
    3151             :   // Enter and run function in the second context.
    3152             :   {
    3153             :     v8::Context::Scope context_scope(context_2);
    3154           5 :     expected_context = context_2;
    3155           5 :     expected_context_data = data_2;
    3156           5 :     v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
    3157          15 :     f->Call(context_2, context_2->Global(), 0, nullptr).ToLocalChecked();
    3158             :   }
    3159             : 
    3160             :   // Two times compile event and two times break event.
    3161           5 :   CHECK_GT(event_listener_hit_count, 3);
    3162             : 
    3163           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    3164           5 :   CheckDebuggerUnloaded();
    3165           5 : }
    3166             : 
    3167             : // Test which creates a context and sets embedder data on it. Checks that this
    3168             : // data is set correctly and that when the debug event listener is called for
    3169             : // break event in an eval statement the expected context is the one returned by
    3170             : // Message.GetEventContext.
    3171       28342 : TEST(EvalContextData) {
    3172           5 :   v8::HandleScope scope(CcTest::isolate());
    3173             : 
    3174             :   v8::Local<v8::Context> context_1;
    3175             :   v8::Local<v8::ObjectTemplate> global_template =
    3176             :       v8::Local<v8::ObjectTemplate>();
    3177           5 :   context_1 = v8::Context::New(CcTest::isolate(), nullptr, global_template);
    3178             : 
    3179           5 :   ContextCheckEventListener delegate;
    3180           5 :   v8::debug::SetDebugDelegate(CcTest::isolate(), &delegate);
    3181             : 
    3182             :   // Contexts initially do not have embedder data fields.
    3183           5 :   CHECK_EQ(0, context_1->GetNumberOfEmbedderDataFields());
    3184             : 
    3185             :   // Set and check a data value.
    3186           5 :   v8::Local<v8::String> data_1 = v8_str(CcTest::isolate(), "1");
    3187           5 :   context_1->SetEmbedderData(0, data_1);
    3188           5 :   CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
    3189             : 
    3190             :   // Simple test function with eval that causes a break.
    3191             :   const char* source = "function f() { eval('debugger;'); }";
    3192             : 
    3193             :   // Enter and run function in the context.
    3194             :   {
    3195             :     v8::Context::Scope context_scope(context_1);
    3196           5 :     expected_context = context_1;
    3197           5 :     expected_context_data = data_1;
    3198           5 :     v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f");
    3199          15 :     f->Call(context_1, context_1->Global(), 0, nullptr).ToLocalChecked();
    3200             :   }
    3201             : 
    3202           5 :   v8::debug::SetDebugDelegate(CcTest::isolate(), nullptr);
    3203             : 
    3204             :   // One time compile event and one time break event.
    3205           5 :   CHECK_GT(event_listener_hit_count, 2);
    3206           5 :   CheckDebuggerUnloaded();
    3207           5 : }
    3208             : 
    3209             : // Debug event listener which counts script compiled events.
    3210          20 : class ScriptCompiledDelegate : public v8::debug::DebugDelegate {
    3211             :  public:
    3212          50 :   void ScriptCompiled(v8::Local<v8::debug::Script>, bool,
    3213             :                       bool has_compile_error) override {
    3214          50 :     if (!has_compile_error) {
    3215          35 :       after_compile_event_count++;
    3216             :     } else {
    3217          15 :       compile_error_event_count++;
    3218             :     }
    3219          50 :   }
    3220             : 
    3221             :   int after_compile_event_count = 0;
    3222             :   int compile_error_event_count = 0;
    3223             : };
    3224             : 
    3225             : // Tests that after compile event is sent as many times as there are scripts
    3226             : // compiled.
    3227       28342 : TEST(AfterCompileEventWhenEventListenerIsReset) {
    3228           5 :   LocalContext env;
    3229          10 :   v8::HandleScope scope(env->GetIsolate());
    3230           5 :   v8::Local<v8::Context> context = env.local();
    3231             :   const char* script = "var a=1";
    3232             : 
    3233           5 :   ScriptCompiledDelegate delegate;
    3234           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3235           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
    3236           5 :       .ToLocalChecked()
    3237             :       ->Run(context)
    3238           5 :       .ToLocalChecked();
    3239           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3240             : 
    3241           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3242           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3243           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
    3244           5 :       .ToLocalChecked()
    3245             :       ->Run(context)
    3246           5 :       .ToLocalChecked();
    3247             : 
    3248             :   // Setting listener to nullptr should cause debugger unload.
    3249           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3250             :   CheckDebuggerUnloaded();
    3251             : 
    3252             :   // Compilation cache should be disabled when debugger is active.
    3253          10 :   CHECK_EQ(2, delegate.after_compile_event_count);
    3254           5 : }
    3255             : 
    3256             : // Tests that syntax error event is sent as many times as there are scripts
    3257             : // with syntax error compiled.
    3258       28342 : TEST(SyntaxErrorEventOnSyntaxException) {
    3259           5 :   LocalContext env;
    3260          10 :   v8::HandleScope scope(env->GetIsolate());
    3261             : 
    3262             :   // For this test, we want to break on uncaught exceptions:
    3263           5 :   ChangeBreakOnException(false, true);
    3264             : 
    3265           5 :   ScriptCompiledDelegate delegate;
    3266           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3267           5 :   v8::Local<v8::Context> context = env.local();
    3268             : 
    3269             :   // Check initial state.
    3270           5 :   CHECK_EQ(0, delegate.compile_error_event_count);
    3271             : 
    3272             :   // Throws SyntaxError: Unexpected end of input
    3273          10 :   CHECK(
    3274             :       v8::Script::Compile(context, v8_str(env->GetIsolate(), "+++")).IsEmpty());
    3275           5 :   CHECK_EQ(1, delegate.compile_error_event_count);
    3276             : 
    3277          10 :   CHECK(v8::Script::Compile(context, v8_str(env->GetIsolate(), "/sel\\/: \\"))
    3278             :             .IsEmpty());
    3279           5 :   CHECK_EQ(2, delegate.compile_error_event_count);
    3280             : 
    3281             :   v8::Local<v8::Script> script =
    3282             :       v8::Script::Compile(context,
    3283           5 :                           v8_str(env->GetIsolate(), "JSON.parse('1234:')"))
    3284           5 :           .ToLocalChecked();
    3285           5 :   CHECK_EQ(2, delegate.compile_error_event_count);
    3286          10 :   CHECK(script->Run(context).IsEmpty());
    3287           5 :   CHECK_EQ(3, delegate.compile_error_event_count);
    3288             : 
    3289             :   v8::Script::Compile(context,
    3290           5 :                       v8_str(env->GetIsolate(), "new RegExp('/\\/\\\\');"))
    3291           5 :       .ToLocalChecked();
    3292           5 :   CHECK_EQ(3, delegate.compile_error_event_count);
    3293             : 
    3294           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), "throw 1;"))
    3295           5 :       .ToLocalChecked();
    3296          10 :   CHECK_EQ(3, delegate.compile_error_event_count);
    3297           5 : }
    3298             : 
    3299             : // Tests that break event is sent when event listener is reset.
    3300       28342 : TEST(BreakEventWhenEventListenerIsReset) {
    3301           5 :   LocalContext env;
    3302          10 :   v8::HandleScope scope(env->GetIsolate());
    3303           5 :   v8::Local<v8::Context> context = env.local();
    3304             :   const char* script = "function f() {};";
    3305             : 
    3306           5 :   ScriptCompiledDelegate delegate;
    3307           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3308           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
    3309           5 :       .ToLocalChecked()
    3310             :       ->Run(context)
    3311           5 :       .ToLocalChecked();
    3312           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3313             : 
    3314           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3315           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3316             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
    3317             :       env->Global()
    3318          15 :           ->Get(context, v8_str(env->GetIsolate(), "f"))
    3319           5 :           .ToLocalChecked());
    3320          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3321             : 
    3322             :   // Setting event listener to nullptr should cause debugger unload.
    3323           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3324             :   CheckDebuggerUnloaded();
    3325             : 
    3326             :   // Compilation cache should be disabled when debugger is active.
    3327          10 :   CHECK_EQ(1, delegate.after_compile_event_count);
    3328           5 : }
    3329             : 
    3330             : // Tests that script is reported as compiled when bound to context.
    3331       28342 : TEST(AfterCompileEventOnBindToContext) {
    3332           5 :   LocalContext env;
    3333           5 :   v8::Isolate* isolate = env->GetIsolate();
    3334          10 :   v8::HandleScope handle_scope(isolate);
    3335           5 :   ScriptCompiledDelegate delegate;
    3336           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3337             : 
    3338             :   const char* source = "var a=1";
    3339             :   v8::ScriptCompiler::Source script_source(
    3340             :       v8::String::NewFromUtf8(isolate, source, v8::NewStringType::kNormal)
    3341           5 :           .ToLocalChecked());
    3342             : 
    3343             :   v8::Local<v8::UnboundScript> unbound =
    3344             :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
    3345           5 :           .ToLocalChecked();
    3346           5 :   CHECK_EQ(delegate.after_compile_event_count, 0);
    3347             : 
    3348           5 :   unbound->BindToCurrentContext();
    3349           5 :   CHECK_EQ(delegate.after_compile_event_count, 1);
    3350          10 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    3351           5 : }
    3352             : 
    3353             : 
    3354             : // Test that if DebugBreak is forced it is ignored when code from
    3355             : // debug-delay.js is executed.
    3356       28342 : TEST(NoDebugBreakInAfterCompileEventListener) {
    3357           5 :   LocalContext env;
    3358          10 :   v8::HandleScope scope(env->GetIsolate());
    3359           5 :   v8::Local<v8::Context> context = env.local();
    3360             : 
    3361             :   // Register a debug event listener which sets the break flag and counts.
    3362           5 :   DebugEventCounter delegate;
    3363           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3364             : 
    3365             :   // Set the debug break flag.
    3366           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3367             : 
    3368             :   // Create a function for testing stepping.
    3369             :   const char* src = "function f() { eval('var x = 10;'); } ";
    3370           5 :   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
    3371             : 
    3372             :   // There should be only one break event.
    3373           5 :   CHECK_EQ(1, break_point_hit_count);
    3374             : 
    3375             :   // Set the debug break flag again.
    3376           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3377          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3378             :   // There should be one more break event when the script is evaluated in 'f'.
    3379           5 :   CHECK_EQ(2, break_point_hit_count);
    3380             : 
    3381             :   // Get rid of the debug event listener.
    3382           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3383           5 :   CheckDebuggerUnloaded();
    3384           5 : }
    3385             : 
    3386             : 
    3387             : // Test that the debug break flag works with function.apply.
    3388       28342 : TEST(DebugBreakFunctionApply) {
    3389           5 :   LocalContext env;
    3390          10 :   v8::HandleScope scope(env->GetIsolate());
    3391           5 :   v8::Local<v8::Context> context = env.local();
    3392             : 
    3393             :   // Create a function for testing breaking in apply.
    3394             :   v8::Local<v8::Function> foo = CompileFunction(
    3395             :       &env,
    3396             :       "function baz(x) { }"
    3397             :       "function bar(x) { baz(); }"
    3398             :       "function foo(){ bar.apply(this, [1]); }",
    3399           5 :       "foo");
    3400             : 
    3401             :   // Register a debug event listener which steps and counts.
    3402           5 :   DebugEventBreakMax delegate;
    3403           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3404             : 
    3405             :   // Set the debug break flag before calling the code using function.apply.
    3406           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3407             : 
    3408             :   // Limit the number of debug breaks. This is a regression test for issue 493
    3409             :   // where this test would enter an infinite loop.
    3410           5 :   break_point_hit_count = 0;
    3411           5 :   max_break_point_hit_count = 10000;  // 10000 => infinite loop.
    3412          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3413             : 
    3414             :   // When keeping the debug break several break will happen.
    3415           5 :   CHECK_GT(break_point_hit_count, 1);
    3416             : 
    3417           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3418           5 :   CheckDebuggerUnloaded();
    3419           5 : }
    3420             : 
    3421             : // Test that setting the terminate execution flag during debug break processing.
    3422          60 : static void TestDebugBreakInLoop(const char* loop_head,
    3423             :                                  const char** loop_bodies,
    3424             :                                  const char* loop_tail) {
    3425             :   // Receive 10 breaks for each test and then terminate JavaScript execution.
    3426             :   static const int kBreaksPerTest = 10;
    3427             : 
    3428         390 :   for (int i = 0; loop_bodies[i] != nullptr; i++) {
    3429             :     // Perform a lazy deoptimization after various numbers of breaks
    3430             :     // have been hit.
    3431             : 
    3432             :     i::EmbeddedVector<char, 1024> buffer;
    3433             :     SNPrintF(buffer, "function f() {%s%s%s}", loop_head, loop_bodies[i],
    3434         330 :              loop_tail);
    3435             : 
    3436         330 :     i::PrintF("%s\n", buffer.start());
    3437             : 
    3438        1320 :     for (int j = 0; j < 3; j++) {
    3439         990 :       break_point_hit_count_deoptimize = j;
    3440         990 :       if (j == 2) {
    3441         330 :         break_point_hit_count_deoptimize = kBreaksPerTest;
    3442             :       }
    3443             : 
    3444         990 :       break_point_hit_count = 0;
    3445         990 :       max_break_point_hit_count = kBreaksPerTest;
    3446         990 :       terminate_after_max_break_point_hit = true;
    3447             : 
    3448             :       // Function with infinite loop.
    3449         990 :       CompileRun(buffer.start());
    3450             : 
    3451             :       // Set the debug break to enter the debugger as soon as possible.
    3452         990 :       v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
    3453             : 
    3454             :       // Call function with infinite loop.
    3455             :       CompileRun("f();");
    3456         990 :       CHECK_EQ(kBreaksPerTest, break_point_hit_count);
    3457             : 
    3458         990 :       CHECK(!CcTest::isolate()->IsExecutionTerminating());
    3459             :     }
    3460             :   }
    3461          60 : }
    3462             : 
    3463             : static const char* loop_bodies_1[] = {"",
    3464             :                                       "g()",
    3465             :                                       "if (a == 0) { g() }",
    3466             :                                       "if (a == 1) { g() }",
    3467             :                                       "if (a == 0) { g() } else { h() }",
    3468             :                                       "if (a == 0) { continue }",
    3469             :                                       nullptr};
    3470             : 
    3471             : static const char* loop_bodies_2[] = {
    3472             :     "if (a == 1) { continue }",
    3473             :     "switch (a) { case 1: g(); }",
    3474             :     "switch (a) { case 1: continue; }",
    3475             :     "switch (a) { case 1: g(); break; default: h() }",
    3476             :     "switch (a) { case 1: continue; break; default: h() }",
    3477             :     nullptr};
    3478             : 
    3479          60 : void DebugBreakLoop(const char* loop_header, const char** loop_bodies,
    3480             :                     const char* loop_footer) {
    3481          60 :   LocalContext env;
    3482         120 :   v8::HandleScope scope(env->GetIsolate());
    3483             : 
    3484             :   // Register a debug event listener which sets the break flag and counts.
    3485          60 :   DebugEventBreakMax delegate;
    3486          60 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3487             : 
    3488             :   CompileRun(
    3489             :       "var a = 1;\n"
    3490             :       "function g() { }\n"
    3491             :       "function h() { }");
    3492             : 
    3493          60 :   TestDebugBreakInLoop(loop_header, loop_bodies, loop_footer);
    3494             : 
    3495             :   // Get rid of the debug event listener.
    3496          60 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3497          60 :   CheckDebuggerUnloaded();
    3498          60 : }
    3499             : 
    3500             : 
    3501       28342 : TEST(DebugBreakInWhileTrue1) {
    3502           5 :   DebugBreakLoop("while (true) {", loop_bodies_1, "}");
    3503           5 : }
    3504             : 
    3505             : 
    3506       28342 : TEST(DebugBreakInWhileTrue2) {
    3507           5 :   DebugBreakLoop("while (true) {", loop_bodies_2, "}");
    3508           5 : }
    3509             : 
    3510             : 
    3511       28342 : TEST(DebugBreakInWhileCondition1) {
    3512           5 :   DebugBreakLoop("while (a == 1) {", loop_bodies_1, "}");
    3513           5 : }
    3514             : 
    3515             : 
    3516       28342 : TEST(DebugBreakInWhileCondition2) {
    3517           5 :   DebugBreakLoop("while (a == 1) {", loop_bodies_2, "}");
    3518           5 : }
    3519             : 
    3520             : 
    3521       28342 : TEST(DebugBreakInDoWhileTrue1) {
    3522           5 :   DebugBreakLoop("do {", loop_bodies_1, "} while (true)");
    3523           5 : }
    3524             : 
    3525             : 
    3526       28342 : TEST(DebugBreakInDoWhileTrue2) {
    3527           5 :   DebugBreakLoop("do {", loop_bodies_2, "} while (true)");
    3528           5 : }
    3529             : 
    3530             : 
    3531       28342 : TEST(DebugBreakInDoWhileCondition1) {
    3532           5 :   DebugBreakLoop("do {", loop_bodies_1, "} while (a == 1)");
    3533           5 : }
    3534             : 
    3535             : 
    3536       28342 : TEST(DebugBreakInDoWhileCondition2) {
    3537           5 :   DebugBreakLoop("do {", loop_bodies_2, "} while (a == 1)");
    3538           5 : }
    3539             : 
    3540             : 
    3541       28342 : TEST(DebugBreakInFor1) { DebugBreakLoop("for (;;) {", loop_bodies_1, "}"); }
    3542             : 
    3543             : 
    3544       28342 : TEST(DebugBreakInFor2) { DebugBreakLoop("for (;;) {", loop_bodies_2, "}"); }
    3545             : 
    3546             : 
    3547       28342 : TEST(DebugBreakInForCondition1) {
    3548           5 :   DebugBreakLoop("for (;a == 1;) {", loop_bodies_1, "}");
    3549           5 : }
    3550             : 
    3551             : 
    3552       28342 : TEST(DebugBreakInForCondition2) {
    3553           5 :   DebugBreakLoop("for (;a == 1;) {", loop_bodies_2, "}");
    3554           5 : }
    3555             : 
    3556           5 : class DebugBreakInlineListener : public v8::debug::DebugDelegate {
    3557             :  public:
    3558           5 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3559             :                              const std::vector<v8::debug::BreakpointId>&
    3560             :                                  inspector_break_points_hit) override {
    3561             :     int expected_frame_count = 4;
    3562           5 :     int expected_line_number[] = {1, 4, 7, 12};
    3563             : 
    3564             :     int frame_count = 0;
    3565           5 :     auto iterator = v8::debug::StackTraceIterator::Create(CcTest::isolate());
    3566          50 :     for (; !iterator->Done(); iterator->Advance(), ++frame_count) {
    3567          20 :       v8::debug::Location loc = iterator->GetSourceLocation();
    3568          20 :       CHECK_EQ(expected_line_number[frame_count], loc.GetLineNumber());
    3569             :     }
    3570           5 :     CHECK_EQ(frame_count, expected_frame_count);
    3571           5 :   }
    3572             : };
    3573             : 
    3574       28342 : TEST(DebugBreakInline) {
    3575           5 :   i::FLAG_allow_natives_syntax = true;
    3576           5 :   LocalContext env;
    3577          10 :   v8::HandleScope scope(env->GetIsolate());
    3578           5 :   v8::Local<v8::Context> context = env.local();
    3579             :   const char* source =
    3580             :       "function debug(b) {             \n"
    3581             :       "  if (b) debugger;              \n"
    3582             :       "}                               \n"
    3583             :       "function f(b) {                 \n"
    3584             :       "  debug(b)                      \n"
    3585             :       "};                              \n"
    3586             :       "function g(b) {                 \n"
    3587             :       "  f(b);                         \n"
    3588             :       "};                              \n"
    3589             :       "g(false);                       \n"
    3590             :       "g(false);                       \n"
    3591             :       "%OptimizeFunctionOnNextCall(g); \n"
    3592             :       "g(true);";
    3593           5 :   DebugBreakInlineListener delegate;
    3594           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3595             :   v8::Local<v8::Script> inline_script =
    3596           5 :       v8::Script::Compile(context, v8_str(env->GetIsolate(), source))
    3597           5 :           .ToLocalChecked();
    3598           5 :   inline_script->Run(context).ToLocalChecked();
    3599          10 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3600           5 : }
    3601             : 
    3602           5 : static void RunScriptInANewCFrame(const char* source) {
    3603           5 :   v8::TryCatch try_catch(CcTest::isolate());
    3604             :   CompileRun(source);
    3605           5 :   CHECK(try_catch.HasCaught());
    3606           5 : }
    3607             : 
    3608             : 
    3609       28342 : TEST(Regress131642) {
    3610             :   // Bug description:
    3611             :   // When doing StepNext through the first script, the debugger is not reset
    3612             :   // after exiting through exception.  A flawed implementation enabling the
    3613             :   // debugger to step into Array.prototype.forEach breaks inside the callback
    3614             :   // for forEach in the second script under the assumption that we are in a
    3615             :   // recursive call.  In an attempt to step out, we crawl the stack using the
    3616             :   // recorded frame pointer from the first script and fail when not finding it
    3617             :   // on the stack.
    3618           5 :   LocalContext env;
    3619          10 :   v8::HandleScope scope(env->GetIsolate());
    3620           5 :   DebugEventCounter delegate;
    3621             :   delegate.set_step_action(StepNext);
    3622           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3623             : 
    3624             :   // We step through the first script.  It exits through an exception.  We run
    3625             :   // this inside a new frame to record a different FP than the second script
    3626             :   // would expect.
    3627             :   const char* script_1 = "debugger; throw new Error();";
    3628           5 :   RunScriptInANewCFrame(script_1);
    3629             : 
    3630             :   // The second script uses forEach.
    3631             :   const char* script_2 = "[0].forEach(function() { });";
    3632             :   CompileRun(script_2);
    3633             : 
    3634          10 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3635           5 : }
    3636             : 
    3637           5 : class DebugBreakStackTraceListener : public v8::debug::DebugDelegate {
    3638             :  public:
    3639           0 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3640             :                              const std::vector<v8::debug::BreakpointId>&
    3641             :                                  inspector_break_points_hit) override {
    3642           0 :     v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
    3643           0 :   }
    3644             : };
    3645             : 
    3646        5000 : static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
    3647        5000 :   v8::debug::SetBreakOnNextFunctionCall(args.GetIsolate());
    3648        5000 : }
    3649             : 
    3650       28342 : TEST(DebugBreakStackTrace) {
    3651           5 :   LocalContext env;
    3652          10 :   v8::HandleScope scope(env->GetIsolate());
    3653           5 :   DebugBreakStackTraceListener delegate;
    3654           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3655           5 :   v8::Local<v8::Context> context = env.local();
    3656             :   v8::Local<v8::FunctionTemplate> add_debug_break_template =
    3657           5 :       v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
    3658             :   v8::Local<v8::Function> add_debug_break =
    3659           5 :       add_debug_break_template->GetFunction(context).ToLocalChecked();
    3660          20 :   CHECK(env->Global()
    3661             :             ->Set(context, v8_str("add_debug_break"), add_debug_break)
    3662             :             .FromJust());
    3663             : 
    3664             :   CompileRun("(function loop() {"
    3665             :              "  for (var j = 0; j < 1000; j++) {"
    3666             :              "    for (var i = 0; i < 1000; i++) {"
    3667             :              "      if (i == 999) add_debug_break();"
    3668             :              "    }"
    3669             :              "  }"
    3670           5 :              "})()");
    3671           5 : }
    3672             : 
    3673             : 
    3674       28337 : v8::base::Semaphore terminate_requested_semaphore(0);
    3675       28337 : v8::base::Semaphore terminate_fired_semaphore(0);
    3676             : 
    3677           5 : class DebugBreakTriggerTerminate : public v8::debug::DebugDelegate {
    3678             :  public:
    3679           5 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3680             :                              const std::vector<v8::debug::BreakpointId>&
    3681             :                                  inspector_break_points_hit) override {
    3682          10 :     if (terminate_already_fired_) return;
    3683           5 :     terminate_requested_semaphore.Signal();
    3684             :     // Wait for at most 2 seconds for the terminate request.
    3685           5 :     CHECK(
    3686             :         terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
    3687           5 :     terminate_already_fired_ = true;
    3688             :   }
    3689             : 
    3690             :  private:
    3691             :   bool terminate_already_fired_ = false;
    3692             : };
    3693             : 
    3694           5 : class TerminationThread : public v8::base::Thread {
    3695             :  public:
    3696             :   explicit TerminationThread(v8::Isolate* isolate)
    3697           5 :       : Thread(Options("terminator")), isolate_(isolate) {}
    3698             : 
    3699           5 :   void Run() override {
    3700           5 :     terminate_requested_semaphore.Wait();
    3701           5 :     isolate_->TerminateExecution();
    3702           5 :     terminate_fired_semaphore.Signal();
    3703           5 :   }
    3704             : 
    3705             :  private:
    3706             :   v8::Isolate* isolate_;
    3707             : };
    3708             : 
    3709             : 
    3710       28342 : TEST(DebugBreakOffThreadTerminate) {
    3711           5 :   LocalContext env;
    3712           5 :   v8::Isolate* isolate = env->GetIsolate();
    3713          10 :   v8::HandleScope scope(isolate);
    3714           5 :   DebugBreakTriggerTerminate delegate;
    3715           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3716             :   TerminationThread terminator(isolate);
    3717           5 :   terminator.Start();
    3718          10 :   v8::TryCatch try_catch(env->GetIsolate());
    3719           5 :   env->GetIsolate()->RequestInterrupt(BreakRightNow, nullptr);
    3720             :   CompileRun("while (true);");
    3721          10 :   CHECK(try_catch.HasTerminated());
    3722           5 : }
    3723             : 
    3724          50 : class ArchiveRestoreThread : public v8::base::Thread,
    3725             :                              public v8::debug::DebugDelegate {
    3726             :  public:
    3727             :   ArchiveRestoreThread(v8::Isolate* isolate, int spawn_count)
    3728             :       : Thread(Options("ArchiveRestoreThread")),
    3729             :         isolate_(isolate),
    3730          25 :         debug_(reinterpret_cast<i::Isolate*>(isolate_)->debug()),
    3731             :         spawn_count_(spawn_count),
    3732          75 :         break_count_(0) {}
    3733             : 
    3734          25 :   void Run() override {
    3735          25 :     v8::Locker locker(isolate_);
    3736          25 :     isolate_->Enter();
    3737             : 
    3738          50 :     v8::HandleScope scope(isolate_);
    3739          25 :     v8::Local<v8::Context> context = v8::Context::New(isolate_);
    3740             :     v8::Context::Scope context_scope(context);
    3741             : 
    3742             :     v8::Local<v8::Function> test = CompileFunction(isolate_,
    3743             :                                                    "function test(n) {\n"
    3744             :                                                    "  debugger;\n"
    3745             :                                                    "  return n + 1;\n"
    3746             :                                                    "}\n",
    3747          25 :                                                    "test");
    3748             : 
    3749          25 :     debug_->SetDebugDelegate(this);
    3750          25 :     v8::internal::DisableBreak enable_break(debug_, false);
    3751             : 
    3752          25 :     v8::Local<v8::Value> args[1] = {v8::Integer::New(isolate_, spawn_count_)};
    3753             : 
    3754          50 :     int result = test->Call(context, context->Global(), 1, args)
    3755          25 :                      .ToLocalChecked()
    3756             :                      ->Int32Value(context)
    3757          50 :                      .FromJust();
    3758             : 
    3759             :     // Verify that test(spawn_count_) returned spawn_count_ + 1.
    3760          25 :     CHECK_EQ(spawn_count_ + 1, result);
    3761             : 
    3762          50 :     isolate_->Exit();
    3763          25 :   }
    3764             : 
    3765          50 :   void BreakProgramRequested(
    3766             :       v8::Local<v8::Context> context,
    3767             :       const std::vector<v8::debug::BreakpointId>&) override {
    3768          50 :     auto stack_traces = v8::debug::StackTraceIterator::Create(isolate_);
    3769          50 :     if (!stack_traces->Done()) {
    3770          50 :       v8::debug::Location location = stack_traces->GetSourceLocation();
    3771             : 
    3772             :       i::PrintF("ArchiveRestoreThread #%d hit breakpoint at line %d\n",
    3773          50 :                 spawn_count_, location.GetLineNumber());
    3774             : 
    3775          50 :       switch (location.GetLineNumber()) {
    3776             :         case 1:  // debugger;
    3777          25 :           CHECK_EQ(break_count_, 0);
    3778             : 
    3779             :           // Attempt to stop on the next line after the first debugger
    3780             :           // statement. If debug->{Archive,Restore}Debug() improperly reset
    3781             :           // thread-local debug information, the debugger will fail to stop
    3782             :           // before the test function returns.
    3783          25 :           debug_->PrepareStep(StepNext);
    3784             : 
    3785             :           // Spawning threads while handling the current breakpoint verifies
    3786             :           // that the parent thread correctly archived and restored the
    3787             :           // state necessary to stop on the next line. If not, then control
    3788             :           // will simply continue past the `return n + 1` statement.
    3789          25 :           MaybeSpawnChildThread();
    3790             : 
    3791          25 :           break;
    3792             : 
    3793             :         case 2:  // return n + 1;
    3794          25 :           CHECK_EQ(break_count_, 1);
    3795             :           break;
    3796             : 
    3797             :         default:
    3798           0 :           CHECK(false);
    3799             :       }
    3800             :     }
    3801             : 
    3802          50 :     ++break_count_;
    3803          50 :   }
    3804             : 
    3805          25 :   void MaybeSpawnChildThread() {
    3806          25 :     if (spawn_count_ > 1) {
    3807          20 :       v8::Unlocker unlocker(isolate_);
    3808             : 
    3809             :       // Spawn a thread that spawns a thread that spawns a thread (and so
    3810             :       // on) so that the ThreadManager is forced to archive and restore
    3811             :       // the current thread.
    3812          20 :       ArchiveRestoreThread child(isolate_, spawn_count_ - 1);
    3813          20 :       child.Start();
    3814          20 :       child.Join();
    3815             : 
    3816             :       // The child thread sets itself as the debug delegate, so we need to
    3817             :       // usurp it after the child finishes, or else future breakpoints
    3818             :       // will be delegated to a destroyed ArchiveRestoreThread object.
    3819          20 :       debug_->SetDebugDelegate(this);
    3820             : 
    3821             :       // This is the most important check in this test, since
    3822             :       // child.GetBreakCount() will return 1 if the debugger fails to stop
    3823             :       // on the `return n + 1` line after the grandchild thread returns.
    3824          40 :       CHECK_EQ(child.GetBreakCount(), 2);
    3825             :     }
    3826          25 :   }
    3827             : 
    3828             :   int GetBreakCount() { return break_count_; }
    3829             : 
    3830             :  private:
    3831             :   v8::Isolate* isolate_;
    3832             :   v8::internal::Debug* debug_;
    3833             :   const int spawn_count_;
    3834             :   int break_count_;
    3835             : };
    3836             : 
    3837       28342 : TEST(DebugArchiveRestore) {
    3838             :   v8::Isolate::CreateParams create_params;
    3839           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3840           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    3841             : 
    3842             :   ArchiveRestoreThread thread(isolate, 5);
    3843             :   // Instead of calling thread.Start() and thread.Join() here, we call
    3844             :   // thread.Run() directly, to make sure we exercise archive/restore
    3845             :   // logic on the *current* thread as well as other threads.
    3846           5 :   thread.Run();
    3847           5 :   CHECK_EQ(thread.GetBreakCount(), 2);
    3848             : 
    3849           5 :   isolate->Dispose();
    3850           5 : }
    3851             : 
    3852           5 : class DebugEventExpectNoException : public v8::debug::DebugDelegate {
    3853             :  public:
    3854           0 :   void ExceptionThrown(v8::Local<v8::Context> paused_context,
    3855             :                        v8::Local<v8::Value> exception,
    3856             :                        v8::Local<v8::Value> promise, bool is_uncaught,
    3857             :                        v8::debug::ExceptionType) override {
    3858           0 :     CHECK(false);
    3859             :   }
    3860             : };
    3861             : 
    3862           5 : static void TryCatchWrappedThrowCallback(
    3863           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    3864           5 :   v8::TryCatch try_catch(args.GetIsolate());
    3865             :   CompileRun("throw 'rejection';");
    3866           5 :   CHECK(try_catch.HasCaught());
    3867           5 : }
    3868             : 
    3869       28342 : TEST(DebugPromiseInterceptedByTryCatch) {
    3870           5 :   LocalContext env;
    3871           5 :   v8::Isolate* isolate = env->GetIsolate();
    3872          10 :   v8::HandleScope scope(isolate);
    3873           5 :   DebugEventExpectNoException delegate;
    3874           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3875           5 :   v8::Local<v8::Context> context = env.local();
    3876           5 :   ChangeBreakOnException(false, true);
    3877             : 
    3878             :   v8::Local<v8::FunctionTemplate> fun =
    3879           5 :       v8::FunctionTemplate::New(isolate, TryCatchWrappedThrowCallback);
    3880          25 :   CHECK(env->Global()
    3881             :             ->Set(context, v8_str("fun"),
    3882             :                   fun->GetFunction(context).ToLocalChecked())
    3883             :             .FromJust());
    3884             : 
    3885             :   CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
    3886             :   CompileRun(
    3887             :       "var r;"
    3888             :       "p.then(function() { r = 'resolved'; },"
    3889             :       "       function() { r = 'rejected'; });");
    3890          20 :   CHECK(CompileRun("r")->Equals(context, v8_str("resolved")).FromJust());
    3891           5 : }
    3892             : 
    3893           5 : class NoInterruptsOnDebugEvent : public v8::debug::DebugDelegate {
    3894             :  public:
    3895           5 :   void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
    3896             :                       bool has_compile_error) override {
    3897           5 :     ++after_compile_handler_depth_;
    3898             :     // Do not allow nested AfterCompile events.
    3899           5 :     CHECK_LE(after_compile_handler_depth_, 1);
    3900           5 :     v8::Isolate* isolate = CcTest::isolate();
    3901           5 :     v8::Isolate::AllowJavascriptExecutionScope allow_script(isolate);
    3902           5 :     isolate->RequestInterrupt(&HandleInterrupt, this);
    3903             :     CompileRun("function foo() {}; foo();");
    3904           5 :     --after_compile_handler_depth_;
    3905           5 :   }
    3906             : 
    3907             :  private:
    3908           5 :   static void HandleInterrupt(v8::Isolate* isolate, void* data) {
    3909             :     NoInterruptsOnDebugEvent* d = static_cast<NoInterruptsOnDebugEvent*>(data);
    3910           5 :     CHECK_EQ(0, d->after_compile_handler_depth_);
    3911           5 :   }
    3912             : 
    3913             :   int after_compile_handler_depth_ = 0;
    3914             : };
    3915             : 
    3916       28342 : TEST(NoInterruptsInDebugListener) {
    3917           5 :   LocalContext env;
    3918          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    3919           5 :   NoInterruptsOnDebugEvent delegate;
    3920           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3921           5 :   CompileRun("void(0);");
    3922           5 : }
    3923             : 
    3924       28342 : TEST(BreakLocationIterator) {
    3925           5 :   LocalContext env;
    3926           5 :   v8::Isolate* isolate = env->GetIsolate();
    3927          10 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    3928          10 :   v8::HandleScope scope(isolate);
    3929             : 
    3930             :   v8::Local<v8::Value> result = CompileRun(
    3931             :       "function f() {\n"
    3932             :       "  debugger;   \n"
    3933             :       "  f();        \n"
    3934             :       "  debugger;   \n"
    3935             :       "}             \n"
    3936             :       "f");
    3937           5 :   Handle<i::Object> function_obj = v8::Utils::OpenHandle(*result);
    3938           5 :   Handle<i::JSFunction> function = Handle<i::JSFunction>::cast(function_obj);
    3939          10 :   Handle<i::SharedFunctionInfo> shared(function->shared(), i_isolate);
    3940             : 
    3941             :   EnableDebugger(isolate);
    3942           5 :   CHECK(i_isolate->debug()->EnsureBreakInfo(shared));
    3943           5 :   i_isolate->debug()->PrepareFunctionForDebugExecution(shared);
    3944             : 
    3945          10 :   Handle<i::DebugInfo> debug_info(shared->GetDebugInfo(), i_isolate);
    3946             : 
    3947             :   {
    3948           5 :     i::BreakIterator iterator(debug_info);
    3949           5 :     CHECK(iterator.GetBreakLocation().IsDebuggerStatement());
    3950           5 :     CHECK_EQ(17, iterator.GetBreakLocation().position());
    3951           5 :     iterator.Next();
    3952          10 :     CHECK(iterator.GetBreakLocation().IsDebugBreakSlot());
    3953           5 :     CHECK_EQ(32, iterator.GetBreakLocation().position());
    3954           5 :     iterator.Next();
    3955           5 :     CHECK(iterator.GetBreakLocation().IsCall());
    3956           5 :     CHECK_EQ(32, iterator.GetBreakLocation().position());
    3957           5 :     iterator.Next();
    3958           5 :     CHECK(iterator.GetBreakLocation().IsDebuggerStatement());
    3959           5 :     CHECK_EQ(47, iterator.GetBreakLocation().position());
    3960           5 :     iterator.Next();
    3961           5 :     CHECK(iterator.GetBreakLocation().IsReturn());
    3962           5 :     CHECK_EQ(60, iterator.GetBreakLocation().position());
    3963           5 :     iterator.Next();
    3964           5 :     CHECK(iterator.Done());
    3965             :   }
    3966             : 
    3967           5 :   DisableDebugger(isolate);
    3968           5 : }
    3969             : 
    3970           5 : class DebugStepOverFunctionWithCaughtExceptionListener
    3971             :     : public v8::debug::DebugDelegate {
    3972             :  public:
    3973          15 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3974             :                              const std::vector<v8::debug::BreakpointId>&
    3975             :                                  inspector_break_points_hit) override {
    3976          15 :     ++break_point_hit_count;
    3977          30 :     if (break_point_hit_count >= 3) return;
    3978          10 :     PrepareStep(StepNext);
    3979             :   }
    3980             :   int break_point_hit_count = 0;
    3981             : };
    3982             : 
    3983       28342 : TEST(DebugStepOverFunctionWithCaughtException) {
    3984           5 :   i::FLAG_allow_natives_syntax = true;
    3985             : 
    3986           5 :   LocalContext env;
    3987           5 :   v8::Isolate* isolate = env->GetIsolate();
    3988          10 :   v8::HandleScope scope(isolate);
    3989           5 :   DebugStepOverFunctionWithCaughtExceptionListener delegate;
    3990           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3991             : 
    3992             :   CompileRun(
    3993             :       "function foo() {\n"
    3994             :       "  try { throw new Error(); } catch (e) {}\n"
    3995             :       "}\n"
    3996             :       "debugger;\n"
    3997             :       "foo();\n"
    3998             :       "foo();\n");
    3999             : 
    4000           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    4001          10 :   CHECK_EQ(3, delegate.break_point_hit_count);
    4002           5 : }
    4003             : 
    4004             : bool near_heap_limit_callback_called = false;
    4005           5 : size_t NearHeapLimitCallback(void* data, size_t current_heap_limit,
    4006             :                              size_t initial_heap_limit) {
    4007           5 :   near_heap_limit_callback_called = true;
    4008           5 :   return initial_heap_limit + 10u * i::MB;
    4009             : }
    4010             : 
    4011       28342 : UNINITIALIZED_TEST(DebugSetOutOfMemoryListener) {
    4012             :   v8::Isolate::CreateParams create_params;
    4013           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    4014             :   create_params.constraints.set_max_old_space_size(10);
    4015           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    4016             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    4017             :   {
    4018             :     v8::Isolate::Scope i_scope(isolate);
    4019          10 :     v8::HandleScope scope(isolate);
    4020           5 :     LocalContext context(isolate);
    4021           5 :     isolate->AddNearHeapLimitCallback(NearHeapLimitCallback, nullptr);
    4022           5 :     CHECK(!near_heap_limit_callback_called);
    4023             :     // The following allocation fails unless the out-of-memory callback
    4024             :     // increases the heap limit.
    4025             :     int length = 10 * i::MB / i::kPointerSize;
    4026           5 :     i_isolate->factory()->NewFixedArray(length, i::TENURED);
    4027           5 :     CHECK(near_heap_limit_callback_called);
    4028           5 :     isolate->RemoveNearHeapLimitCallback(NearHeapLimitCallback, 0);
    4029             :   }
    4030           5 :   isolate->Dispose();
    4031           5 : }
    4032             : 
    4033       28342 : TEST(DebugCoverage) {
    4034             :   // Coverage needs feedback vectors.
    4035           5 :   if (i::FLAG_lite_mode) return;
    4036           5 :   i::FLAG_always_opt = false;
    4037           5 :   LocalContext env;
    4038           5 :   v8::Isolate* isolate = env->GetIsolate();
    4039          10 :   v8::HandleScope scope(isolate);
    4040           5 :   v8::debug::Coverage::SelectMode(isolate, v8::debug::Coverage::kPreciseCount);
    4041             :   v8::Local<v8::String> source = v8_str(
    4042             :       "function f() {\n"
    4043             :       "}\n"
    4044             :       "f();\n"
    4045           5 :       "f();");
    4046           5 :   CompileRun(source);
    4047           5 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(isolate);
    4048           5 :   CHECK_EQ(1u, coverage.ScriptCount());
    4049           5 :   v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(0);
    4050           5 :   v8::Local<v8::debug::Script> script = script_data.GetScript();
    4051          15 :   CHECK(script->Source()
    4052             :             .ToLocalChecked()
    4053             :             ->Equals(env.local(), source)
    4054             :             .FromMaybe(false));
    4055             : 
    4056           5 :   CHECK_EQ(2u, script_data.FunctionCount());
    4057             :   v8::debug::Coverage::FunctionData function_data =
    4058           5 :       script_data.GetFunctionData(0);
    4059             :   v8::debug::Location start =
    4060           5 :       script->GetSourceLocation(function_data.StartOffset());
    4061             :   v8::debug::Location end =
    4062           5 :       script->GetSourceLocation(function_data.EndOffset());
    4063           5 :   CHECK_EQ(0, start.GetLineNumber());
    4064           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4065           5 :   CHECK_EQ(3, end.GetLineNumber());
    4066           5 :   CHECK_EQ(4, end.GetColumnNumber());
    4067           5 :   CHECK_EQ(1, function_data.Count());
    4068             : 
    4069          10 :   function_data = script_data.GetFunctionData(1);
    4070           5 :   start = script->GetSourceLocation(function_data.StartOffset());
    4071           5 :   end = script->GetSourceLocation(function_data.EndOffset());
    4072           5 :   CHECK_EQ(0, start.GetLineNumber());
    4073           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4074           5 :   CHECK_EQ(1, end.GetLineNumber());
    4075           5 :   CHECK_EQ(1, end.GetColumnNumber());
    4076          10 :   CHECK_EQ(2, function_data.Count());
    4077             : }
    4078             : 
    4079             : namespace {
    4080           5 : v8::debug::Coverage::ScriptData GetScriptDataAndDeleteCoverage(
    4081             :     v8::Isolate* isolate) {
    4082           5 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(isolate);
    4083           5 :   CHECK_EQ(1u, coverage.ScriptCount());
    4084          10 :   return coverage.GetScriptData(0);
    4085             : }
    4086             : }  // namespace
    4087             : 
    4088       28342 : TEST(DebugCoverageWithCoverageOutOfScope) {
    4089             :   // Coverage needs feedback vectors.
    4090           5 :   if (i::FLAG_lite_mode) return;
    4091           5 :   i::FLAG_always_opt = false;
    4092           5 :   LocalContext env;
    4093           5 :   v8::Isolate* isolate = env->GetIsolate();
    4094          10 :   v8::HandleScope scope(isolate);
    4095           5 :   v8::debug::Coverage::SelectMode(isolate, v8::debug::Coverage::kPreciseCount);
    4096             :   v8::Local<v8::String> source = v8_str(
    4097             :       "function f() {\n"
    4098             :       "}\n"
    4099             :       "f();\n"
    4100           5 :       "f();");
    4101           5 :   CompileRun(source);
    4102             :   v8::debug::Coverage::ScriptData script_data =
    4103           5 :       GetScriptDataAndDeleteCoverage(isolate);
    4104           5 :   v8::Local<v8::debug::Script> script = script_data.GetScript();
    4105          15 :   CHECK(script->Source()
    4106             :             .ToLocalChecked()
    4107             :             ->Equals(env.local(), source)
    4108             :             .FromMaybe(false));
    4109             : 
    4110           5 :   CHECK_EQ(2u, script_data.FunctionCount());
    4111             :   v8::debug::Coverage::FunctionData function_data =
    4112           5 :       script_data.GetFunctionData(0);
    4113             : 
    4114           5 :   CHECK_EQ(0, function_data.StartOffset());
    4115           5 :   CHECK_EQ(26, function_data.EndOffset());
    4116             : 
    4117             :   v8::debug::Location start =
    4118           5 :       script->GetSourceLocation(function_data.StartOffset());
    4119             :   v8::debug::Location end =
    4120           5 :       script->GetSourceLocation(function_data.EndOffset());
    4121           5 :   CHECK_EQ(0, start.GetLineNumber());
    4122           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4123           5 :   CHECK_EQ(3, end.GetLineNumber());
    4124           5 :   CHECK_EQ(4, end.GetColumnNumber());
    4125           5 :   CHECK_EQ(1, function_data.Count());
    4126             : 
    4127          10 :   function_data = script_data.GetFunctionData(1);
    4128           5 :   start = script->GetSourceLocation(function_data.StartOffset());
    4129           5 :   end = script->GetSourceLocation(function_data.EndOffset());
    4130             : 
    4131           5 :   CHECK_EQ(0, function_data.StartOffset());
    4132           5 :   CHECK_EQ(16, function_data.EndOffset());
    4133             : 
    4134           5 :   CHECK_EQ(0, start.GetLineNumber());
    4135           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4136           5 :   CHECK_EQ(1, end.GetLineNumber());
    4137           5 :   CHECK_EQ(1, end.GetColumnNumber());
    4138          10 :   CHECK_EQ(2, function_data.Count());
    4139             : }
    4140             : 
    4141             : namespace {
    4142           5 : v8::debug::Coverage::FunctionData GetFunctionDataAndDeleteCoverage(
    4143             :     v8::Isolate* isolate) {
    4144           5 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(isolate);
    4145           5 :   CHECK_EQ(1u, coverage.ScriptCount());
    4146             : 
    4147           5 :   v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(0);
    4148             : 
    4149           5 :   CHECK_EQ(2u, script_data.FunctionCount());
    4150             :   v8::debug::Coverage::FunctionData function_data =
    4151           5 :       script_data.GetFunctionData(0);
    4152           5 :   CHECK_EQ(1, function_data.Count());
    4153           5 :   CHECK_EQ(0, function_data.StartOffset());
    4154           5 :   CHECK_EQ(26, function_data.EndOffset());
    4155           5 :   return function_data;
    4156             : }
    4157             : }  // namespace
    4158             : 
    4159       28342 : TEST(DebugCoverageWithScriptDataOutOfScope) {
    4160             :   // Coverage needs feedback vectors.
    4161           5 :   if (i::FLAG_lite_mode) return;
    4162           5 :   i::FLAG_always_opt = false;
    4163           5 :   LocalContext env;
    4164           5 :   v8::Isolate* isolate = env->GetIsolate();
    4165          10 :   v8::HandleScope scope(isolate);
    4166           5 :   v8::debug::Coverage::SelectMode(isolate, v8::debug::Coverage::kPreciseCount);
    4167             :   v8::Local<v8::String> source = v8_str(
    4168             :       "function f() {\n"
    4169             :       "}\n"
    4170             :       "f();\n"
    4171           5 :       "f();");
    4172           5 :   CompileRun(source);
    4173             : 
    4174             :   v8::debug::Coverage::FunctionData function_data =
    4175           5 :       GetFunctionDataAndDeleteCoverage(isolate);
    4176           5 :   CHECK_EQ(1, function_data.Count());
    4177           5 :   CHECK_EQ(0, function_data.StartOffset());
    4178          10 :   CHECK_EQ(26, function_data.EndOffset());
    4179             : }
    4180             : 
    4181       28342 : TEST(BuiltinsExceptionPrediction) {
    4182           5 :   v8::Isolate* isolate = CcTest::isolate();
    4183             :   i::Isolate* iisolate = CcTest::i_isolate();
    4184           5 :   v8::HandleScope handle_scope(isolate);
    4185           5 :   v8::Context::New(isolate);
    4186             : 
    4187           5 :   i::Builtins* builtins = iisolate->builtins();
    4188             :   bool fail = false;
    4189        7560 :   for (int i = 0; i < i::Builtins::builtin_count; i++) {
    4190        7555 :     i::Code builtin = builtins->builtin(i);
    4191        9925 :     if (builtin->kind() != i::Code::BUILTIN) continue;
    4192        5185 :     auto prediction = builtin->GetBuiltinCatchPrediction();
    4193             :     USE(prediction);
    4194             :   }
    4195           5 :   CHECK(!fail);
    4196           5 : }
    4197             : 
    4198       28342 : TEST(DebugGetPossibleBreakpointsReturnLocations) {
    4199           5 :   LocalContext env;
    4200           5 :   v8::Isolate* isolate = env->GetIsolate();
    4201          10 :   v8::HandleScope scope(isolate);
    4202             :   v8::Local<v8::String> source = v8_str(
    4203             :       "function fib(x) {\n"
    4204             :       "  if (x < 0) return;\n"
    4205             :       "  if (x === 0) return 1;\n"
    4206             :       "  if (x === 1) return fib(0);\n"
    4207             :       "  return x > 2 ? fib(x - 1) + fib(x - 2) : fib(1) + fib(0);\n"
    4208           5 :       "}");
    4209           5 :   CompileRun(source);
    4210           5 :   v8::PersistentValueVector<v8::debug::Script> scripts(isolate);
    4211           5 :   v8::debug::GetLoadedScripts(isolate, scripts);
    4212           5 :   CHECK_EQ(scripts.Size(), 1);
    4213             :   std::vector<v8::debug::BreakLocation> locations;
    4214          10 :   CHECK(scripts.Get(0)->GetPossibleBreakpoints(
    4215             :       v8::debug::Location(0, 17), v8::debug::Location(), true, &locations));
    4216             :   int returns_count = 0;
    4217         165 :   for (size_t i = 0; i < locations.size(); ++i) {
    4218          80 :     if (locations[i].type() == v8::debug::kReturnBreakLocation) {
    4219          20 :       ++returns_count;
    4220             :     }
    4221             :   }
    4222             :   // With Ignition we generate one return location per return statement,
    4223             :   // each has line = 5, column = 0 as statement position.
    4224          10 :   CHECK_EQ(returns_count, 4);
    4225           5 : }
    4226             : 
    4227       28342 : TEST(DebugEvaluateNoSideEffect) {
    4228           5 :   LocalContext env;
    4229          10 :   v8::HandleScope scope(env->GetIsolate());
    4230           5 :   EnableDebugger(env->GetIsolate());
    4231           5 :   i::Isolate* isolate = CcTest::i_isolate();
    4232             :   std::vector<i::Handle<i::JSFunction>> all_functions;
    4233             :   {
    4234        9500 :     i::HeapIterator iterator(isolate->heap());
    4235       69170 :     for (i::HeapObject obj = iterator.next(); !obj.is_null();
    4236             :          obj = iterator.next()) {
    4237       65995 :       if (!obj->IsJSFunction()) continue;
    4238        3165 :       i::JSFunction fun = i::JSFunction::cast(obj);
    4239        3165 :       all_functions.emplace_back(fun, isolate);
    4240           5 :     }
    4241             :   }
    4242             : 
    4243             :   // Perform side effect check on all built-in functions. The side effect check
    4244             :   // itself contains additional sanity checks.
    4245        3175 :   for (i::Handle<i::JSFunction> fun : all_functions) {
    4246             :     bool failed = false;
    4247        6330 :     isolate->debug()->StartSideEffectCheckMode();
    4248             :     failed = !isolate->debug()->PerformSideEffectCheck(
    4249        9495 :         fun, v8::Utils::OpenHandle(*env->Global()));
    4250        6330 :     isolate->debug()->StopSideEffectCheckMode();
    4251        3165 :     if (failed) isolate->clear_pending_exception();
    4252             :   }
    4253          10 :   DisableDebugger(env->GetIsolate());
    4254           5 : }
    4255             : 
    4256             : namespace {
    4257          10 : i::MaybeHandle<i::Script> FindScript(
    4258             :     i::Isolate* isolate, const std::vector<i::Handle<i::Script>>& scripts,
    4259             :     const char* name) {
    4260             :   Handle<i::String> i_name =
    4261          10 :       isolate->factory()->NewStringFromAsciiChecked(name);
    4262          35 :   for (const auto& script : scripts) {
    4263          50 :     if (!script->name()->IsString()) continue;
    4264          50 :     if (i_name->Equals(i::String::cast(script->name()))) return script;
    4265             :   }
    4266           0 :   return i::MaybeHandle<i::Script>();
    4267             : }
    4268             : }  // anonymous namespace
    4269             : 
    4270       28342 : UNINITIALIZED_TEST(LoadedAtStartupScripts) {
    4271           5 :   i::FLAG_expose_gc = true;
    4272             : 
    4273             :   v8::Isolate::CreateParams create_params;
    4274           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    4275           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    4276           5 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    4277             :   {
    4278             :     v8::Isolate::Scope i_scope(isolate);
    4279          10 :     v8::HandleScope scope(isolate);
    4280           5 :     LocalContext context(isolate);
    4281             : 
    4282             :     std::vector<i::Handle<i::Script>> scripts;
    4283           5 :     CompileWithOrigin(v8_str("function foo(){}"), v8_str("normal.js"));
    4284           5 :     std::unordered_map<int, int> count_by_type;
    4285             :     {
    4286             :       i::DisallowHeapAllocation no_gc;
    4287           5 :       i::Script::Iterator iterator(i_isolate);
    4288          60 :       for (i::Script script = iterator.Next(); !script.is_null();
    4289             :            script = iterator.Next()) {
    4290          75 :         if (script->type() == i::Script::TYPE_NATIVE &&
    4291          45 :             script->name()->IsUndefined(i_isolate)) {
    4292             :           continue;
    4293             :         }
    4294          30 :         ++count_by_type[script->type()];
    4295          15 :         scripts.emplace_back(script, i_isolate);
    4296             :       }
    4297             :     }
    4298          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_NATIVE], 0);
    4299          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_EXTENSION], 2);
    4300          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_NORMAL], 1);
    4301          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_WASM], 0);
    4302          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_INSPECTOR], 0);
    4303             : 
    4304             :     i::Handle<i::Script> gc_script =
    4305          10 :         FindScript(i_isolate, scripts, "v8/gc").ToHandleChecked();
    4306           5 :     CHECK_EQ(gc_script->type(), i::Script::TYPE_EXTENSION);
    4307             : 
    4308             :     i::Handle<i::Script> normal_script =
    4309          10 :         FindScript(i_isolate, scripts, "normal.js").ToHandleChecked();
    4310           5 :     CHECK_EQ(normal_script->type(), i::Script::TYPE_NORMAL);
    4311             :   }
    4312           5 :   isolate->Dispose();
    4313           5 : }
    4314             : 
    4315       28342 : TEST(SourceInfo) {
    4316           5 :   LocalContext env;
    4317          10 :   v8::HandleScope scope(env->GetIsolate());
    4318             :   const char* source =
    4319             :       "//\n"
    4320             :       "function a() { b(); };\n"
    4321             :       "function    b() {\n"
    4322             :       "  c(true);\n"
    4323             :       "};\n"
    4324             :       "  function c(x) {\n"
    4325             :       "    if (x) {\n"
    4326             :       "      return 1;\n"
    4327             :       "    } else {\n"
    4328             :       "      return 1;\n"
    4329             :       "    }\n"
    4330             :       "  };\n"
    4331             :       "function d(x) {\n"
    4332             :       "  x = 1 ;\n"
    4333             :       "  x = 2 ;\n"
    4334             :       "  x = 3 ;\n"
    4335             :       "  x = 4 ;\n"
    4336             :       "  x = 5 ;\n"
    4337             :       "  x = 6 ;\n"
    4338             :       "  x = 7 ;\n"
    4339             :       "  x = 8 ;\n"
    4340             :       "  x = 9 ;\n"
    4341             :       "  x = 10;\n"
    4342             :       "  x = 11;\n"
    4343             :       "  x = 12;\n"
    4344             :       "  x = 13;\n"
    4345             :       "  x = 14;\n"
    4346             :       "  x = 15;\n"
    4347             :       "}\n";
    4348             :   v8::Local<v8::Script> v8_script =
    4349           5 :       v8::Script::Compile(env.local(), v8_str(source)).ToLocalChecked();
    4350             :   i::Handle<i::Script> i_script(
    4351          10 :       i::Script::cast(v8::Utils::OpenHandle(*v8_script)->shared()->script()),
    4352          10 :       CcTest::i_isolate());
    4353             :   v8::Local<v8::debug::Script> script =
    4354             :       v8::ToApiHandle<v8::debug::Script>(i_script);
    4355             : 
    4356             :   // Test that when running through source positions the position, line and
    4357             :   // column progresses as expected.
    4358           5 :   v8::debug::Location prev_location = script->GetSourceLocation(0);
    4359           5 :   CHECK_EQ(prev_location.GetLineNumber(), 0);
    4360           5 :   CHECK_EQ(prev_location.GetColumnNumber(), 0);
    4361         495 :   for (int offset = 1; offset < 100; ++offset) {
    4362         495 :     v8::debug::Location location = script->GetSourceLocation(offset);
    4363         495 :     if (prev_location.GetLineNumber() == location.GetLineNumber()) {
    4364         460 :       CHECK_EQ(location.GetColumnNumber(), prev_location.GetColumnNumber() + 1);
    4365             :     } else {
    4366          35 :       CHECK_EQ(location.GetLineNumber(), prev_location.GetLineNumber() + 1);
    4367          35 :       CHECK_EQ(location.GetColumnNumber(), 0);
    4368             :     }
    4369         495 :     prev_location = location;
    4370             :   }
    4371             : 
    4372             :   // Every line of d() is the same length.  Verify we can loop through all
    4373             :   // positions and find the right line # for each.
    4374             :   // The position of the first line of d(), i.e. "x = 1 ;".
    4375             :   const int start_line_d = 13;
    4376             :   const int start_code_d =
    4377             :       static_cast<int>(strstr(source, "  x = 1 ;") - source);
    4378             :   const int num_lines_d = 15;
    4379             :   const int line_length_d = 10;
    4380             :   int p = start_code_d;
    4381          75 :   for (int line = 0; line < num_lines_d; ++line) {
    4382         750 :     for (int column = 0; column < line_length_d; ++column) {
    4383         750 :       v8::debug::Location location = script->GetSourceLocation(p);
    4384         750 :       CHECK_EQ(location.GetLineNumber(), start_line_d + line);
    4385         750 :       CHECK_EQ(location.GetColumnNumber(), column);
    4386         750 :       ++p;
    4387             :     }
    4388             :   }
    4389             : 
    4390             :   // Test first positon.
    4391           5 :   CHECK_EQ(script->GetSourceLocation(0).GetLineNumber(), 0);
    4392           5 :   CHECK_EQ(script->GetSourceLocation(0).GetColumnNumber(), 0);
    4393             : 
    4394             :   // Test second positon.
    4395           5 :   CHECK_EQ(script->GetSourceLocation(1).GetLineNumber(), 0);
    4396           5 :   CHECK_EQ(script->GetSourceLocation(1).GetColumnNumber(), 1);
    4397             : 
    4398             :   // Test first positin in function a().
    4399             :   const int start_a =
    4400             :       static_cast<int>(strstr(source, "function a") - source) + 10;
    4401           5 :   CHECK_EQ(script->GetSourceLocation(start_a).GetLineNumber(), 1);
    4402           5 :   CHECK_EQ(script->GetSourceLocation(start_a).GetColumnNumber(), 10);
    4403             : 
    4404             :   // Test first positin in function b().
    4405             :   const int start_b =
    4406             :       static_cast<int>(strstr(source, "function    b") - source) + 13;
    4407           5 :   CHECK_EQ(script->GetSourceLocation(start_b).GetLineNumber(), 2);
    4408           5 :   CHECK_EQ(script->GetSourceLocation(start_b).GetColumnNumber(), 13);
    4409             : 
    4410             :   // Test first positin in function c().
    4411             :   const int start_c =
    4412             :       static_cast<int>(strstr(source, "function c") - source) + 10;
    4413           5 :   CHECK_EQ(script->GetSourceLocation(start_c).GetLineNumber(), 5);
    4414           5 :   CHECK_EQ(script->GetSourceLocation(start_c).GetColumnNumber(), 12);
    4415             : 
    4416             :   // Test first positin in function d().
    4417             :   const int start_d =
    4418             :       static_cast<int>(strstr(source, "function d") - source) + 10;
    4419           5 :   CHECK_EQ(script->GetSourceLocation(start_d).GetLineNumber(), 12);
    4420           5 :   CHECK_EQ(script->GetSourceLocation(start_d).GetColumnNumber(), 10);
    4421             : 
    4422             :   // Test offsets.
    4423           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(1, 10)), start_a);
    4424           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(2, 13)), start_b);
    4425           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(3, 0)), start_b + 5);
    4426           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(3, 2)), start_b + 7);
    4427           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(4, 0)), start_b + 16);
    4428           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(5, 12)), start_c);
    4429           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(6, 0)), start_c + 6);
    4430           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(7, 0)), start_c + 19);
    4431           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(8, 0)), start_c + 35);
    4432           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(9, 0)), start_c + 48);
    4433           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(10, 0)), start_c + 64);
    4434           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(11, 0)), start_c + 70);
    4435           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(12, 10)), start_d);
    4436           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(13, 0)), start_d + 6);
    4437          75 :   for (int i = 1; i <= num_lines_d; ++i) {
    4438          75 :     CHECK_EQ(script->GetSourceOffset(v8::debug::Location(start_line_d + i, 0)),
    4439             :              6 + (i * line_length_d) + start_d);
    4440             :   }
    4441           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(start_line_d + 17, 0)),
    4442             :            start_d + 158);
    4443             : 
    4444             :   // Make sure invalid inputs work properly.
    4445             :   const int last_position = static_cast<int>(strlen(source)) - 1;
    4446           5 :   CHECK_EQ(script->GetSourceLocation(-1).GetLineNumber(), 0);
    4447           5 :   CHECK_EQ(script->GetSourceLocation(last_position + 2).GetLineNumber(),
    4448             :            i::kNoSourcePosition);
    4449             : 
    4450             :   // Test last position.
    4451           5 :   CHECK_EQ(script->GetSourceLocation(last_position).GetLineNumber(), 28);
    4452           5 :   CHECK_EQ(script->GetSourceLocation(last_position).GetColumnNumber(), 1);
    4453           5 :   CHECK_EQ(script->GetSourceLocation(last_position + 1).GetLineNumber(), 29);
    4454          10 :   CHECK_EQ(script->GetSourceLocation(last_position + 1).GetColumnNumber(), 0);
    4455           5 : }
    4456             : 
    4457             : namespace {
    4458          10 : class SetBreakpointOnScriptCompiled : public v8::debug::DebugDelegate {
    4459             :  public:
    4460          15 :   void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
    4461             :                       bool has_compile_error) override {
    4462             :     v8::Local<v8::String> name;
    4463          40 :     if (!script->SourceURL().ToLocal(&name)) return;
    4464           5 :     v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
    4465          15 :     if (!name->Equals(context, v8_str("test")).FromJust()) return;
    4466           5 :     CHECK(!has_compile_error);
    4467           5 :     v8::debug::Location loc(1, 2);
    4468           5 :     CHECK(script->SetBreakpoint(v8_str(""), &loc, &id_));
    4469           5 :     CHECK_EQ(loc.GetLineNumber(), 1);
    4470           5 :     CHECK_EQ(loc.GetColumnNumber(), 10);
    4471             :   }
    4472             : 
    4473           5 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    4474             :                              const std::vector<v8::debug::BreakpointId>&
    4475           5 :                                  inspector_break_points_hit) override {
    4476           5 :     ++break_count_;
    4477          10 :     CHECK_EQ(inspector_break_points_hit[0], id_);
    4478           5 :   }
    4479             : 
    4480             :   int break_count() const { return break_count_; }
    4481             : 
    4482             :  private:
    4483             :   int break_count_ = 0;
    4484             :   v8::debug::BreakpointId id_;
    4485             : };
    4486             : }  // anonymous namespace
    4487             : 
    4488       28342 : TEST(Regress517592) {
    4489           5 :   LocalContext env;
    4490          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    4491             :   SetBreakpointOnScriptCompiled delegate;
    4492           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    4493             :   CompileRun(
    4494             :       v8_str("eval('var foo = function foo() {\\n' +\n"
    4495             :              "'  var a = 1;\\n' +\n"
    4496             :              "'}\\n' +\n"
    4497           5 :              "'//@ sourceURL=test')"));
    4498           5 :   CHECK_EQ(delegate.break_count(), 0);
    4499           5 :   CompileRun(v8_str("foo()"));
    4500           5 :   CHECK_EQ(delegate.break_count(), 1);
    4501          10 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    4502       85016 : }

Generated by: LCOV version 1.10