LCOV - code coverage report
Current view: top level - test/cctest - test-debug.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1937 1971 98.3 %
Date: 2019-04-17 Functions: 146 187 78.1 %

          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             : 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             :       Handle<v8::internal::JSFunction>::cast(v8::Utils::OpenHandle(*fun));
      76             :   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             :       i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*fun));
      87         350 :   position += function->shared()->StartPosition();
      88             :   static int break_point_index = 0;
      89             :   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             : static void ClearBreakPoint(i::Handle<i::BreakPoint> break_point) {
     103             :   v8::internal::Isolate* isolate = CcTest::i_isolate();
     104             :   v8::internal::Debug* debug = isolate->debug();
     105         175 :   debug->ClearBreakPoint(break_point);
     106             : }
     107             : 
     108             : 
     109             : // Change break on exception.
     110          15 : static void ChangeBreakOnException(bool caught, bool uncaught) {
     111             :   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             : static void PrepareStep(i::StepAction step_action) {
     119             :   v8::internal::Debug* debug = CcTest::i_isolate()->debug();
     120       11980 :   debug->PrepareStep(step_action);
     121             : }
     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             :   Debug* debug = CcTest::i_isolate()->debug();
     131             : 
     132          25 :   v8::internal::DebugInfoListNode* node = debug->debug_info_list_;
     133             : 
     134             :   // Find the number of debugged functions.
     135             :   int count = 0;
     136          65 :   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          25 :   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         820 :   HeapIterator iterator(CcTest::heap());
     168     5632324 :   for (HeapObject obj = iterator.next(); !obj.is_null();
     169             :        obj = iterator.next()) {
     170     2815752 :     CHECK(!obj->IsDebugInfo());
     171             :   }
     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         570 : class DebugEventCounter : public v8::debug::DebugDelegate {
     191             :  public:
     192       12775 :   void BreakProgramRequested(
     193             :       v8::Local<v8::Context>,
     194             :       const std::vector<v8::debug::BreakpointId>&) override {
     195       12775 :     break_point_hit_count++;
     196             :     // Perform a full deoptimization when the specified number of
     197             :     // breaks have been hit.
     198       12775 :     if (break_point_hit_count == break_point_hit_count_deoptimize) {
     199           0 :       i::Deoptimizer::DeoptimizeAll(CcTest::i_isolate());
     200             :     }
     201       12775 :     if (step_action_ != StepNone) PrepareStep(step_action_);
     202       12775 :   }
     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          30 : 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          20 : 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         130 : 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       26644 : 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             :   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             :   ClearBreakPoint(bp2);
     320           5 :   DisableDebugger(env->GetIsolate());
     321          10 :   CHECK_EQ(0, v8::internal::GetDebuggedFunctions()->length());
     322           5 :   CHECK(!HasBreakInfo(foo));
     323           5 :   CHECK(!HasBreakInfo(bar));
     324           5 : }
     325             : 
     326             : 
     327             : // Test that a break point can be set at an IC store location.
     328       26644 : 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             :       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             :   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             :   CheckDebuggerUnloaded();
     356           5 : }
     357             : 
     358             : // Test that a break point can be set at an IC store location.
     359       26644 : 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             :   ClearBreakPoint(bp);
     384             :   CompileRun("foo()");
     385           5 :   CHECK_EQ(1, break_point_hit_count);
     386             : 
     387           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     388             :   CheckDebuggerUnloaded();
     389           5 : }
     390             : 
     391             : // Test that a break point can be set at an IC load location.
     392       26644 : 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             :       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             :   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             :   CheckDebuggerUnloaded();
     421           5 : }
     422             : 
     423             : 
     424             : // Test that a break point can be set at an IC call location.
     425       26644 : 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             :       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             :   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             :   CheckDebuggerUnloaded();
     453           5 : }
     454             : 
     455             : 
     456             : // Test that a break point can be set at an IC call location and survive a GC.
     457       26644 : 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             :       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             :   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             :   CheckDebuggerUnloaded();
     495           5 : }
     496             : 
     497             : 
     498             : // Test that a break point can be set at an IC call location and survive a GC.
     499       26644 : 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             :       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             :   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             :   CheckDebuggerUnloaded();
     537           5 : }
     538             : 
     539             : 
     540       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     569           5 : }
     570             : 
     571       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     600           5 : }
     601             : 
     602       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     633           5 : }
     634             : 
     635       26644 : 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             :   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             :   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             :   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             :   CheckDebuggerUnloaded();
     695           5 : }
     696             : 
     697       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     736           5 : }
     737             : 
     738       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     781           5 : }
     782             : 
     783       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     823           5 : }
     824             : 
     825       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     863           5 : }
     864             : 
     865       26644 : 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             :   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             :   CheckDebuggerUnloaded();
     904           5 : }
     905             : 
     906       26644 : 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          10 :     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             :     ClearBreakPoint(bp);
     941             :     CompileRun("'b'.repeat(10)");
     942           5 :     CHECK_EQ(2, break_point_hit_count);
     943             :   }
     944             : #endif
     945             : 
     946           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
     947             :   CheckDebuggerUnloaded();
     948           5 : }
     949             : 
     950         415 : void NoOpFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
     951         415 :   args.GetReturnValue().Set(v8_num(2));
     952         415 : }
     953             : 
     954       26644 : 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           5 :       function_template->GetFunction(env.local()).ToLocalChecked();
     968             : 
     969          20 :   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             :   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             :   CheckDebuggerUnloaded();
     989           5 : }
     990             : 
     991          10 : void GetWrapperCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
     992             :   args.GetReturnValue().Set(
     993             :       args[0]
     994             :           .As<v8::Object>()
     995          20 :           ->Get(args.GetIsolate()->GetCurrentContext(), args[1])
     996             :           .ToLocalChecked());
     997          10 : }
     998             : 
     999       26644 : 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           5 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1015             :   v8::Local<v8::Function> get =
    1016           5 :       get_template->GetFunction(env.local()).ToLocalChecked();
    1017             : 
    1018          20 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
    1019          20 :   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             :   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             :   CheckDebuggerUnloaded();
    1042           5 : }
    1043             : 
    1044          20 : 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       26644 : 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           5 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1067             :   v8::Local<v8::Function> set =
    1068           5 :       set_template->GetFunction(env.local()).ToLocalChecked();
    1069             : 
    1070          20 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
    1071          20 :   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             :   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             :   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             :   CheckDebuggerUnloaded();
    1115           5 : }
    1116             : 
    1117       26644 : 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          10 :   obj_template->SetAccessorProperty(v8_str("f"), accessor_template,
    1132           5 :                                     accessor_template);
    1133             :   v8::Local<v8::Object> obj =
    1134           5 :       obj_template->NewInstance(env.local()).ToLocalChecked();
    1135          20 :   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             :   // Test that the break point also works when we install the function
    1171             :   // template on a new property (with a fresh AccessorPair instance).
    1172             :   v8::Local<v8::ObjectTemplate> baz_template =
    1173           5 :       v8::ObjectTemplate::New(env->GetIsolate());
    1174          10 :   baz_template->SetAccessorProperty(v8_str("g"), accessor_template,
    1175           5 :                                     accessor_template);
    1176             :   v8::Local<v8::Object> baz =
    1177           5 :       baz_template->NewInstance(env.local()).ToLocalChecked();
    1178          20 :   env->Global()->Set(env.local(), v8_str("b"), baz).ToChecked();
    1179             : 
    1180             :   CompileRun("b.g = 4");
    1181           5 :   CHECK_EQ(43, break_point_hit_count);
    1182             : 
    1183             :   CompileRun("b.g");
    1184           5 :   CHECK_EQ(44, break_point_hit_count);
    1185             : 
    1186             :   // Run without breakpoints.
    1187             :   ClearBreakPoint(bp);
    1188             :   CompileRun("o.f = 3");
    1189             :   CompileRun("o.f");
    1190           5 :   CHECK_EQ(44, break_point_hit_count);
    1191             : 
    1192           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1193             :   CheckDebuggerUnloaded();
    1194           5 : }
    1195             : 
    1196       26644 : TEST(BreakPointInlineApiFunction) {
    1197           5 :   i::FLAG_allow_natives_syntax = true;
    1198           5 :   LocalContext env;
    1199          10 :   v8::HandleScope scope(env->GetIsolate());
    1200             : 
    1201           5 :   DebugEventCounter delegate;
    1202           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1203             : 
    1204             :   i::Handle<i::BreakPoint> bp;
    1205             : 
    1206             :   v8::Local<v8::FunctionTemplate> function_template =
    1207           5 :       v8::FunctionTemplate::New(env->GetIsolate(), NoOpFunctionCallback);
    1208             : 
    1209             :   v8::Local<v8::Function> function =
    1210           5 :       function_template->GetFunction(env.local()).ToLocalChecked();
    1211             : 
    1212          20 :   env->Global()->Set(env.local(), v8_str("f"), function).ToChecked();
    1213             :   CompileRun("function g() { return 1 +  f(); }");
    1214             : 
    1215             :   // === Test simple builtin ===
    1216           5 :   break_point_hit_count = 0;
    1217             : 
    1218             :   // Run with breakpoint.
    1219           5 :   bp = SetBreakPoint(function, 0);
    1220           5 :   ExpectInt32("g()", 3);
    1221           5 :   CHECK_EQ(1, break_point_hit_count);
    1222             : 
    1223           5 :   ExpectInt32("g()", 3);
    1224           5 :   CHECK_EQ(2, break_point_hit_count);
    1225             : 
    1226             :   CompileRun("%OptimizeFunctionOnNextCall(g)");
    1227           5 :   ExpectInt32("g()", 3);
    1228           5 :   CHECK_EQ(3, break_point_hit_count);
    1229             : 
    1230             :   // Run without breakpoints.
    1231             :   ClearBreakPoint(bp);
    1232           5 :   ExpectInt32("g()", 3);
    1233           5 :   CHECK_EQ(3, break_point_hit_count);
    1234             : 
    1235           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1236             :   CheckDebuggerUnloaded();
    1237           5 : }
    1238             : 
    1239             : // Test that a break point can be set at a return store location.
    1240       26644 : TEST(BreakPointConditionBuiltin) {
    1241           5 :   i::FLAG_allow_natives_syntax = true;
    1242           5 :   i::FLAG_block_concurrent_recompilation = true;
    1243           5 :   LocalContext env;
    1244          10 :   v8::HandleScope scope(env->GetIsolate());
    1245             : 
    1246           5 :   DebugEventCounter delegate;
    1247           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1248             :   v8::Local<v8::Function> builtin;
    1249             :   i::Handle<i::BreakPoint> bp;
    1250             : 
    1251             :   // === Test global variable ===
    1252           5 :   break_point_hit_count = 0;
    1253           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1254             :   CompileRun("var condition = false");
    1255             :   CompileRun("'a'.repeat(10)");
    1256           5 :   CHECK_EQ(0, break_point_hit_count);
    1257             : 
    1258             :   // Run with breakpoint.
    1259           5 :   bp = SetBreakPoint(builtin, 0, "condition == true");
    1260             :   CompileRun("'b'.repeat(10)");
    1261           5 :   CHECK_EQ(0, break_point_hit_count);
    1262             : 
    1263             :   CompileRun("condition = true");
    1264             :   CompileRun("'b'.repeat(10)");
    1265           5 :   CHECK_EQ(1, break_point_hit_count);
    1266             : 
    1267             :   // Run without breakpoints.
    1268             :   ClearBreakPoint(bp);
    1269             :   CompileRun("'b'.repeat(10)");
    1270           5 :   CHECK_EQ(1, break_point_hit_count);
    1271             : 
    1272             :   // === Test arguments ===
    1273           5 :   break_point_hit_count = 0;
    1274           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1275             :   CompileRun("function f(x) { return 'a'.repeat(x * 2); }");
    1276           5 :   CHECK_EQ(0, break_point_hit_count);
    1277             : 
    1278             :   // Run with breakpoint.
    1279           5 :   bp = SetBreakPoint(builtin, 0, "arguments[0] == 20");
    1280           5 :   ExpectString("f(5)", "aaaaaaaaaa");
    1281           5 :   CHECK_EQ(0, break_point_hit_count);
    1282             : 
    1283           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1284           5 :   CHECK_EQ(1, break_point_hit_count);
    1285             : 
    1286             :   // Run without breakpoints.
    1287             :   ClearBreakPoint(bp);
    1288           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1289           5 :   CHECK_EQ(1, break_point_hit_count);
    1290             : 
    1291             :   // === Test adapted arguments ===
    1292           5 :   break_point_hit_count = 0;
    1293           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1294             :   CompileRun("function f(x) { return 'a'.repeat(x * 2, x); }");
    1295           5 :   CHECK_EQ(0, break_point_hit_count);
    1296             : 
    1297             :   // Run with breakpoint.
    1298             :   bp = SetBreakPoint(builtin, 0,
    1299           5 :                      "arguments[1] == 10 && arguments[2] == undefined");
    1300           5 :   ExpectString("f(5)", "aaaaaaaaaa");
    1301           5 :   CHECK_EQ(0, break_point_hit_count);
    1302             : 
    1303           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1304           5 :   CHECK_EQ(1, break_point_hit_count);
    1305             : 
    1306             :   // Run without breakpoints.
    1307             :   ClearBreakPoint(bp);
    1308           5 :   ExpectString("f(10)", "aaaaaaaaaaaaaaaaaaaa");
    1309           5 :   CHECK_EQ(1, break_point_hit_count);
    1310             : 
    1311             :   // === Test var-arg builtins ===
    1312           5 :   break_point_hit_count = 0;
    1313           5 :   builtin = CompileRun("String.fromCharCode").As<v8::Function>();
    1314             :   CompileRun("function f() { return String.fromCharCode(1, 2, 3); }");
    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             :   // Run without breakpoints.
    1323             :   ClearBreakPoint(bp);
    1324             :   CompileRun("f(1, 2, 3)");
    1325           5 :   CHECK_EQ(1, break_point_hit_count);
    1326             : 
    1327             :   // === Test rest arguments ===
    1328           5 :   break_point_hit_count = 0;
    1329           5 :   builtin = CompileRun("String.fromCharCode").As<v8::Function>();
    1330             :   CompileRun("function f(...args) { return String.fromCharCode(...args); }");
    1331           5 :   CHECK_EQ(0, break_point_hit_count);
    1332             : 
    1333             :   // Run with breakpoint.
    1334           5 :   bp = SetBreakPoint(builtin, 0, "arguments.length == 3 && arguments[1] == 2");
    1335             :   CompileRun("f(1, 2, 3)");
    1336           5 :   CHECK_EQ(1, break_point_hit_count);
    1337             : 
    1338             :   ClearBreakPoint(bp);
    1339             :   CompileRun("f(1, 3, 3)");
    1340           5 :   CHECK_EQ(1, break_point_hit_count);
    1341             : 
    1342             :   // Run without breakpoints.
    1343             :   ClearBreakPoint(bp);
    1344             :   CompileRun("f(1, 2, 3)");
    1345           5 :   CHECK_EQ(1, break_point_hit_count);
    1346             : 
    1347             :   // === Test receiver ===
    1348           5 :   break_point_hit_count = 0;
    1349           5 :   builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
    1350             :   CompileRun("function f(x) { return x.repeat(10); }");
    1351           5 :   CHECK_EQ(0, break_point_hit_count);
    1352             : 
    1353             :   // Run with breakpoint.
    1354           5 :   bp = SetBreakPoint(builtin, 0, "this == 'a'");
    1355           5 :   ExpectString("f('b')", "bbbbbbbbbb");
    1356           5 :   CHECK_EQ(0, break_point_hit_count);
    1357             : 
    1358           5 :   ExpectString("f('a')", "aaaaaaaaaa");
    1359           5 :   CHECK_EQ(1, break_point_hit_count);
    1360             : 
    1361             :   // Run without breakpoints.
    1362             :   ClearBreakPoint(bp);
    1363           5 :   ExpectString("f('a')", "aaaaaaaaaa");
    1364           5 :   CHECK_EQ(1, break_point_hit_count);
    1365             : 
    1366           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1367             :   CheckDebuggerUnloaded();
    1368           5 : }
    1369             : 
    1370       26644 : TEST(BreakPointInlining) {
    1371           5 :   i::FLAG_allow_natives_syntax = true;
    1372           5 :   break_point_hit_count = 0;
    1373           5 :   LocalContext env;
    1374          10 :   v8::HandleScope scope(env->GetIsolate());
    1375             : 
    1376           5 :   DebugEventCounter delegate;
    1377           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1378             : 
    1379           5 :   break_point_hit_count = 0;
    1380             :   v8::Local<v8::Function> inlinee =
    1381           5 :       CompileRun("function f(x) { return x*2; } f").As<v8::Function>();
    1382             :   CompileRun("function test(x) { return 1 + f(x) }");
    1383             :   CompileRun(
    1384             :       "test(0.5); test(0.6);"
    1385             :       "%OptimizeFunctionOnNextCall(test); test(0.7);");
    1386           5 :   CHECK_EQ(0, break_point_hit_count);
    1387             : 
    1388             :   // Run with breakpoint.
    1389           5 :   i::Handle<i::BreakPoint> bp = SetBreakPoint(inlinee, 0);
    1390             :   CompileRun("f(0.1);");
    1391           5 :   CHECK_EQ(1, break_point_hit_count);
    1392             :   CompileRun("test(0.2);");
    1393           5 :   CHECK_EQ(2, break_point_hit_count);
    1394             : 
    1395             :   // Re-optimize.
    1396             :   CompileRun("%OptimizeFunctionOnNextCall(test);");
    1397             :   CompileRun("test(0.3);");
    1398           5 :   CHECK_EQ(3, break_point_hit_count);
    1399             : 
    1400             :   // Run without breakpoints.
    1401             :   ClearBreakPoint(bp);
    1402             :   CompileRun("test(0.3);");
    1403           5 :   CHECK_EQ(3, break_point_hit_count);
    1404             : 
    1405           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1406             :   CheckDebuggerUnloaded();
    1407           5 : }
    1408             : 
    1409          25 : static void CallWithBreakPoints(v8::Local<v8::Context> context,
    1410             :                                 v8::Local<v8::Object> recv,
    1411             :                                 v8::Local<v8::Function> f,
    1412             :                                 int break_point_count, int call_count) {
    1413          25 :   break_point_hit_count = 0;
    1414         425 :   for (int i = 0; i < call_count; i++) {
    1415         800 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1416         400 :     CHECK_EQ((i + 1) * break_point_count, break_point_hit_count);
    1417             :   }
    1418          25 : }
    1419             : 
    1420             : 
    1421             : // Test GC during break point processing.
    1422       26644 : TEST(GCDuringBreakPointProcessing) {
    1423           5 :   break_point_hit_count = 0;
    1424           5 :   LocalContext env;
    1425          10 :   v8::HandleScope scope(env->GetIsolate());
    1426           5 :   v8::Local<v8::Context> context = env.local();
    1427             : 
    1428           5 :   DebugEventBreakPointCollectGarbage delegate;
    1429           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1430             :   v8::Local<v8::Function> foo;
    1431             : 
    1432             :   // Test IC store break point with garbage collection.
    1433           5 :   foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
    1434           5 :   SetBreakPoint(foo, 0);
    1435           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 10);
    1436             : 
    1437             :   // Test IC load break point with garbage collection.
    1438           5 :   foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
    1439           5 :   SetBreakPoint(foo, 0);
    1440           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 10);
    1441             : 
    1442             :   // Test IC call break point with garbage collection.
    1443           5 :   foo = CompileFunction(&env, "function bar(){};function foo(){bar();}", "foo");
    1444           5 :   SetBreakPoint(foo, 0);
    1445           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 10);
    1446             : 
    1447             :   // Test return break point with garbage collection.
    1448           5 :   foo = CompileFunction(&env, "function foo(){}", "foo");
    1449           5 :   SetBreakPoint(foo, 0);
    1450           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 25);
    1451             : 
    1452             :   // Test debug break slot break point with garbage collection.
    1453           5 :   foo = CompileFunction(&env, "function foo(){var a;}", "foo");
    1454           5 :   SetBreakPoint(foo, 0);
    1455           5 :   CallWithBreakPoints(context, env->Global(), foo, 1, 25);
    1456             : 
    1457           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1458             :   CheckDebuggerUnloaded();
    1459           5 : }
    1460             : 
    1461             : 
    1462             : // Call the function three times with different garbage collections in between
    1463             : // and make sure that the break point survives.
    1464          25 : static void CallAndGC(v8::Local<v8::Context> context,
    1465             :                       v8::Local<v8::Object> recv, v8::Local<v8::Function> f) {
    1466          25 :   break_point_hit_count = 0;
    1467             : 
    1468         100 :   for (int i = 0; i < 3; i++) {
    1469             :     // Call function.
    1470         150 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1471          75 :     CHECK_EQ(1 + i * 3, break_point_hit_count);
    1472             : 
    1473             :     // Scavenge and call function.
    1474          75 :     CcTest::CollectGarbage(v8::internal::NEW_SPACE);
    1475         150 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1476          75 :     CHECK_EQ(2 + i * 3, break_point_hit_count);
    1477             : 
    1478             :     // Mark sweep (and perhaps compact) and call function.
    1479          75 :     CcTest::CollectAllGarbage();
    1480         150 :     f->Call(context, recv, 0, nullptr).ToLocalChecked();
    1481          75 :     CHECK_EQ(3 + i * 3, break_point_hit_count);
    1482             :   }
    1483          25 : }
    1484             : 
    1485             : 
    1486             : // Test that a break point can be set at a return store location.
    1487       26644 : TEST(BreakPointSurviveGC) {
    1488           5 :   break_point_hit_count = 0;
    1489           5 :   LocalContext env;
    1490          10 :   v8::HandleScope scope(env->GetIsolate());
    1491           5 :   v8::Local<v8::Context> context = env.local();
    1492             : 
    1493           5 :   DebugEventCounter delegate;
    1494           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1495             :   v8::Local<v8::Function> foo;
    1496             : 
    1497             :   // Test IC store break point with garbage collection.
    1498             :   {
    1499             :     CompileFunction(&env, "function foo(){}", "foo");
    1500           5 :     foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
    1501           5 :     SetBreakPoint(foo, 0);
    1502             :   }
    1503           5 :   CallAndGC(context, env->Global(), foo);
    1504             : 
    1505             :   // Test IC load break point with garbage collection.
    1506             :   {
    1507             :     CompileFunction(&env, "function foo(){}", "foo");
    1508           5 :     foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
    1509           5 :     SetBreakPoint(foo, 0);
    1510             :   }
    1511           5 :   CallAndGC(context, env->Global(), foo);
    1512             : 
    1513             :   // Test IC call break point with garbage collection.
    1514             :   {
    1515             :     CompileFunction(&env, "function foo(){}", "foo");
    1516             :     foo = CompileFunction(&env,
    1517             :                           "function bar(){};function foo(){bar();}",
    1518           5 :                           "foo");
    1519           5 :     SetBreakPoint(foo, 0);
    1520             :   }
    1521           5 :   CallAndGC(context, env->Global(), foo);
    1522             : 
    1523             :   // Test return break point with garbage collection.
    1524             :   {
    1525             :     CompileFunction(&env, "function foo(){}", "foo");
    1526           5 :     foo = CompileFunction(&env, "function foo(){}", "foo");
    1527           5 :     SetBreakPoint(foo, 0);
    1528             :   }
    1529           5 :   CallAndGC(context, env->Global(), foo);
    1530             : 
    1531             :   // Test non IC break point with garbage collection.
    1532             :   {
    1533             :     CompileFunction(&env, "function foo(){}", "foo");
    1534           5 :     foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
    1535           5 :     SetBreakPoint(foo, 0);
    1536             :   }
    1537           5 :   CallAndGC(context, env->Global(), foo);
    1538             : 
    1539           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1540             :   CheckDebuggerUnloaded();
    1541           5 : }
    1542             : 
    1543             : // Test that the debugger statement causes a break.
    1544       26644 : TEST(DebuggerStatement) {
    1545           5 :   break_point_hit_count = 0;
    1546           5 :   LocalContext env;
    1547          10 :   v8::HandleScope scope(env->GetIsolate());
    1548           5 :   DebugEventCounter delegate;
    1549           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1550           5 :   v8::Local<v8::Context> context = env.local();
    1551           5 :   v8::Script::Compile(context,
    1552           5 :                       v8_str(env->GetIsolate(), "function bar(){debugger}"))
    1553             :       .ToLocalChecked()
    1554           5 :       ->Run(context)
    1555             :       .ToLocalChecked();
    1556           5 :   v8::Script::Compile(
    1557           5 :       context, v8_str(env->GetIsolate(), "function foo(){debugger;debugger;}"))
    1558             :       .ToLocalChecked()
    1559           5 :       ->Run(context)
    1560             :       .ToLocalChecked();
    1561             :   v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
    1562          10 :       env->Global()
    1563          15 :           ->Get(context, v8_str(env->GetIsolate(), "foo"))
    1564             :           .ToLocalChecked());
    1565             :   v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
    1566          10 :       env->Global()
    1567          15 :           ->Get(context, v8_str(env->GetIsolate(), "bar"))
    1568             :           .ToLocalChecked());
    1569             : 
    1570             :   // Run function with debugger statement
    1571          15 :   bar->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1572           5 :   CHECK_EQ(1, break_point_hit_count);
    1573             : 
    1574             :   // Run function with two debugger statement
    1575          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1576           5 :   CHECK_EQ(3, break_point_hit_count);
    1577             : 
    1578           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1579             :   CheckDebuggerUnloaded();
    1580           5 : }
    1581             : 
    1582             : 
    1583             : // Test setting a breakpoint on the debugger statement.
    1584       26644 : TEST(DebuggerStatementBreakpoint) {
    1585           5 :     break_point_hit_count = 0;
    1586           5 :     LocalContext env;
    1587          10 :     v8::HandleScope scope(env->GetIsolate());
    1588           5 :     v8::Local<v8::Context> context = env.local();
    1589           5 :     DebugEventCounter delegate;
    1590           5 :     v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1591           5 :     v8::Script::Compile(context,
    1592           5 :                         v8_str(env->GetIsolate(), "function foo(){debugger;}"))
    1593             :         .ToLocalChecked()
    1594           5 :         ->Run(context)
    1595             :         .ToLocalChecked();
    1596             :     v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
    1597          10 :         env->Global()
    1598          15 :             ->Get(context, v8_str(env->GetIsolate(), "foo"))
    1599             :             .ToLocalChecked());
    1600             : 
    1601             :     // The debugger statement triggers breakpoint hit
    1602          15 :     foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1603           5 :     CHECK_EQ(1, break_point_hit_count);
    1604             : 
    1605           5 :     i::Handle<i::BreakPoint> bp = SetBreakPoint(foo, 0);
    1606             : 
    1607             :     // Set breakpoint does not duplicate hits
    1608          15 :     foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1609           5 :     CHECK_EQ(2, break_point_hit_count);
    1610             : 
    1611             :     ClearBreakPoint(bp);
    1612           5 :     v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1613             :     CheckDebuggerUnloaded();
    1614           5 : }
    1615             : 
    1616             : 
    1617             : // Test that the conditional breakpoints work event if code generation from
    1618             : // strings is prohibited in the debugee context.
    1619       26644 : TEST(ConditionalBreakpointWithCodeGenerationDisallowed) {
    1620           5 :   LocalContext env;
    1621          10 :   v8::HandleScope scope(env->GetIsolate());
    1622             : 
    1623           5 :   DebugEventCounter delegate;
    1624           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1625             : 
    1626           5 :   v8::Local<v8::Context> context = env.local();
    1627             :   v8::Local<v8::Function> foo = CompileFunction(&env,
    1628             :     "function foo(x) {\n"
    1629             :     "  var s = 'String value2';\n"
    1630             :     "  return s + x;\n"
    1631             :     "}",
    1632             :     "foo");
    1633             : 
    1634             :   // Set conditional breakpoint with condition 'true'.
    1635           5 :   SetBreakPoint(foo, 4, "true");
    1636             : 
    1637           5 :   break_point_hit_count = 0;
    1638           5 :   env->AllowCodeGenerationFromStrings(false);
    1639          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1640           5 :   CHECK_EQ(1, break_point_hit_count);
    1641             : 
    1642           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1643             :   CheckDebuggerUnloaded();
    1644           5 : }
    1645             : 
    1646             : 
    1647             : // Simple test of the stepping mechanism using only store ICs.
    1648       26644 : TEST(DebugStepLinear) {
    1649           5 :   LocalContext env;
    1650          10 :   v8::HandleScope scope(env->GetIsolate());
    1651             : 
    1652             :   // Create a function for testing stepping.
    1653             :   v8::Local<v8::Function> foo = CompileFunction(&env,
    1654             :                                                 "function foo(){a=1;b=1;c=1;}",
    1655             :                                                 "foo");
    1656             : 
    1657             :   // Run foo to allow it to get optimized.
    1658             :   CompileRun("a=0; b=0; c=0; foo();");
    1659             : 
    1660             :   // Register a debug event listener which steps and counts.
    1661           5 :   DebugEventCounter run_step;
    1662           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1663             : 
    1664           5 :   SetBreakPoint(foo, 3);
    1665             : 
    1666             :   run_step.set_step_action(StepIn);
    1667           5 :   break_point_hit_count = 0;
    1668           5 :   v8::Local<v8::Context> context = env.local();
    1669          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1670             : 
    1671             :   // With stepping all break locations are hit.
    1672           5 :   CHECK_EQ(4, break_point_hit_count);
    1673             : 
    1674           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1675             :   CheckDebuggerUnloaded();
    1676             : 
    1677             :   // Register a debug event listener which just counts.
    1678           5 :   DebugEventCounter delegate;
    1679           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1680             : 
    1681           5 :   SetBreakPoint(foo, 3);
    1682           5 :   break_point_hit_count = 0;
    1683          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1684             : 
    1685             :   // Without stepping only active break points are hit.
    1686           5 :   CHECK_EQ(1, break_point_hit_count);
    1687             : 
    1688           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1689             :   CheckDebuggerUnloaded();
    1690           5 : }
    1691             : 
    1692             : 
    1693             : // Test of the stepping mechanism for keyed load in a loop.
    1694       26644 : TEST(DebugStepKeyedLoadLoop) {
    1695           5 :   LocalContext env;
    1696          10 :   v8::HandleScope scope(env->GetIsolate());
    1697             : 
    1698             :   // Register a debug event listener which steps and counts.
    1699           5 :   DebugEventCounter run_step;
    1700           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1701             : 
    1702             :   // Create a function for testing stepping of keyed load. The statement 'y=1'
    1703             :   // is there to have more than one breakable statement in the loop, TODO(315).
    1704             :   v8::Local<v8::Function> foo = CompileFunction(
    1705             :       &env,
    1706             :       "function foo(a) {\n"
    1707             :       "  var x;\n"
    1708             :       "  var len = a.length;\n"
    1709             :       "  for (var i = 0; i < len; i++) {\n"
    1710             :       "    y = 1;\n"
    1711             :       "    x = a[i];\n"
    1712             :       "  }\n"
    1713             :       "}\n"
    1714             :       "y=0\n",
    1715             :       "foo");
    1716             : 
    1717           5 :   v8::Local<v8::Context> context = env.local();
    1718             :   // Create array [0,1,2,3,4,5,6,7,8,9]
    1719           5 :   v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
    1720         105 :   for (int i = 0; i < 10; i++) {
    1721         250 :     CHECK(a->Set(context, v8::Number::New(env->GetIsolate(), i),
    1722             :                  v8::Number::New(env->GetIsolate(), i))
    1723             :               .FromJust());
    1724             :   }
    1725             : 
    1726             :   // Call function without any break points to ensure inlining is in place.
    1727             :   const int kArgc = 1;
    1728             :   v8::Local<v8::Value> args[kArgc] = {a};
    1729          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1730             : 
    1731             :   // Set up break point and step through the function.
    1732           5 :   SetBreakPoint(foo, 3);
    1733             :   run_step.set_step_action(StepNext);
    1734           5 :   break_point_hit_count = 0;
    1735          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1736             : 
    1737             :   // With stepping all break locations are hit.
    1738           5 :   CHECK_EQ(44, break_point_hit_count);
    1739             : 
    1740           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1741             :   CheckDebuggerUnloaded();
    1742           5 : }
    1743             : 
    1744             : 
    1745             : // Test of the stepping mechanism for keyed store in a loop.
    1746       26644 : TEST(DebugStepKeyedStoreLoop) {
    1747           5 :   LocalContext env;
    1748          10 :   v8::HandleScope scope(env->GetIsolate());
    1749             : 
    1750             :   // Register a debug event listener which steps and counts.
    1751           5 :   DebugEventCounter run_step;
    1752           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1753             : 
    1754             :   // Create a function for testing stepping of keyed store. The statement 'y=1'
    1755             :   // is there to have more than one breakable statement in the loop, TODO(315).
    1756             :   v8::Local<v8::Function> foo = CompileFunction(
    1757             :       &env,
    1758             :       "function foo(a) {\n"
    1759             :       "  var len = a.length;\n"
    1760             :       "  for (var i = 0; i < len; i++) {\n"
    1761             :       "    y = 1;\n"
    1762             :       "    a[i] = 42;\n"
    1763             :       "  }\n"
    1764             :       "}\n"
    1765             :       "y=0\n",
    1766             :       "foo");
    1767             : 
    1768           5 :   v8::Local<v8::Context> context = env.local();
    1769             :   // Create array [0,1,2,3,4,5,6,7,8,9]
    1770           5 :   v8::Local<v8::Array> a = v8::Array::New(env->GetIsolate(), 10);
    1771         105 :   for (int i = 0; i < 10; i++) {
    1772         250 :     CHECK(a->Set(context, v8::Number::New(env->GetIsolate(), i),
    1773             :                  v8::Number::New(env->GetIsolate(), i))
    1774             :               .FromJust());
    1775             :   }
    1776             : 
    1777             :   // Call function without any break points to ensure inlining is in place.
    1778             :   const int kArgc = 1;
    1779             :   v8::Local<v8::Value> args[kArgc] = {a};
    1780          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1781             : 
    1782             :   // Set up break point and step through the function.
    1783           5 :   SetBreakPoint(foo, 3);
    1784             :   run_step.set_step_action(StepNext);
    1785           5 :   break_point_hit_count = 0;
    1786          15 :   foo->Call(context, env->Global(), kArgc, args).ToLocalChecked();
    1787             : 
    1788             :   // With stepping all break locations are hit.
    1789           5 :   CHECK_EQ(44, break_point_hit_count);
    1790             : 
    1791           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1792             :   CheckDebuggerUnloaded();
    1793           5 : }
    1794             : 
    1795             : 
    1796             : // Test of the stepping mechanism for named load in a loop.
    1797       26644 : TEST(DebugStepNamedLoadLoop) {
    1798           5 :   LocalContext env;
    1799          10 :   v8::HandleScope scope(env->GetIsolate());
    1800             : 
    1801             :   // Register a debug event listener which steps and counts.
    1802           5 :   DebugEventCounter run_step;
    1803           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1804             : 
    1805           5 :   v8::Local<v8::Context> context = env.local();
    1806             :   // Create a function for testing stepping of named load.
    1807             :   v8::Local<v8::Function> foo = CompileFunction(
    1808             :       &env,
    1809             :       "function foo() {\n"
    1810             :           "  var a = [];\n"
    1811             :           "  var s = \"\";\n"
    1812             :           "  for (var i = 0; i < 10; i++) {\n"
    1813             :           "    var v = new V(i, i + 1);\n"
    1814             :           "    v.y;\n"
    1815             :           "    a.length;\n"  // Special case: array length.
    1816             :           "    s.length;\n"  // Special case: string length.
    1817             :           "  }\n"
    1818             :           "}\n"
    1819             :           "function V(x, y) {\n"
    1820             :           "  this.x = x;\n"
    1821             :           "  this.y = y;\n"
    1822             :           "}\n",
    1823             :           "foo");
    1824             : 
    1825             :   // Call function without any break points to ensure inlining is in place.
    1826          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1827             : 
    1828             :   // Set up break point and step through the function.
    1829           5 :   SetBreakPoint(foo, 4);
    1830             :   run_step.set_step_action(StepNext);
    1831           5 :   break_point_hit_count = 0;
    1832          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1833             : 
    1834             :   // With stepping all break locations are hit.
    1835           5 :   CHECK_EQ(65, break_point_hit_count);
    1836             : 
    1837           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1838             :   CheckDebuggerUnloaded();
    1839           5 : }
    1840             : 
    1841             : 
    1842           5 : static void DoDebugStepNamedStoreLoop(int expected) {
    1843           5 :   LocalContext env;
    1844          10 :   v8::HandleScope scope(env->GetIsolate());
    1845             : 
    1846             :   // Register a debug event listener which steps and counts.
    1847           5 :   DebugEventCounter run_step;
    1848           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1849             : 
    1850             :   // Create a function for testing stepping of named store.
    1851           5 :   v8::Local<v8::Context> context = env.local();
    1852             :   v8::Local<v8::Function> foo = CompileFunction(
    1853             :       &env,
    1854             :       "function foo() {\n"
    1855             :           "  var a = {a:1};\n"
    1856             :           "  for (var i = 0; i < 10; i++) {\n"
    1857             :           "    a.a = 2\n"
    1858             :           "  }\n"
    1859             :           "}\n",
    1860             :           "foo");
    1861             : 
    1862             :   // Call function without any break points to ensure inlining is in place.
    1863          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1864             : 
    1865             :   // Set up break point and step through the function.
    1866           5 :   SetBreakPoint(foo, 3);
    1867             :   run_step.set_step_action(StepNext);
    1868           5 :   break_point_hit_count = 0;
    1869          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1870             : 
    1871             :   // With stepping all expected break locations are hit.
    1872           5 :   CHECK_EQ(expected, break_point_hit_count);
    1873             : 
    1874           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1875             :   CheckDebuggerUnloaded();
    1876           5 : }
    1877             : 
    1878             : 
    1879             : // Test of the stepping mechanism for named load in a loop.
    1880       26644 : TEST(DebugStepNamedStoreLoop) { DoDebugStepNamedStoreLoop(34); }
    1881             : 
    1882             : // Test the stepping mechanism with different ICs.
    1883       26644 : TEST(DebugStepLinearMixedICs) {
    1884           5 :   LocalContext env;
    1885          10 :   v8::HandleScope scope(env->GetIsolate());
    1886             : 
    1887             :   // Register a debug event listener which steps and counts.
    1888           5 :   DebugEventCounter run_step;
    1889           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1890             : 
    1891           5 :   v8::Local<v8::Context> context = env.local();
    1892             :   // Create a function for testing stepping.
    1893             :   v8::Local<v8::Function> foo = CompileFunction(&env,
    1894             :       "function bar() {};"
    1895             :       "function foo() {"
    1896             :       "  var x;"
    1897             :       "  var index='name';"
    1898             :       "  var y = {};"
    1899             :       "  a=1;b=2;x=a;y[index]=3;x=y[index];bar();}", "foo");
    1900             : 
    1901             :   // Run functions to allow them to get optimized.
    1902             :   CompileRun("a=0; b=0; bar(); foo();");
    1903             : 
    1904           5 :   SetBreakPoint(foo, 0);
    1905             : 
    1906             :   run_step.set_step_action(StepIn);
    1907           5 :   break_point_hit_count = 0;
    1908          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1909             : 
    1910             :   // With stepping all break locations are hit.
    1911           5 :   CHECK_EQ(10, break_point_hit_count);
    1912             : 
    1913           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1914             :   CheckDebuggerUnloaded();
    1915             : 
    1916             :   // Register a debug event listener which just counts.
    1917           5 :   DebugEventCounter delegate;
    1918           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    1919             : 
    1920           5 :   SetBreakPoint(foo, 0);
    1921           5 :   break_point_hit_count = 0;
    1922          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1923             : 
    1924             :   // Without stepping only active break points are hit.
    1925           5 :   CHECK_EQ(1, break_point_hit_count);
    1926             : 
    1927           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1928             :   CheckDebuggerUnloaded();
    1929           5 : }
    1930             : 
    1931             : 
    1932       26644 : TEST(DebugStepDeclarations) {
    1933           5 :   LocalContext env;
    1934          10 :   v8::HandleScope scope(env->GetIsolate());
    1935             : 
    1936             :   // Register a debug event listener which steps and counts.
    1937           5 :   DebugEventCounter run_step;
    1938           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1939             : 
    1940           5 :   v8::Local<v8::Context> context = env.local();
    1941             :   // Create a function for testing stepping. Run it to allow it to get
    1942             :   // optimized.
    1943             :   const char* src = "function foo() { "
    1944             :                     "  var a;"
    1945             :                     "  var b = 1;"
    1946             :                     "  var c = foo;"
    1947             :                     "  var d = Math.floor;"
    1948             :                     "  var e = b + d(1.2);"
    1949             :                     "}"
    1950             :                     "foo()";
    1951             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    1952             : 
    1953           5 :   SetBreakPoint(foo, 0);
    1954             : 
    1955             :   // Stepping through the declarations.
    1956             :   run_step.set_step_action(StepIn);
    1957           5 :   break_point_hit_count = 0;
    1958          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1959           5 :   CHECK_EQ(5, break_point_hit_count);
    1960             : 
    1961             :   // Get rid of the debug event listener.
    1962           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1963             :   CheckDebuggerUnloaded();
    1964           5 : }
    1965             : 
    1966             : 
    1967       26644 : TEST(DebugStepLocals) {
    1968           5 :   LocalContext env;
    1969          10 :   v8::HandleScope scope(env->GetIsolate());
    1970             : 
    1971             :   // Register a debug event listener which steps and counts.
    1972           5 :   DebugEventCounter run_step;
    1973           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    1974             : 
    1975           5 :   v8::Local<v8::Context> context = env.local();
    1976             :   // Create a function for testing stepping. Run it to allow it to get
    1977             :   // optimized.
    1978             :   const char* src = "function foo() { "
    1979             :                     "  var a,b;"
    1980             :                     "  a = 1;"
    1981             :                     "  b = a + 2;"
    1982             :                     "  b = 1 + 2 + 3;"
    1983             :                     "  a = Math.floor(b);"
    1984             :                     "}"
    1985             :                     "foo()";
    1986             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    1987             : 
    1988           5 :   SetBreakPoint(foo, 0);
    1989             : 
    1990             :   // Stepping through the declarations.
    1991             :   run_step.set_step_action(StepIn);
    1992           5 :   break_point_hit_count = 0;
    1993          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    1994           5 :   CHECK_EQ(5, break_point_hit_count);
    1995             : 
    1996             :   // Get rid of the debug event listener.
    1997           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    1998             :   CheckDebuggerUnloaded();
    1999           5 : }
    2000             : 
    2001             : 
    2002       26644 : TEST(DebugStepIf) {
    2003           5 :   LocalContext env;
    2004           5 :   v8::Isolate* isolate = env->GetIsolate();
    2005          10 :   v8::HandleScope scope(isolate);
    2006             : 
    2007             :   // Register a debug event listener which steps and counts.
    2008           5 :   DebugEventCounter run_step;
    2009           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2010             : 
    2011           5 :   v8::Local<v8::Context> context = env.local();
    2012             :   // Create a function for testing stepping. Run it to allow it to get
    2013             :   // optimized.
    2014             :   const int argc = 1;
    2015             :   const char* src = "function foo(x) { "
    2016             :                     "  a = 1;"
    2017             :                     "  if (x) {"
    2018             :                     "    b = 1;"
    2019             :                     "  } else {"
    2020             :                     "    c = 1;"
    2021             :                     "    d = 1;"
    2022             :                     "  }"
    2023             :                     "}"
    2024             :                     "a=0; b=0; c=0; d=0; foo()";
    2025             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2026           5 :   SetBreakPoint(foo, 0);
    2027             : 
    2028             :   // Stepping through the true part.
    2029             :   run_step.set_step_action(StepIn);
    2030           5 :   break_point_hit_count = 0;
    2031             :   v8::Local<v8::Value> argv_true[argc] = {v8::True(isolate)};
    2032          15 :   foo->Call(context, env->Global(), argc, argv_true).ToLocalChecked();
    2033           5 :   CHECK_EQ(4, break_point_hit_count);
    2034             : 
    2035             :   // Stepping through the false part.
    2036             :   run_step.set_step_action(StepIn);
    2037           5 :   break_point_hit_count = 0;
    2038             :   v8::Local<v8::Value> argv_false[argc] = {v8::False(isolate)};
    2039          15 :   foo->Call(context, env->Global(), argc, argv_false).ToLocalChecked();
    2040           5 :   CHECK_EQ(5, break_point_hit_count);
    2041             : 
    2042             :   // Get rid of the debug event listener.
    2043           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2044             :   CheckDebuggerUnloaded();
    2045           5 : }
    2046             : 
    2047             : 
    2048       26644 : TEST(DebugStepSwitch) {
    2049           5 :   LocalContext env;
    2050           5 :   v8::Isolate* isolate = env->GetIsolate();
    2051          10 :   v8::HandleScope scope(isolate);
    2052             : 
    2053             :   // Register a debug event listener which steps and counts.
    2054           5 :   DebugEventCounter run_step;
    2055           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2056             : 
    2057           5 :   v8::Local<v8::Context> context = env.local();
    2058             :   // Create a function for testing stepping. Run it to allow it to get
    2059             :   // optimized.
    2060             :   const int argc = 1;
    2061             :   const char* src = "function foo(x) { "
    2062             :                     "  a = 1;"
    2063             :                     "  switch (x) {"
    2064             :                     "    case 1:"
    2065             :                     "      b = 1;"
    2066             :                     "    case 2:"
    2067             :                     "      c = 1;"
    2068             :                     "      break;"
    2069             :                     "    case 3:"
    2070             :                     "      d = 1;"
    2071             :                     "      e = 1;"
    2072             :                     "      f = 1;"
    2073             :                     "      break;"
    2074             :                     "  }"
    2075             :                     "}"
    2076             :                     "a=0; b=0; c=0; d=0; e=0; f=0; foo()";
    2077             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2078           5 :   SetBreakPoint(foo, 0);
    2079             : 
    2080             :   // One case with fall-through.
    2081             :   run_step.set_step_action(StepIn);
    2082           5 :   break_point_hit_count = 0;
    2083           5 :   v8::Local<v8::Value> argv_1[argc] = {v8::Number::New(isolate, 1)};
    2084          15 :   foo->Call(context, env->Global(), argc, argv_1).ToLocalChecked();
    2085           5 :   CHECK_EQ(6, break_point_hit_count);
    2086             : 
    2087             :   // Another case.
    2088             :   run_step.set_step_action(StepIn);
    2089           5 :   break_point_hit_count = 0;
    2090           5 :   v8::Local<v8::Value> argv_2[argc] = {v8::Number::New(isolate, 2)};
    2091          15 :   foo->Call(context, env->Global(), argc, argv_2).ToLocalChecked();
    2092           5 :   CHECK_EQ(5, break_point_hit_count);
    2093             : 
    2094             :   // Last case.
    2095             :   run_step.set_step_action(StepIn);
    2096           5 :   break_point_hit_count = 0;
    2097           5 :   v8::Local<v8::Value> argv_3[argc] = {v8::Number::New(isolate, 3)};
    2098          15 :   foo->Call(context, env->Global(), argc, argv_3).ToLocalChecked();
    2099           5 :   CHECK_EQ(7, break_point_hit_count);
    2100             : 
    2101             :   // Get rid of the debug event listener.
    2102           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2103             :   CheckDebuggerUnloaded();
    2104           5 : }
    2105             : 
    2106             : 
    2107       26644 : TEST(DebugStepWhile) {
    2108           5 :   LocalContext env;
    2109           5 :   v8::Isolate* isolate = env->GetIsolate();
    2110          10 :   v8::HandleScope scope(isolate);
    2111             : 
    2112             :   // Register a debug event listener which steps and counts.
    2113           5 :   DebugEventCounter run_step;
    2114           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2115             : 
    2116           5 :   v8::Local<v8::Context> context = env.local();
    2117             :   // Create a function for testing stepping. Run it to allow it to get
    2118             :   // optimized.
    2119             :   const int argc = 1;
    2120             :   const char* src = "function foo(x) { "
    2121             :                     "  var a = 0;"
    2122             :                     "  while (a < x) {"
    2123             :                     "    a++;"
    2124             :                     "  }"
    2125             :                     "}"
    2126             :                     "foo()";
    2127             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2128           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2129             : 
    2130             :   // Looping 0 times.  We still should break at the while-condition once.
    2131             :   run_step.set_step_action(StepIn);
    2132           5 :   break_point_hit_count = 0;
    2133           5 :   v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
    2134          15 :   foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
    2135           5 :   CHECK_EQ(3, break_point_hit_count);
    2136             : 
    2137             :   // Looping 10 times.
    2138             :   run_step.set_step_action(StepIn);
    2139           5 :   break_point_hit_count = 0;
    2140           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2141          15 :   foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2142           5 :   CHECK_EQ(23, break_point_hit_count);
    2143             : 
    2144             :   // Looping 100 times.
    2145             :   run_step.set_step_action(StepIn);
    2146           5 :   break_point_hit_count = 0;
    2147           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2148          15 :   foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2149           5 :   CHECK_EQ(203, break_point_hit_count);
    2150             : 
    2151             :   // Get rid of the debug event listener.
    2152           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2153             :   CheckDebuggerUnloaded();
    2154           5 : }
    2155             : 
    2156             : 
    2157       26644 : TEST(DebugStepDoWhile) {
    2158           5 :   LocalContext env;
    2159           5 :   v8::Isolate* isolate = env->GetIsolate();
    2160          10 :   v8::HandleScope scope(isolate);
    2161             : 
    2162             :   // Register a debug event listener which steps and counts.
    2163           5 :   DebugEventCounter run_step;
    2164           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2165             : 
    2166           5 :   v8::Local<v8::Context> context = env.local();
    2167             :   // Create a function for testing stepping. Run it to allow it to get
    2168             :   // optimized.
    2169             :   const int argc = 1;
    2170             :   const char* src = "function foo(x) { "
    2171             :                     "  var a = 0;"
    2172             :                     "  do {"
    2173             :                     "    a++;"
    2174             :                     "  } while (a < x)"
    2175             :                     "}"
    2176             :                     "foo()";
    2177             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2178           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2179             : 
    2180             :   // Looping 0 times.
    2181             :   run_step.set_step_action(StepIn);
    2182           5 :   break_point_hit_count = 0;
    2183           5 :   v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
    2184          15 :   foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
    2185           5 :   CHECK_EQ(4, break_point_hit_count);
    2186             : 
    2187             :   // Looping 10 times.
    2188             :   run_step.set_step_action(StepIn);
    2189           5 :   break_point_hit_count = 0;
    2190           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2191          15 :   foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2192           5 :   CHECK_EQ(22, break_point_hit_count);
    2193             : 
    2194             :   // Looping 100 times.
    2195             :   run_step.set_step_action(StepIn);
    2196           5 :   break_point_hit_count = 0;
    2197           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2198          15 :   foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2199           5 :   CHECK_EQ(202, break_point_hit_count);
    2200             : 
    2201             :   // Get rid of the debug event listener.
    2202           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2203             :   CheckDebuggerUnloaded();
    2204           5 : }
    2205             : 
    2206             : 
    2207       26644 : TEST(DebugStepFor) {
    2208           5 :   LocalContext env;
    2209           5 :   v8::Isolate* isolate = env->GetIsolate();
    2210          10 :   v8::HandleScope scope(isolate);
    2211             : 
    2212             :   // Register a debug event listener which steps and counts.
    2213           5 :   DebugEventCounter run_step;
    2214           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2215             : 
    2216           5 :   v8::Local<v8::Context> context = env.local();
    2217             :   // Create a function for testing stepping. Run it to allow it to get
    2218             :   // optimized.
    2219             :   const int argc = 1;
    2220             :   const char* src = "function foo(x) { "
    2221             :                     "  a = 1;"
    2222             :                     "  for (i = 0; i < x; i++) {"
    2223             :                     "    b = 1;"
    2224             :                     "  }"
    2225             :                     "}"
    2226             :                     "a=0; b=0; i=0; foo()";
    2227             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2228             : 
    2229           5 :   SetBreakPoint(foo, 8);  // "a = 1;"
    2230             : 
    2231             :   // Looping 0 times.
    2232             :   run_step.set_step_action(StepIn);
    2233           5 :   break_point_hit_count = 0;
    2234           5 :   v8::Local<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
    2235          15 :   foo->Call(context, env->Global(), argc, argv_0).ToLocalChecked();
    2236           5 :   CHECK_EQ(4, break_point_hit_count);
    2237             : 
    2238             :   // Looping 10 times.
    2239             :   run_step.set_step_action(StepIn);
    2240           5 :   break_point_hit_count = 0;
    2241           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2242          15 :   foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2243           5 :   CHECK_EQ(34, break_point_hit_count);
    2244             : 
    2245             :   // Looping 100 times.
    2246             :   run_step.set_step_action(StepIn);
    2247           5 :   break_point_hit_count = 0;
    2248           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2249          15 :   foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2250           5 :   CHECK_EQ(304, break_point_hit_count);
    2251             : 
    2252             :   // Get rid of the debug event listener.
    2253           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2254             :   CheckDebuggerUnloaded();
    2255           5 : }
    2256             : 
    2257             : 
    2258       26644 : TEST(DebugStepForContinue) {
    2259           5 :   LocalContext env;
    2260           5 :   v8::Isolate* isolate = env->GetIsolate();
    2261          10 :   v8::HandleScope scope(isolate);
    2262             : 
    2263             :   // Register a debug event listener which steps and counts.
    2264           5 :   DebugEventCounter run_step;
    2265           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2266             : 
    2267           5 :   v8::Local<v8::Context> context = env.local();
    2268             :   // Create a function for testing stepping. Run it to allow it to get
    2269             :   // optimized.
    2270             :   const int argc = 1;
    2271             :   const char* src = "function foo(x) { "
    2272             :                     "  var a = 0;"
    2273             :                     "  var b = 0;"
    2274             :                     "  var c = 0;"
    2275             :                     "  for (var i = 0; i < x; i++) {"
    2276             :                     "    a++;"
    2277             :                     "    if (a % 2 == 0) continue;"
    2278             :                     "    b++;"
    2279             :                     "    c++;"
    2280             :                     "  }"
    2281             :                     "  return b;"
    2282             :                     "}"
    2283             :                     "foo()";
    2284             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2285             :   v8::Local<v8::Value> result;
    2286           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2287             : 
    2288             :   // Each loop generates 4 or 5 steps depending on whether a is equal.
    2289             : 
    2290             :   // Looping 10 times.
    2291             :   run_step.set_step_action(StepIn);
    2292           5 :   break_point_hit_count = 0;
    2293           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2294          15 :   result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2295          10 :   CHECK_EQ(5, result->Int32Value(context).FromJust());
    2296           5 :   CHECK_EQ(62, break_point_hit_count);
    2297             : 
    2298             :   // Looping 100 times.
    2299             :   run_step.set_step_action(StepIn);
    2300           5 :   break_point_hit_count = 0;
    2301           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2302          15 :   result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2303          10 :   CHECK_EQ(50, result->Int32Value(context).FromJust());
    2304           5 :   CHECK_EQ(557, break_point_hit_count);
    2305             : 
    2306             :   // Get rid of the debug event listener.
    2307           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2308             :   CheckDebuggerUnloaded();
    2309           5 : }
    2310             : 
    2311             : 
    2312       26644 : TEST(DebugStepForBreak) {
    2313           5 :   LocalContext env;
    2314           5 :   v8::Isolate* isolate = env->GetIsolate();
    2315          10 :   v8::HandleScope scope(isolate);
    2316             : 
    2317             :   // Register a debug event listener which steps and counts.
    2318           5 :   DebugEventCounter run_step;
    2319           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2320             : 
    2321           5 :   v8::Local<v8::Context> context = env.local();
    2322             :   // Create a function for testing stepping. Run it to allow it to get
    2323             :   // optimized.
    2324             :   const int argc = 1;
    2325             :   const char* src = "function foo(x) { "
    2326             :                     "  var a = 0;"
    2327             :                     "  var b = 0;"
    2328             :                     "  var c = 0;"
    2329             :                     "  for (var i = 0; i < 1000; i++) {"
    2330             :                     "    a++;"
    2331             :                     "    if (a == x) break;"
    2332             :                     "    b++;"
    2333             :                     "    c++;"
    2334             :                     "  }"
    2335             :                     "  return b;"
    2336             :                     "}"
    2337             :                     "foo()";
    2338             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2339             :   v8::Local<v8::Value> result;
    2340           5 :   SetBreakPoint(foo, 8);  // "var a = 0;"
    2341             : 
    2342             :   // Each loop generates 5 steps except for the last (when break is executed)
    2343             :   // which only generates 4.
    2344             : 
    2345             :   // Looping 10 times.
    2346             :   run_step.set_step_action(StepIn);
    2347           5 :   break_point_hit_count = 0;
    2348           5 :   v8::Local<v8::Value> argv_10[argc] = {v8::Number::New(isolate, 10)};
    2349          15 :   result = foo->Call(context, env->Global(), argc, argv_10).ToLocalChecked();
    2350          10 :   CHECK_EQ(9, result->Int32Value(context).FromJust());
    2351           5 :   CHECK_EQ(64, break_point_hit_count);
    2352             : 
    2353             :   // Looping 100 times.
    2354             :   run_step.set_step_action(StepIn);
    2355           5 :   break_point_hit_count = 0;
    2356           5 :   v8::Local<v8::Value> argv_100[argc] = {v8::Number::New(isolate, 100)};
    2357          15 :   result = foo->Call(context, env->Global(), argc, argv_100).ToLocalChecked();
    2358          10 :   CHECK_EQ(99, result->Int32Value(context).FromJust());
    2359           5 :   CHECK_EQ(604, break_point_hit_count);
    2360             : 
    2361             :   // Get rid of the debug event listener.
    2362           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2363             :   CheckDebuggerUnloaded();
    2364           5 : }
    2365             : 
    2366             : 
    2367       26644 : TEST(DebugStepForIn) {
    2368           5 :   LocalContext env;
    2369          10 :   v8::HandleScope scope(env->GetIsolate());
    2370             : 
    2371             :   // Register a debug event listener which steps and counts.
    2372           5 :   DebugEventCounter run_step;
    2373           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2374             : 
    2375           5 :   v8::Local<v8::Context> context = env.local();
    2376             :   // Create a function for testing stepping. Run it to allow it to get
    2377             :   // optimized.
    2378             :   v8::Local<v8::Function> foo;
    2379             :   const char* src_1 = "function foo() { "
    2380             :                       "  var a = [1, 2];"
    2381             :                       "  for (x in a) {"
    2382             :                       "    b = 0;"
    2383             :                       "  }"
    2384             :                       "}"
    2385             :                       "foo()";
    2386             :   foo = CompileFunction(&env, src_1, "foo");
    2387           5 :   SetBreakPoint(foo, 0);  // "var a = ..."
    2388             : 
    2389             :   run_step.set_step_action(StepIn);
    2390           5 :   break_point_hit_count = 0;
    2391          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2392           5 :   CHECK_EQ(8, break_point_hit_count);
    2393             : 
    2394             :   // Create a function for testing stepping. Run it to allow it to get
    2395             :   // optimized.
    2396             :   const char* src_2 = "function foo() { "
    2397             :                       "  var a = {a:[1, 2, 3]};"
    2398             :                       "  for (x in a.a) {"
    2399             :                       "    b = 0;"
    2400             :                       "  }"
    2401             :                       "}"
    2402             :                       "foo()";
    2403             :   foo = CompileFunction(&env, src_2, "foo");
    2404           5 :   SetBreakPoint(foo, 0);  // "var a = ..."
    2405             : 
    2406             :   run_step.set_step_action(StepIn);
    2407           5 :   break_point_hit_count = 0;
    2408          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2409           5 :   CHECK_EQ(10, break_point_hit_count);
    2410             : 
    2411             :   // Get rid of the debug event listener.
    2412           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2413             :   CheckDebuggerUnloaded();
    2414           5 : }
    2415             : 
    2416             : 
    2417       26644 : TEST(DebugStepWith) {
    2418           5 :   LocalContext env;
    2419          10 :   v8::HandleScope scope(env->GetIsolate());
    2420             : 
    2421             :   // Register a debug event listener which steps and counts.
    2422           5 :   DebugEventCounter run_step;
    2423           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2424             : 
    2425           5 :   v8::Local<v8::Context> context = env.local();
    2426             :   // Create a function for testing stepping. Run it to allow it to get
    2427             :   // optimized.
    2428             :   const char* src = "function foo(x) { "
    2429             :                     "  var a = {};"
    2430             :                     "  with (a) {}"
    2431             :                     "  with (b) {}"
    2432             :                     "}"
    2433             :                     "foo()";
    2434          25 :   CHECK(env->Global()
    2435             :             ->Set(context, v8_str(env->GetIsolate(), "b"),
    2436             :                   v8::Object::New(env->GetIsolate()))
    2437             :             .FromJust());
    2438             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2439             :   v8::Local<v8::Value> result;
    2440           5 :   SetBreakPoint(foo, 8);  // "var a = {};"
    2441             : 
    2442             :   run_step.set_step_action(StepIn);
    2443           5 :   break_point_hit_count = 0;
    2444          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2445           5 :   CHECK_EQ(4, break_point_hit_count);
    2446             : 
    2447             :   // Get rid of the debug event listener.
    2448           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2449             :   CheckDebuggerUnloaded();
    2450           5 : }
    2451             : 
    2452             : 
    2453       26644 : TEST(DebugConditional) {
    2454           5 :   LocalContext env;
    2455           5 :   v8::Isolate* isolate = env->GetIsolate();
    2456          10 :   v8::HandleScope scope(isolate);
    2457             : 
    2458             :   // Register a debug event listener which steps and counts.
    2459           5 :   DebugEventCounter run_step;
    2460           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2461             : 
    2462           5 :   v8::Local<v8::Context> context = env.local();
    2463             :   // Create a function for testing stepping. Run it to allow it to get
    2464             :   // optimized.
    2465             :   const char* src =
    2466             :       "function foo(x) { "
    2467             :       "  return x ? 1 : 2;"
    2468             :       "}"
    2469             :       "foo()";
    2470             :   v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
    2471           5 :   SetBreakPoint(foo, 0);  // "var a;"
    2472             : 
    2473             :   run_step.set_step_action(StepIn);
    2474           5 :   break_point_hit_count = 0;
    2475          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2476           5 :   CHECK_EQ(2, break_point_hit_count);
    2477             : 
    2478             :   run_step.set_step_action(StepIn);
    2479           5 :   break_point_hit_count = 0;
    2480             :   const int argc = 1;
    2481             :   v8::Local<v8::Value> argv_true[argc] = {v8::True(isolate)};
    2482          15 :   foo->Call(context, env->Global(), argc, argv_true).ToLocalChecked();
    2483           5 :   CHECK_EQ(2, break_point_hit_count);
    2484             : 
    2485             :   // Get rid of the debug event listener.
    2486           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2487             :   CheckDebuggerUnloaded();
    2488           5 : }
    2489             : 
    2490             : // Test that step in does not step into native functions.
    2491       26644 : TEST(DebugStepNatives) {
    2492           5 :   LocalContext env;
    2493          10 :   v8::HandleScope scope(env->GetIsolate());
    2494             : 
    2495             :   // Create a function for testing stepping.
    2496             :   v8::Local<v8::Function> foo =
    2497             :       CompileFunction(&env, "function foo(){debugger;Math.sin(1);}", "foo");
    2498             : 
    2499             :   // Register a debug event listener which steps and counts.
    2500           5 :   DebugEventCounter run_step;
    2501           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2502             : 
    2503           5 :   v8::Local<v8::Context> context = env.local();
    2504             :   run_step.set_step_action(StepIn);
    2505           5 :   break_point_hit_count = 0;
    2506          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2507             : 
    2508             :   // With stepping all break locations are hit.
    2509           5 :   CHECK_EQ(3, break_point_hit_count);
    2510             : 
    2511           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2512             :   CheckDebuggerUnloaded();
    2513             : 
    2514             :   // Register a debug event listener which just counts.
    2515           5 :   DebugEventCounter delegate;
    2516           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2517             : 
    2518           5 :   break_point_hit_count = 0;
    2519          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2520             : 
    2521             :   // Without stepping only active break points are hit.
    2522           5 :   CHECK_EQ(1, break_point_hit_count);
    2523             : 
    2524           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2525             :   CheckDebuggerUnloaded();
    2526           5 : }
    2527             : 
    2528             : // Test that step in works with function.apply.
    2529       26644 : TEST(DebugStepFunctionApply) {
    2530           5 :   LocalContext env;
    2531          10 :   v8::HandleScope scope(env->GetIsolate());
    2532             : 
    2533             :   // Create a function for testing stepping.
    2534             :   v8::Local<v8::Function> foo =
    2535             :       CompileFunction(&env,
    2536             :                       "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
    2537             :                       "function foo(){ debugger; bar.apply(this, [1,2,3]); }",
    2538             :                       "foo");
    2539             : 
    2540             :   // Register a debug event listener which steps and counts.
    2541           5 :   DebugEventCounter run_step;
    2542           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2543             : 
    2544           5 :   v8::Local<v8::Context> context = env.local();
    2545             :   run_step.set_step_action(StepIn);
    2546           5 :   break_point_hit_count = 0;
    2547          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2548             : 
    2549             :   // With stepping all break locations are hit.
    2550           5 :   CHECK_EQ(7, break_point_hit_count);
    2551             : 
    2552           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2553             :   CheckDebuggerUnloaded();
    2554             : 
    2555             :   // Register a debug event listener which just counts.
    2556           5 :   DebugEventCounter delegate;
    2557           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2558             : 
    2559           5 :   break_point_hit_count = 0;
    2560          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2561             : 
    2562             :   // Without stepping only the debugger statement is hit.
    2563           5 :   CHECK_EQ(1, break_point_hit_count);
    2564             : 
    2565           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2566             :   CheckDebuggerUnloaded();
    2567           5 : }
    2568             : 
    2569             : 
    2570             : // Test that step in works with function.call.
    2571       26644 : TEST(DebugStepFunctionCall) {
    2572           5 :   LocalContext env;
    2573           5 :   v8::Isolate* isolate = env->GetIsolate();
    2574          10 :   v8::HandleScope scope(isolate);
    2575             : 
    2576           5 :   v8::Local<v8::Context> context = env.local();
    2577             :   // Create a function for testing stepping.
    2578             :   v8::Local<v8::Function> foo = CompileFunction(
    2579             :       &env,
    2580             :       "function bar(x, y, z) { if (x == 1) { a = y; b = z; } }"
    2581             :       "function foo(a){ debugger;"
    2582             :       "                 if (a) {"
    2583             :       "                   bar.call(this, 1, 2, 3);"
    2584             :       "                 } else {"
    2585             :       "                   bar.call(this, 0);"
    2586             :       "                 }"
    2587             :       "}",
    2588             :       "foo");
    2589             : 
    2590             :   // Register a debug event listener which steps and counts.
    2591           5 :   DebugEventCounter run_step;
    2592           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2593             :   run_step.set_step_action(StepIn);
    2594             : 
    2595             :   // Check stepping where the if condition in bar is false.
    2596           5 :   break_point_hit_count = 0;
    2597          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2598           5 :   CHECK_EQ(6, break_point_hit_count);
    2599             : 
    2600             :   // Check stepping where the if condition in bar is true.
    2601           5 :   break_point_hit_count = 0;
    2602             :   const int argc = 1;
    2603             :   v8::Local<v8::Value> argv[argc] = {v8::True(isolate)};
    2604          15 :   foo->Call(context, env->Global(), argc, argv).ToLocalChecked();
    2605           5 :   CHECK_EQ(8, break_point_hit_count);
    2606             : 
    2607           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2608             :   CheckDebuggerUnloaded();
    2609             : 
    2610             :   // Register a debug event listener which just counts.
    2611           5 :   DebugEventCounter delegate;
    2612           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2613             : 
    2614           5 :   break_point_hit_count = 0;
    2615          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2616             : 
    2617             :   // Without stepping only the debugger statement is hit.
    2618           5 :   CHECK_EQ(1, break_point_hit_count);
    2619             : 
    2620           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    2621             :   CheckDebuggerUnloaded();
    2622           5 : }
    2623             : 
    2624             : 
    2625             : // Test that step in works with Function.call.apply.
    2626       26644 : TEST(DebugStepFunctionCallApply) {
    2627           5 :   LocalContext env;
    2628           5 :   v8::Isolate* isolate = env->GetIsolate();
    2629          10 :   v8::HandleScope scope(isolate);
    2630             : 
    2631           5 :   v8::Local<v8::Context> context = env.local();
    2632             :   // Create a function for testing stepping.
    2633             :   v8::Local<v8::Function> foo =
    2634             :       CompileFunction(&env,
    2635             :                       "function bar() { }"
    2636             :                       "function foo(){ debugger;"
    2637             :                       "                Function.call.apply(bar);"
    2638             :                       "                Function.call.apply(Function.call, "
    2639             :                       "[Function.call, bar]);"
    2640             :                       "}",
    2641             :                       "foo");
    2642             : 
    2643             :   // Register a debug event listener which steps and counts.
    2644           5 :   DebugEventCounter run_step;
    2645           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &run_step);
    2646             :   run_step.set_step_action(StepIn);
    2647             : 
    2648           5 :   break_point_hit_count = 0;
    2649          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2650           5 :   CHECK_EQ(6, break_point_hit_count);
    2651             : 
    2652           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2653             :   CheckDebuggerUnloaded();
    2654             : 
    2655             :   // Register a debug event listener which just counts.
    2656           5 :   DebugEventCounter delegate;
    2657           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2658             : 
    2659           5 :   break_point_hit_count = 0;
    2660          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2661             : 
    2662             :   // Without stepping only the debugger statement is hit.
    2663           5 :   CHECK_EQ(1, break_point_hit_count);
    2664             : 
    2665           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    2666             :   CheckDebuggerUnloaded();
    2667           5 : }
    2668             : 
    2669             : 
    2670             : // Tests that breakpoint will be hit if it's set in script.
    2671       26644 : TEST(PauseInScript) {
    2672           5 :   LocalContext env;
    2673          10 :   v8::HandleScope scope(env->GetIsolate());
    2674           5 :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
    2675             : 
    2676             :   // Register a debug event listener which counts.
    2677           5 :   DebugEventCounter event_counter;
    2678           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &event_counter);
    2679             : 
    2680           5 :   v8::Local<v8::Context> context = env.local();
    2681             :   // Create a script that returns a function.
    2682             :   const char* src = "(function (evt) {})";
    2683             :   const char* script_name = "StepInHandlerTest";
    2684             : 
    2685             :   v8::ScriptOrigin origin(v8_str(env->GetIsolate(), script_name),
    2686          10 :                           v8::Integer::New(env->GetIsolate(), 0));
    2687             :   v8::Local<v8::Script> script =
    2688           5 :       v8::Script::Compile(context, v8_str(env->GetIsolate(), src), &origin)
    2689             :           .ToLocalChecked();
    2690             : 
    2691             :   // Set breakpoint in the script.
    2692             :   i::Handle<i::Script> i_script(
    2693          10 :       i::Script::cast(v8::Utils::OpenHandle(*script)->shared()->script()),
    2694           5 :       isolate);
    2695           5 :   i::Handle<i::String> condition = isolate->factory()->empty_string();
    2696           5 :   int position = 0;
    2697             :   int id;
    2698           5 :   isolate->debug()->SetBreakPointForScript(i_script, condition, &position, &id);
    2699           5 :   break_point_hit_count = 0;
    2700             : 
    2701           5 :   v8::Local<v8::Value> r = script->Run(context).ToLocalChecked();
    2702             : 
    2703           5 :   CHECK(r->IsFunction());
    2704           5 :   CHECK_EQ(1, break_point_hit_count);
    2705             : 
    2706             :   // Get rid of the debug delegate.
    2707           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2708             :   CheckDebuggerUnloaded();
    2709           5 : }
    2710             : 
    2711             : int message_callback_count = 0;
    2712             : 
    2713       26644 : TEST(DebugBreak) {
    2714           5 :   i::FLAG_stress_compaction = false;
    2715             : #ifdef VERIFY_HEAP
    2716             :   i::FLAG_verify_heap = true;
    2717             : #endif
    2718           5 :   LocalContext env;
    2719           5 :   v8::Isolate* isolate = env->GetIsolate();
    2720          10 :   v8::HandleScope scope(isolate);
    2721             : 
    2722             :   // Register a debug event listener which sets the break flag and counts.
    2723           5 :   DebugEventBreak delegate;
    2724           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2725             : 
    2726           5 :   v8::Local<v8::Context> context = env.local();
    2727             :   // Create a function for testing stepping.
    2728             :   const char* src = "function f0() {}"
    2729             :                     "function f1(x1) {}"
    2730             :                     "function f2(x1,x2) {}"
    2731             :                     "function f3(x1,x2,x3) {}";
    2732             :   v8::Local<v8::Function> f0 = CompileFunction(&env, src, "f0");
    2733             :   v8::Local<v8::Function> f1 = CompileFunction(&env, src, "f1");
    2734             :   v8::Local<v8::Function> f2 = CompileFunction(&env, src, "f2");
    2735             :   v8::Local<v8::Function> f3 = CompileFunction(&env, src, "f3");
    2736             : 
    2737             :   // Call the function to make sure it is compiled.
    2738             :   v8::Local<v8::Value> argv[] = {
    2739             :       v8::Number::New(isolate, 1), v8::Number::New(isolate, 1),
    2740          20 :       v8::Number::New(isolate, 1), v8::Number::New(isolate, 1)};
    2741             : 
    2742             :   // Call all functions to make sure that they are compiled.
    2743          15 :   f0->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2744          15 :   f1->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2745          15 :   f2->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2746          15 :   f3->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2747             : 
    2748             :   // Set the debug break flag.
    2749           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2750             : 
    2751             :   // Call all functions with different argument count.
    2752           5 :   break_point_hit_count = 0;
    2753          45 :   for (unsigned int i = 0; i < arraysize(argv); i++) {
    2754          80 :     f0->Call(context, env->Global(), i, argv).ToLocalChecked();
    2755          60 :     f1->Call(context, env->Global(), i, argv).ToLocalChecked();
    2756          60 :     f2->Call(context, env->Global(), i, argv).ToLocalChecked();
    2757          60 :     f3->Call(context, env->Global(), i, argv).ToLocalChecked();
    2758             :   }
    2759             : 
    2760             :   // One break for each function called.
    2761          10 :   CHECK_EQ(4 * arraysize(argv), break_point_hit_count);
    2762             : 
    2763             :   // Get rid of the debug event listener.
    2764           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2765             :   CheckDebuggerUnloaded();
    2766           5 : }
    2767             : 
    2768          10 : class DebugScopingListener : public v8::debug::DebugDelegate {
    2769             :  public:
    2770           0 :   void BreakProgramRequested(
    2771             :       v8::Local<v8::Context>,
    2772             :       const std::vector<v8::debug::BreakpointId>&) override {
    2773             :     auto stack_traces =
    2774           0 :         v8::debug::StackTraceIterator::Create(CcTest::isolate());
    2775           0 :     v8::debug::Location location = stack_traces->GetSourceLocation();
    2776           0 :     CHECK_EQ(26, location.GetColumnNumber());
    2777           0 :     CHECK_EQ(0, location.GetLineNumber());
    2778             : 
    2779           0 :     auto scopes = stack_traces->GetScopeIterator();
    2780           0 :     CHECK_EQ(v8::debug::ScopeIterator::ScopeTypeWith, scopes->GetType());
    2781           0 :     CHECK_EQ(20, scopes->GetStartLocation().GetColumnNumber());
    2782           0 :     CHECK_EQ(31, scopes->GetEndLocation().GetColumnNumber());
    2783             : 
    2784           0 :     scopes->Advance();
    2785           0 :     CHECK_EQ(v8::debug::ScopeIterator::ScopeTypeLocal, scopes->GetType());
    2786           0 :     CHECK_EQ(0, scopes->GetStartLocation().GetColumnNumber());
    2787           0 :     CHECK_EQ(68, scopes->GetEndLocation().GetColumnNumber());
    2788             : 
    2789           0 :     scopes->Advance();
    2790           0 :     CHECK_EQ(v8::debug::ScopeIterator::ScopeTypeGlobal, scopes->GetType());
    2791             : 
    2792           0 :     scopes->Advance();
    2793           0 :     CHECK(scopes->Done());
    2794           0 :   }
    2795             : };
    2796             : 
    2797       26644 : TEST(DebugBreakInWrappedScript) {
    2798           5 :   i::FLAG_stress_compaction = false;
    2799             : #ifdef VERIFY_HEAP
    2800             :   i::FLAG_verify_heap = true;
    2801             : #endif
    2802           5 :   LocalContext env;
    2803           5 :   v8::Isolate* isolate = env->GetIsolate();
    2804          10 :   v8::HandleScope scope(isolate);
    2805             : 
    2806             :   // Register a debug event listener which sets the break flag and counts.
    2807           5 :   DebugScopingListener delegate;
    2808           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2809             : 
    2810             :   static const char* source =
    2811             :       //   0         1         2         3         4         5         6 7
    2812             :       "try { with({o : []}){ o[0](); } } catch (e) { return e.toString(); }";
    2813             :   static const char* expect = "TypeError: o[0] is not a function";
    2814             : 
    2815             :   // For this test, we want to break on uncaught exceptions:
    2816           5 :   ChangeBreakOnException(true, true);
    2817             : 
    2818             :   {
    2819           5 :     v8::ScriptCompiler::Source script_source(v8_str(source));
    2820             :     v8::Local<v8::Function> fun =
    2821           5 :         v8::ScriptCompiler::CompileFunctionInContext(
    2822             :             env.local(), &script_source, 0, nullptr, 0, nullptr)
    2823             :             .ToLocalChecked();
    2824             :     v8::Local<v8::Value> result =
    2825          15 :         fun->Call(env.local(), env->Global(), 0, nullptr).ToLocalChecked();
    2826           5 :     CHECK(result->IsString());
    2827          15 :     CHECK(v8::Local<v8::String>::Cast(result)
    2828             :               ->Equals(env.local(), v8_str(expect))
    2829             :               .FromJust());
    2830             :   }
    2831             : 
    2832             :   // Get rid of the debug event listener.
    2833           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2834             :   CheckDebuggerUnloaded();
    2835           5 : }
    2836             : 
    2837           0 : static void EmptyHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {}
    2838             : 
    2839       26644 : TEST(DebugScopeIteratorWithFunctionTemplate) {
    2840           5 :   LocalContext env;
    2841          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    2842           5 :   v8::Isolate* isolate = env->GetIsolate();
    2843             :   EnableDebugger(isolate);
    2844             :   v8::Local<v8::Function> func =
    2845          10 :       v8::Function::New(env.local(), EmptyHandler).ToLocalChecked();
    2846             :   std::unique_ptr<v8::debug::ScopeIterator> iterator =
    2847           5 :       v8::debug::ScopeIterator::CreateForFunction(isolate, func);
    2848           5 :   CHECK(iterator->Done());
    2849             :   DisableDebugger(isolate);
    2850           5 : }
    2851             : 
    2852       26644 : TEST(DebugBreakWithoutJS) {
    2853           5 :   i::FLAG_stress_compaction = false;
    2854             : #ifdef VERIFY_HEAP
    2855             :   i::FLAG_verify_heap = true;
    2856             : #endif
    2857           5 :   LocalContext env;
    2858           5 :   v8::Isolate* isolate = env->GetIsolate();
    2859          10 :   v8::HandleScope scope(isolate);
    2860           5 :   v8::Local<v8::Context> context = env.local();
    2861             : 
    2862             :   // Register a debug event listener which sets the break flag and counts.
    2863           5 :   DebugEventBreak delegate;
    2864           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2865             : 
    2866             :   // Set the debug break flag.
    2867           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2868             : 
    2869           5 :   v8::Local<v8::String> json = v8_str("[1]");
    2870          10 :   v8::Local<v8::Value> parsed = v8::JSON::Parse(context, json).ToLocalChecked();
    2871          15 :   CHECK(v8::JSON::Stringify(context, parsed)
    2872             :             .ToLocalChecked()
    2873             :             ->Equals(context, json)
    2874             :             .FromJust());
    2875           5 :   CHECK_EQ(0, break_point_hit_count);
    2876             :   CompileRun("");
    2877           5 :   CHECK_EQ(1, break_point_hit_count);
    2878             : 
    2879             :   // Get rid of the debug event listener.
    2880           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2881             :   CheckDebuggerUnloaded();
    2882           5 : }
    2883             : 
    2884             : // Test to ensure that JavaScript code keeps running while the debug break
    2885             : // through the stack limit flag is set but breaks are disabled.
    2886       26644 : TEST(DisableBreak) {
    2887           5 :   LocalContext env;
    2888          10 :   v8::HandleScope scope(env->GetIsolate());
    2889             : 
    2890             :   // Register a debug event listener which sets the break flag and counts.
    2891           5 :   DebugEventCounter delegate;
    2892           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2893             : 
    2894           5 :   v8::Local<v8::Context> context = env.local();
    2895             :   // Create a function for testing stepping.
    2896             :   const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
    2897             :   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
    2898             : 
    2899             :   // Set, test and cancel debug break.
    2900           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2901           5 :   v8::debug::ClearBreakOnNextFunctionCall(env->GetIsolate());
    2902             : 
    2903             :   // Set the debug break flag.
    2904           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2905             : 
    2906             :   // Call all functions with different argument count.
    2907           5 :   break_point_hit_count = 0;
    2908          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2909           5 :   CHECK_EQ(1, break_point_hit_count);
    2910             : 
    2911             :   {
    2912           5 :     v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    2913           5 :     i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
    2914             :     v8::internal::DisableBreak disable_break(isolate->debug());
    2915          15 :     f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2916           5 :     CHECK_EQ(1, break_point_hit_count);
    2917             :   }
    2918             : 
    2919          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    2920           5 :   CHECK_EQ(2, break_point_hit_count);
    2921             : 
    2922             :   // Get rid of the debug event listener.
    2923           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2924             :   CheckDebuggerUnloaded();
    2925           5 : }
    2926             : 
    2927       26644 : TEST(DisableDebuggerStatement) {
    2928           5 :   LocalContext env;
    2929          10 :   v8::HandleScope scope(env->GetIsolate());
    2930             : 
    2931             :   // Register a debug event listener which sets the break flag and counts.
    2932           5 :   DebugEventCounter delegate;
    2933           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    2934             : 
    2935             :   CompileRun("debugger;");
    2936           5 :   CHECK_EQ(1, break_point_hit_count);
    2937             : 
    2938             :   // Check that we ignore debugger statement when breakpoints aren't active.
    2939           5 :   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
    2940             :   isolate->debug()->set_break_points_active(false);
    2941             :   CompileRun("debugger;");
    2942           5 :   CHECK_EQ(1, break_point_hit_count);
    2943             : 
    2944           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    2945           5 : }
    2946             : 
    2947             : static const char* kSimpleExtensionSource =
    2948             :   "(function Foo() {"
    2949             :   "  return 4;"
    2950             :   "})() ";
    2951             : 
    2952             : // http://crbug.com/28933
    2953             : // Test that debug break is disabled when bootstrapper is active.
    2954       26644 : TEST(NoBreakWhenBootstrapping) {
    2955           5 :   v8::Isolate* isolate = CcTest::isolate();
    2956          10 :   v8::HandleScope scope(isolate);
    2957             : 
    2958             :   // Register a debug event listener which sets the break flag and counts.
    2959           5 :   DebugEventCounter delegate;
    2960           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    2961             : 
    2962             :   // Set the debug break flag.
    2963           5 :   v8::debug::SetBreakOnNextFunctionCall(isolate);
    2964           5 :   break_point_hit_count = 0;
    2965             :   {
    2966             :     // Create a context with an extension to make sure that some JavaScript
    2967             :     // code is executed during bootstrapping.
    2968          10 :     v8::RegisterExtension(v8::base::make_unique<v8::Extension>(
    2969           5 :         "simpletest", kSimpleExtensionSource));
    2970           5 :     const char* extension_names[] = { "simpletest" };
    2971             :     v8::ExtensionConfiguration extensions(1, extension_names);
    2972          10 :     v8::HandleScope handle_scope(isolate);
    2973           5 :     v8::Context::New(isolate, &extensions);
    2974             :   }
    2975             :   // Check that no DebugBreak events occurred during the context creation.
    2976           5 :   CHECK_EQ(0, break_point_hit_count);
    2977             : 
    2978             :   // Get rid of the debug event listener.
    2979           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    2980             :   CheckDebuggerUnloaded();
    2981           5 : }
    2982             : 
    2983       26644 : TEST(SetDebugEventListenerOnUninitializedVM) {
    2984          10 :   v8::HandleScope scope(CcTest::isolate());
    2985           5 :   EnableDebugger(CcTest::isolate());
    2986           5 : }
    2987             : 
    2988             : // Test that clearing the debug event listener actually clears all break points
    2989             : // and related information.
    2990       26644 : TEST(DebuggerUnload) {
    2991           5 :   LocalContext env;
    2992          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    2993             :   // Check debugger is unloaded before it is used.
    2994             :   CheckDebuggerUnloaded();
    2995             : 
    2996             :   // Set a debug event listener.
    2997           5 :   break_point_hit_count = 0;
    2998           5 :   DebugEventCounter delegate;
    2999           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3000           5 :   v8::Local<v8::Context> context = env.local();
    3001             :   {
    3002          10 :     v8::HandleScope scope(env->GetIsolate());
    3003             :     // Create a couple of functions for the test.
    3004             :     v8::Local<v8::Function> foo =
    3005             :         CompileFunction(&env, "function foo(){x=1}", "foo");
    3006             :     v8::Local<v8::Function> bar =
    3007             :         CompileFunction(&env, "function bar(){y=2}", "bar");
    3008             : 
    3009             :     // Set some break points.
    3010           5 :     SetBreakPoint(foo, 0);
    3011           5 :     SetBreakPoint(foo, 4);
    3012           5 :     SetBreakPoint(bar, 0);
    3013           5 :     SetBreakPoint(bar, 4);
    3014             : 
    3015             :     // Make sure that the break points are there.
    3016           5 :     break_point_hit_count = 0;
    3017          15 :     foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3018           5 :     CHECK_EQ(2, break_point_hit_count);
    3019          15 :     bar->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3020           5 :     CHECK_EQ(4, break_point_hit_count);
    3021             :   }
    3022             : 
    3023             :   // Remove the debug event listener without clearing breakpoints. Do this
    3024             :   // outside a handle scope.
    3025           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3026             :   CheckDebuggerUnloaded();
    3027           5 : }
    3028             : 
    3029             : int event_listener_hit_count = 0;
    3030             : 
    3031             : // Test for issue http://code.google.com/p/v8/issues/detail?id=289.
    3032             : // Make sure that DebugGetLoadedScripts doesn't return scripts
    3033             : // with disposed external source.
    3034             : class EmptyExternalStringResource : public v8::String::ExternalStringResource {
    3035             :  public:
    3036             :   EmptyExternalStringResource() { empty_[0] = 0; }
    3037           0 :   ~EmptyExternalStringResource() override = default;
    3038           0 :   size_t length() const override { return empty_.length(); }
    3039           0 :   const uint16_t* data() const override { return empty_.start(); }
    3040             : 
    3041             :  private:
    3042             :   ::v8::internal::EmbeddedVector<uint16_t, 1> empty_;
    3043             : };
    3044             : 
    3045       26644 : TEST(DebugScriptLineEndsAreAscending) {
    3046           5 :   LocalContext env;
    3047           5 :   v8::Isolate* isolate = env->GetIsolate();
    3048          10 :   v8::HandleScope scope(isolate);
    3049             : 
    3050             :   // Compile a test script.
    3051             :   v8::Local<v8::String> script = v8_str(isolate,
    3052             :                                         "function f() {\n"
    3053             :                                         "  debugger;\n"
    3054           5 :                                         "}\n");
    3055             : 
    3056           5 :   v8::ScriptOrigin origin1 = v8::ScriptOrigin(v8_str(isolate, "name"));
    3057             :   v8::Local<v8::Script> script1 =
    3058           5 :       v8::Script::Compile(env.local(), script, &origin1).ToLocalChecked();
    3059             :   USE(script1);
    3060             : 
    3061             :   Handle<v8::internal::FixedArray> instances;
    3062             :   {
    3063             :     v8::internal::Debug* debug = CcTest::i_isolate()->debug();
    3064           5 :     instances = debug->GetLoadedScripts();
    3065             :   }
    3066             : 
    3067           5 :   CHECK_GT(instances->length(), 0);
    3068          45 :   for (int i = 0; i < instances->length(); i++) {
    3069             :     Handle<v8::internal::Script> script = Handle<v8::internal::Script>(
    3070             :         v8::internal::Script::cast(instances->get(i)), CcTest::i_isolate());
    3071             : 
    3072          20 :     v8::internal::Script::InitLineEnds(script);
    3073             :     v8::internal::FixedArray ends =
    3074             :         v8::internal::FixedArray::cast(script->line_ends());
    3075          20 :     CHECK_GT(ends->length(), 0);
    3076             : 
    3077             :     int prev_end = -1;
    3078        1030 :     for (int j = 0; j < ends->length(); j++) {
    3079             :       const int curr_end = v8::internal::Smi::ToInt(ends->get(j));
    3080         505 :       CHECK_GT(curr_end, prev_end);
    3081             :       prev_end = curr_end;
    3082             :     }
    3083             :   }
    3084           5 : }
    3085             : 
    3086             : static v8::Local<v8::Context> expected_context;
    3087             : static v8::Local<v8::Value> expected_context_data;
    3088             : 
    3089          20 : class ContextCheckEventListener : public v8::debug::DebugDelegate {
    3090             :  public:
    3091          15 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3092             :                              const std::vector<v8::debug::BreakpointId>&
    3093             :                                  inspector_break_points_hit) override {
    3094          15 :     CheckContext();
    3095          15 :   }
    3096          20 :   void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
    3097             :                       bool has_compile_error) override {
    3098          20 :     CheckContext();
    3099          20 :   }
    3100           0 :   void ExceptionThrown(v8::Local<v8::Context> paused_context,
    3101             :                        v8::Local<v8::Value> exception,
    3102             :                        v8::Local<v8::Value> promise, bool is_uncaught,
    3103             :                        v8::debug::ExceptionType) override {
    3104           0 :     CheckContext();
    3105           0 :   }
    3106          15 :   bool IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
    3107             :                             const v8::debug::Location& start,
    3108             :                             const v8::debug::Location& end) override {
    3109          15 :     CheckContext();
    3110          15 :     return false;
    3111             :   }
    3112             : 
    3113             :  private:
    3114          50 :   void CheckContext() {
    3115          50 :     v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
    3116          50 :     CHECK(context == expected_context);
    3117          50 :     CHECK(context->GetEmbedderData(0)->StrictEquals(expected_context_data));
    3118          50 :     event_listener_hit_count++;
    3119          50 :   }
    3120             : };
    3121             : 
    3122             : // Test which creates two contexts and sets different embedder data on each.
    3123             : // Checks that this data is set correctly and that when the debug event
    3124             : // listener is called the expected context is the one active.
    3125       26644 : TEST(ContextData) {
    3126           5 :   v8::Isolate* isolate = CcTest::isolate();
    3127          10 :   v8::HandleScope scope(isolate);
    3128             : 
    3129             :   // Create two contexts.
    3130             :   v8::Local<v8::Context> context_1;
    3131             :   v8::Local<v8::Context> context_2;
    3132             :   v8::Local<v8::ObjectTemplate> global_template =
    3133             :       v8::Local<v8::ObjectTemplate>();
    3134             :   v8::Local<v8::Value> global_object = v8::Local<v8::Value>();
    3135             :   context_1 =
    3136           5 :       v8::Context::New(isolate, nullptr, global_template, global_object);
    3137             :   context_2 =
    3138           5 :       v8::Context::New(isolate, nullptr, global_template, global_object);
    3139             : 
    3140           5 :   ContextCheckEventListener delegate;
    3141           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3142             : 
    3143             :   // Default data value is undefined.
    3144           5 :   CHECK_EQ(0, context_1->GetNumberOfEmbedderDataFields());
    3145           5 :   CHECK_EQ(0, context_2->GetNumberOfEmbedderDataFields());
    3146             : 
    3147             :   // Set and check different data values.
    3148           5 :   v8::Local<v8::String> data_1 = v8_str(isolate, "1");
    3149           5 :   v8::Local<v8::String> data_2 = v8_str(isolate, "2");
    3150           5 :   context_1->SetEmbedderData(0, data_1);
    3151           5 :   context_2->SetEmbedderData(0, data_2);
    3152           5 :   CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
    3153           5 :   CHECK(context_2->GetEmbedderData(0)->StrictEquals(data_2));
    3154             : 
    3155             :   // Simple test function which causes a break.
    3156             :   const char* source = "function f() { debugger; }";
    3157             : 
    3158             :   // Enter and run function in the first context.
    3159             :   {
    3160             :     v8::Context::Scope context_scope(context_1);
    3161           5 :     expected_context = context_1;
    3162           5 :     expected_context_data = data_1;
    3163           5 :     v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
    3164          15 :     f->Call(context_1, context_1->Global(), 0, nullptr).ToLocalChecked();
    3165             :   }
    3166             : 
    3167             :   // Enter and run function in the second context.
    3168             :   {
    3169             :     v8::Context::Scope context_scope(context_2);
    3170           5 :     expected_context = context_2;
    3171           5 :     expected_context_data = data_2;
    3172           5 :     v8::Local<v8::Function> f = CompileFunction(isolate, source, "f");
    3173          15 :     f->Call(context_2, context_2->Global(), 0, nullptr).ToLocalChecked();
    3174             :   }
    3175             : 
    3176             :   // Two times compile event and two times break event.
    3177           5 :   CHECK_GT(event_listener_hit_count, 3);
    3178             : 
    3179           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    3180             :   CheckDebuggerUnloaded();
    3181           5 : }
    3182             : 
    3183             : // Test which creates a context and sets embedder data on it. Checks that this
    3184             : // data is set correctly and that when the debug event listener is called for
    3185             : // break event in an eval statement the expected context is the one returned by
    3186             : // Message.GetEventContext.
    3187       26644 : TEST(EvalContextData) {
    3188          10 :   v8::HandleScope scope(CcTest::isolate());
    3189             : 
    3190             :   v8::Local<v8::Context> context_1;
    3191             :   v8::Local<v8::ObjectTemplate> global_template =
    3192             :       v8::Local<v8::ObjectTemplate>();
    3193           5 :   context_1 = v8::Context::New(CcTest::isolate(), nullptr, global_template);
    3194             : 
    3195           5 :   ContextCheckEventListener delegate;
    3196           5 :   v8::debug::SetDebugDelegate(CcTest::isolate(), &delegate);
    3197             : 
    3198             :   // Contexts initially do not have embedder data fields.
    3199           5 :   CHECK_EQ(0, context_1->GetNumberOfEmbedderDataFields());
    3200             : 
    3201             :   // Set and check a data value.
    3202           5 :   v8::Local<v8::String> data_1 = v8_str(CcTest::isolate(), "1");
    3203           5 :   context_1->SetEmbedderData(0, data_1);
    3204           5 :   CHECK(context_1->GetEmbedderData(0)->StrictEquals(data_1));
    3205             : 
    3206             :   // Simple test function with eval that causes a break.
    3207             :   const char* source = "function f() { eval('debugger;'); }";
    3208             : 
    3209             :   // Enter and run function in the context.
    3210             :   {
    3211             :     v8::Context::Scope context_scope(context_1);
    3212           5 :     expected_context = context_1;
    3213           5 :     expected_context_data = data_1;
    3214           5 :     v8::Local<v8::Function> f = CompileFunction(CcTest::isolate(), source, "f");
    3215          15 :     f->Call(context_1, context_1->Global(), 0, nullptr).ToLocalChecked();
    3216             :   }
    3217             : 
    3218           5 :   v8::debug::SetDebugDelegate(CcTest::isolate(), nullptr);
    3219             : 
    3220             :   // One time compile event and one time break event.
    3221           5 :   CHECK_GT(event_listener_hit_count, 2);
    3222             :   CheckDebuggerUnloaded();
    3223           5 : }
    3224             : 
    3225             : // Debug event listener which counts script compiled events.
    3226          40 : class ScriptCompiledDelegate : public v8::debug::DebugDelegate {
    3227             :  public:
    3228          50 :   void ScriptCompiled(v8::Local<v8::debug::Script>, bool,
    3229             :                       bool has_compile_error) override {
    3230          50 :     if (!has_compile_error) {
    3231          35 :       after_compile_event_count++;
    3232             :     } else {
    3233          15 :       compile_error_event_count++;
    3234             :     }
    3235          50 :   }
    3236             : 
    3237             :   int after_compile_event_count = 0;
    3238             :   int compile_error_event_count = 0;
    3239             : };
    3240             : 
    3241             : // Tests that after compile event is sent as many times as there are scripts
    3242             : // compiled.
    3243       26644 : TEST(AfterCompileEventWhenEventListenerIsReset) {
    3244           5 :   LocalContext env;
    3245          10 :   v8::HandleScope scope(env->GetIsolate());
    3246           5 :   v8::Local<v8::Context> context = env.local();
    3247             :   const char* script = "var a=1";
    3248             : 
    3249           5 :   ScriptCompiledDelegate delegate;
    3250           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3251           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
    3252             :       .ToLocalChecked()
    3253           5 :       ->Run(context)
    3254             :       .ToLocalChecked();
    3255           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3256             : 
    3257           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3258           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3259           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
    3260             :       .ToLocalChecked()
    3261           5 :       ->Run(context)
    3262             :       .ToLocalChecked();
    3263             : 
    3264             :   // Setting listener to nullptr should cause debugger unload.
    3265           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3266             :   CheckDebuggerUnloaded();
    3267             : 
    3268             :   // Compilation cache should be disabled when debugger is active.
    3269           5 :   CHECK_EQ(2, delegate.after_compile_event_count);
    3270           5 : }
    3271             : 
    3272             : // Tests that syntax error event is sent as many times as there are scripts
    3273             : // with syntax error compiled.
    3274       26644 : TEST(SyntaxErrorEventOnSyntaxException) {
    3275           5 :   LocalContext env;
    3276          10 :   v8::HandleScope scope(env->GetIsolate());
    3277             : 
    3278             :   // For this test, we want to break on uncaught exceptions:
    3279           5 :   ChangeBreakOnException(false, true);
    3280             : 
    3281           5 :   ScriptCompiledDelegate delegate;
    3282           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3283           5 :   v8::Local<v8::Context> context = env.local();
    3284             : 
    3285             :   // Check initial state.
    3286           5 :   CHECK_EQ(0, delegate.compile_error_event_count);
    3287             : 
    3288             :   // Throws SyntaxError: Unexpected end of input
    3289          10 :   CHECK(
    3290             :       v8::Script::Compile(context, v8_str(env->GetIsolate(), "+++")).IsEmpty());
    3291           5 :   CHECK_EQ(1, delegate.compile_error_event_count);
    3292             : 
    3293          10 :   CHECK(v8::Script::Compile(context, v8_str(env->GetIsolate(), "/sel\\/: \\"))
    3294             :             .IsEmpty());
    3295           5 :   CHECK_EQ(2, delegate.compile_error_event_count);
    3296             : 
    3297             :   v8::Local<v8::Script> script =
    3298           5 :       v8::Script::Compile(context,
    3299           5 :                           v8_str(env->GetIsolate(), "JSON.parse('1234:')"))
    3300             :           .ToLocalChecked();
    3301           5 :   CHECK_EQ(2, delegate.compile_error_event_count);
    3302          10 :   CHECK(script->Run(context).IsEmpty());
    3303           5 :   CHECK_EQ(3, delegate.compile_error_event_count);
    3304             : 
    3305           5 :   v8::Script::Compile(context,
    3306           5 :                       v8_str(env->GetIsolate(), "new RegExp('/\\/\\\\');"))
    3307             :       .ToLocalChecked();
    3308           5 :   CHECK_EQ(3, delegate.compile_error_event_count);
    3309             : 
    3310           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), "throw 1;"))
    3311             :       .ToLocalChecked();
    3312           5 :   CHECK_EQ(3, delegate.compile_error_event_count);
    3313           5 : }
    3314             : 
    3315             : // Tests that break event is sent when event listener is reset.
    3316       26644 : TEST(BreakEventWhenEventListenerIsReset) {
    3317           5 :   LocalContext env;
    3318          10 :   v8::HandleScope scope(env->GetIsolate());
    3319           5 :   v8::Local<v8::Context> context = env.local();
    3320             :   const char* script = "function f() {};";
    3321             : 
    3322           5 :   ScriptCompiledDelegate delegate;
    3323           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3324           5 :   v8::Script::Compile(context, v8_str(env->GetIsolate(), script))
    3325             :       .ToLocalChecked()
    3326           5 :       ->Run(context)
    3327             :       .ToLocalChecked();
    3328           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3329             : 
    3330           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3331           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3332             :   v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
    3333          10 :       env->Global()
    3334          15 :           ->Get(context, v8_str(env->GetIsolate(), "f"))
    3335             :           .ToLocalChecked());
    3336          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3337             : 
    3338             :   // Setting event listener to nullptr should cause debugger unload.
    3339           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3340             :   CheckDebuggerUnloaded();
    3341             : 
    3342             :   // Compilation cache should be disabled when debugger is active.
    3343           5 :   CHECK_EQ(1, delegate.after_compile_event_count);
    3344           5 : }
    3345             : 
    3346             : // Tests that script is reported as compiled when bound to context.
    3347       26644 : TEST(AfterCompileEventOnBindToContext) {
    3348           5 :   LocalContext env;
    3349           5 :   v8::Isolate* isolate = env->GetIsolate();
    3350          10 :   v8::HandleScope handle_scope(isolate);
    3351           5 :   ScriptCompiledDelegate delegate;
    3352           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3353             : 
    3354             :   const char* source = "var a=1";
    3355             :   v8::ScriptCompiler::Source script_source(
    3356           5 :       v8::String::NewFromUtf8(isolate, source, v8::NewStringType::kNormal)
    3357             :           .ToLocalChecked());
    3358             : 
    3359             :   v8::Local<v8::UnboundScript> unbound =
    3360           5 :       v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
    3361             :           .ToLocalChecked();
    3362           5 :   CHECK_EQ(delegate.after_compile_event_count, 0);
    3363             : 
    3364           5 :   unbound->BindToCurrentContext();
    3365           5 :   CHECK_EQ(delegate.after_compile_event_count, 1);
    3366           5 :   v8::debug::SetDebugDelegate(isolate, nullptr);
    3367           5 : }
    3368             : 
    3369             : 
    3370             : // Test that if DebugBreak is forced it is ignored when code from
    3371             : // debug-delay.js is executed.
    3372       26644 : TEST(NoDebugBreakInAfterCompileEventListener) {
    3373           5 :   LocalContext env;
    3374          10 :   v8::HandleScope scope(env->GetIsolate());
    3375           5 :   v8::Local<v8::Context> context = env.local();
    3376             : 
    3377             :   // Register a debug event listener which sets the break flag and counts.
    3378           5 :   DebugEventCounter delegate;
    3379           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3380             : 
    3381             :   // Set the debug break flag.
    3382           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3383             : 
    3384             :   // Create a function for testing stepping.
    3385             :   const char* src = "function f() { eval('var x = 10;'); } ";
    3386             :   v8::Local<v8::Function> f = CompileFunction(&env, src, "f");
    3387             : 
    3388             :   // There should be only one break event.
    3389           5 :   CHECK_EQ(1, break_point_hit_count);
    3390             : 
    3391             :   // Set the debug break flag again.
    3392           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3393          15 :   f->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3394             :   // There should be one more break event when the script is evaluated in 'f'.
    3395           5 :   CHECK_EQ(2, break_point_hit_count);
    3396             : 
    3397             :   // Get rid of the debug event listener.
    3398           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3399             :   CheckDebuggerUnloaded();
    3400           5 : }
    3401             : 
    3402             : 
    3403             : // Test that the debug break flag works with function.apply.
    3404       26644 : TEST(DebugBreakFunctionApply) {
    3405           5 :   LocalContext env;
    3406          10 :   v8::HandleScope scope(env->GetIsolate());
    3407           5 :   v8::Local<v8::Context> context = env.local();
    3408             : 
    3409             :   // Create a function for testing breaking in apply.
    3410             :   v8::Local<v8::Function> foo = CompileFunction(
    3411             :       &env,
    3412             :       "function baz(x) { }"
    3413             :       "function bar(x) { baz(); }"
    3414             :       "function foo(){ bar.apply(this, [1]); }",
    3415             :       "foo");
    3416             : 
    3417             :   // Register a debug event listener which steps and counts.
    3418           5 :   DebugEventBreakMax delegate;
    3419           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3420             : 
    3421             :   // Set the debug break flag before calling the code using function.apply.
    3422           5 :   v8::debug::SetBreakOnNextFunctionCall(env->GetIsolate());
    3423             : 
    3424             :   // Limit the number of debug breaks. This is a regression test for issue 493
    3425             :   // where this test would enter an infinite loop.
    3426           5 :   break_point_hit_count = 0;
    3427           5 :   max_break_point_hit_count = 10000;  // 10000 => infinite loop.
    3428          15 :   foo->Call(context, env->Global(), 0, nullptr).ToLocalChecked();
    3429             : 
    3430             :   // When keeping the debug break several break will happen.
    3431           5 :   CHECK_GT(break_point_hit_count, 1);
    3432             : 
    3433           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3434             :   CheckDebuggerUnloaded();
    3435           5 : }
    3436             : 
    3437             : // Test that setting the terminate execution flag during debug break processing.
    3438          60 : static void TestDebugBreakInLoop(const char* loop_head,
    3439             :                                  const char** loop_bodies,
    3440             :                                  const char* loop_tail) {
    3441             :   // Receive 10 breaks for each test and then terminate JavaScript execution.
    3442             :   static const int kBreaksPerTest = 10;
    3443             : 
    3444         720 :   for (int i = 0; loop_bodies[i] != nullptr; i++) {
    3445             :     // Perform a lazy deoptimization after various numbers of breaks
    3446             :     // have been hit.
    3447             : 
    3448             :     i::EmbeddedVector<char, 1024> buffer;
    3449             :     SNPrintF(buffer, "function f() {%s%s%s}", loop_head, loop_bodies[i],
    3450         330 :              loop_tail);
    3451             : 
    3452         330 :     i::PrintF("%s\n", buffer.start());
    3453             : 
    3454        2310 :     for (int j = 0; j < 3; j++) {
    3455         990 :       break_point_hit_count_deoptimize = j;
    3456         990 :       if (j == 2) {
    3457         330 :         break_point_hit_count_deoptimize = kBreaksPerTest;
    3458             :       }
    3459             : 
    3460         990 :       break_point_hit_count = 0;
    3461         990 :       max_break_point_hit_count = kBreaksPerTest;
    3462         990 :       terminate_after_max_break_point_hit = true;
    3463             : 
    3464             :       // Function with infinite loop.
    3465             :       CompileRun(buffer.start());
    3466             : 
    3467             :       // Set the debug break to enter the debugger as soon as possible.
    3468         990 :       v8::debug::SetBreakOnNextFunctionCall(CcTest::isolate());
    3469             : 
    3470             :       // Call function with infinite loop.
    3471             :       CompileRun("f();");
    3472         990 :       CHECK_EQ(kBreaksPerTest, break_point_hit_count);
    3473             : 
    3474         990 :       CHECK(!CcTest::isolate()->IsExecutionTerminating());
    3475             :     }
    3476             :   }
    3477          60 : }
    3478             : 
    3479             : static const char* loop_bodies_1[] = {"",
    3480             :                                       "g()",
    3481             :                                       "if (a == 0) { g() }",
    3482             :                                       "if (a == 1) { g() }",
    3483             :                                       "if (a == 0) { g() } else { h() }",
    3484             :                                       "if (a == 0) { continue }",
    3485             :                                       nullptr};
    3486             : 
    3487             : static const char* loop_bodies_2[] = {
    3488             :     "if (a == 1) { continue }",
    3489             :     "switch (a) { case 1: g(); }",
    3490             :     "switch (a) { case 1: continue; }",
    3491             :     "switch (a) { case 1: g(); break; default: h() }",
    3492             :     "switch (a) { case 1: continue; break; default: h() }",
    3493             :     nullptr};
    3494             : 
    3495          60 : void DebugBreakLoop(const char* loop_header, const char** loop_bodies,
    3496             :                     const char* loop_footer) {
    3497          60 :   LocalContext env;
    3498         120 :   v8::HandleScope scope(env->GetIsolate());
    3499             : 
    3500             :   // Register a debug event listener which sets the break flag and counts.
    3501          60 :   DebugEventBreakMax delegate;
    3502          60 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3503             : 
    3504             :   CompileRun(
    3505             :       "var a = 1;\n"
    3506             :       "function g() { }\n"
    3507             :       "function h() { }");
    3508             : 
    3509          60 :   TestDebugBreakInLoop(loop_header, loop_bodies, loop_footer);
    3510             : 
    3511             :   // Get rid of the debug event listener.
    3512          60 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3513             :   CheckDebuggerUnloaded();
    3514          60 : }
    3515             : 
    3516             : 
    3517       26644 : TEST(DebugBreakInWhileTrue1) {
    3518           5 :   DebugBreakLoop("while (true) {", loop_bodies_1, "}");
    3519           5 : }
    3520             : 
    3521             : 
    3522       26644 : TEST(DebugBreakInWhileTrue2) {
    3523           5 :   DebugBreakLoop("while (true) {", loop_bodies_2, "}");
    3524           5 : }
    3525             : 
    3526             : 
    3527       26644 : TEST(DebugBreakInWhileCondition1) {
    3528           5 :   DebugBreakLoop("while (a == 1) {", loop_bodies_1, "}");
    3529           5 : }
    3530             : 
    3531             : 
    3532       26644 : TEST(DebugBreakInWhileCondition2) {
    3533           5 :   DebugBreakLoop("while (a == 1) {", loop_bodies_2, "}");
    3534           5 : }
    3535             : 
    3536             : 
    3537       26644 : TEST(DebugBreakInDoWhileTrue1) {
    3538           5 :   DebugBreakLoop("do {", loop_bodies_1, "} while (true)");
    3539           5 : }
    3540             : 
    3541             : 
    3542       26644 : TEST(DebugBreakInDoWhileTrue2) {
    3543           5 :   DebugBreakLoop("do {", loop_bodies_2, "} while (true)");
    3544           5 : }
    3545             : 
    3546             : 
    3547       26644 : TEST(DebugBreakInDoWhileCondition1) {
    3548           5 :   DebugBreakLoop("do {", loop_bodies_1, "} while (a == 1)");
    3549           5 : }
    3550             : 
    3551             : 
    3552       26644 : TEST(DebugBreakInDoWhileCondition2) {
    3553           5 :   DebugBreakLoop("do {", loop_bodies_2, "} while (a == 1)");
    3554           5 : }
    3555             : 
    3556             : 
    3557       26644 : TEST(DebugBreakInFor1) { DebugBreakLoop("for (;;) {", loop_bodies_1, "}"); }
    3558             : 
    3559             : 
    3560       26644 : TEST(DebugBreakInFor2) { DebugBreakLoop("for (;;) {", loop_bodies_2, "}"); }
    3561             : 
    3562             : 
    3563       26644 : TEST(DebugBreakInForCondition1) {
    3564           5 :   DebugBreakLoop("for (;a == 1;) {", loop_bodies_1, "}");
    3565           5 : }
    3566             : 
    3567             : 
    3568       26644 : TEST(DebugBreakInForCondition2) {
    3569           5 :   DebugBreakLoop("for (;a == 1;) {", loop_bodies_2, "}");
    3570           5 : }
    3571             : 
    3572          10 : class DebugBreakInlineListener : public v8::debug::DebugDelegate {
    3573             :  public:
    3574           5 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3575             :                              const std::vector<v8::debug::BreakpointId>&
    3576             :                                  inspector_break_points_hit) override {
    3577             :     int expected_frame_count = 4;
    3578           5 :     int expected_line_number[] = {1, 4, 7, 12};
    3579             : 
    3580             :     int frame_count = 0;
    3581           5 :     auto iterator = v8::debug::StackTraceIterator::Create(CcTest::isolate());
    3582          45 :     for (; !iterator->Done(); iterator->Advance(), ++frame_count) {
    3583          20 :       v8::debug::Location loc = iterator->GetSourceLocation();
    3584          20 :       CHECK_EQ(expected_line_number[frame_count], loc.GetLineNumber());
    3585             :     }
    3586           5 :     CHECK_EQ(frame_count, expected_frame_count);
    3587           5 :   }
    3588             : };
    3589             : 
    3590       26644 : TEST(DebugBreakInline) {
    3591           5 :   i::FLAG_allow_natives_syntax = true;
    3592           5 :   LocalContext env;
    3593          10 :   v8::HandleScope scope(env->GetIsolate());
    3594           5 :   v8::Local<v8::Context> context = env.local();
    3595             :   const char* source =
    3596             :       "function debug(b) {             \n"
    3597             :       "  if (b) debugger;              \n"
    3598             :       "}                               \n"
    3599             :       "function f(b) {                 \n"
    3600             :       "  debug(b)                      \n"
    3601             :       "};                              \n"
    3602             :       "function g(b) {                 \n"
    3603             :       "  f(b);                         \n"
    3604             :       "};                              \n"
    3605             :       "g(false);                       \n"
    3606             :       "g(false);                       \n"
    3607             :       "%OptimizeFunctionOnNextCall(g); \n"
    3608             :       "g(true);";
    3609           5 :   DebugBreakInlineListener delegate;
    3610           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3611             :   v8::Local<v8::Script> inline_script =
    3612           5 :       v8::Script::Compile(context, v8_str(env->GetIsolate(), source))
    3613             :           .ToLocalChecked();
    3614           5 :   inline_script->Run(context).ToLocalChecked();
    3615           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3616           5 : }
    3617             : 
    3618           5 : static void RunScriptInANewCFrame(const char* source) {
    3619          10 :   v8::TryCatch try_catch(CcTest::isolate());
    3620             :   CompileRun(source);
    3621           5 :   CHECK(try_catch.HasCaught());
    3622           5 : }
    3623             : 
    3624             : 
    3625       26644 : TEST(Regress131642) {
    3626             :   // Bug description:
    3627             :   // When doing StepNext through the first script, the debugger is not reset
    3628             :   // after exiting through exception.  A flawed implementation enabling the
    3629             :   // debugger to step into Array.prototype.forEach breaks inside the callback
    3630             :   // for forEach in the second script under the assumption that we are in a
    3631             :   // recursive call.  In an attempt to step out, we crawl the stack using the
    3632             :   // recorded frame pointer from the first script and fail when not finding it
    3633             :   // on the stack.
    3634           5 :   LocalContext env;
    3635          10 :   v8::HandleScope scope(env->GetIsolate());
    3636           5 :   DebugEventCounter delegate;
    3637             :   delegate.set_step_action(StepNext);
    3638           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3639             : 
    3640             :   // We step through the first script.  It exits through an exception.  We run
    3641             :   // this inside a new frame to record a different FP than the second script
    3642             :   // would expect.
    3643             :   const char* script_1 = "debugger; throw new Error();";
    3644           5 :   RunScriptInANewCFrame(script_1);
    3645             : 
    3646             :   // The second script uses forEach.
    3647             :   const char* script_2 = "[0].forEach(function() { });";
    3648             :   CompileRun(script_2);
    3649             : 
    3650           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    3651           5 : }
    3652             : 
    3653          10 : class DebugBreakStackTraceListener : public v8::debug::DebugDelegate {
    3654             :  public:
    3655           0 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3656             :                              const std::vector<v8::debug::BreakpointId>&
    3657             :                                  inspector_break_points_hit) override {
    3658           0 :     v8::StackTrace::CurrentStackTrace(CcTest::isolate(), 10);
    3659           0 :   }
    3660             : };
    3661             : 
    3662        5000 : static void AddDebugBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
    3663        5000 :   v8::debug::SetBreakOnNextFunctionCall(args.GetIsolate());
    3664        5000 : }
    3665             : 
    3666       26644 : TEST(DebugBreakStackTrace) {
    3667           5 :   LocalContext env;
    3668          10 :   v8::HandleScope scope(env->GetIsolate());
    3669           5 :   DebugBreakStackTraceListener delegate;
    3670           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3671           5 :   v8::Local<v8::Context> context = env.local();
    3672             :   v8::Local<v8::FunctionTemplate> add_debug_break_template =
    3673           5 :       v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
    3674             :   v8::Local<v8::Function> add_debug_break =
    3675           5 :       add_debug_break_template->GetFunction(context).ToLocalChecked();
    3676          20 :   CHECK(env->Global()
    3677             :             ->Set(context, v8_str("add_debug_break"), add_debug_break)
    3678             :             .FromJust());
    3679             : 
    3680             :   CompileRun("(function loop() {"
    3681             :              "  for (var j = 0; j < 1000; j++) {"
    3682             :              "    for (var i = 0; i < 1000; i++) {"
    3683             :              "      if (i == 999) add_debug_break();"
    3684             :              "    }"
    3685             :              "  }"
    3686             :              "})()");
    3687           5 : }
    3688             : 
    3689             : 
    3690       26639 : v8::base::Semaphore terminate_requested_semaphore(0);
    3691       26639 : v8::base::Semaphore terminate_fired_semaphore(0);
    3692             : 
    3693          10 : class DebugBreakTriggerTerminate : public v8::debug::DebugDelegate {
    3694             :  public:
    3695           5 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3696             :                              const std::vector<v8::debug::BreakpointId>&
    3697             :                                  inspector_break_points_hit) override {
    3698           5 :     if (terminate_already_fired_) return;
    3699           5 :     terminate_requested_semaphore.Signal();
    3700             :     // Wait for at most 2 seconds for the terminate request.
    3701           5 :     CHECK(
    3702             :         terminate_fired_semaphore.WaitFor(v8::base::TimeDelta::FromSeconds(2)));
    3703           5 :     terminate_already_fired_ = true;
    3704             :   }
    3705             : 
    3706             :  private:
    3707             :   bool terminate_already_fired_ = false;
    3708             : };
    3709             : 
    3710           5 : class TerminationThread : public v8::base::Thread {
    3711             :  public:
    3712             :   explicit TerminationThread(v8::Isolate* isolate)
    3713           5 :       : Thread(Options("terminator")), isolate_(isolate) {}
    3714             : 
    3715           5 :   void Run() override {
    3716           5 :     terminate_requested_semaphore.Wait();
    3717           5 :     isolate_->TerminateExecution();
    3718           5 :     terminate_fired_semaphore.Signal();
    3719           5 :   }
    3720             : 
    3721             :  private:
    3722             :   v8::Isolate* isolate_;
    3723             : };
    3724             : 
    3725             : 
    3726       26644 : TEST(DebugBreakOffThreadTerminate) {
    3727           5 :   LocalContext env;
    3728           5 :   v8::Isolate* isolate = env->GetIsolate();
    3729          10 :   v8::HandleScope scope(isolate);
    3730           5 :   DebugBreakTriggerTerminate delegate;
    3731           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3732             :   TerminationThread terminator(isolate);
    3733           5 :   terminator.Start();
    3734          10 :   v8::TryCatch try_catch(env->GetIsolate());
    3735           5 :   env->GetIsolate()->RequestInterrupt(BreakRightNow, nullptr);
    3736             :   CompileRun("while (true);");
    3737           5 :   CHECK(try_catch.HasTerminated());
    3738           5 : }
    3739             : 
    3740          50 : class ArchiveRestoreThread : public v8::base::Thread,
    3741             :                              public v8::debug::DebugDelegate {
    3742             :  public:
    3743             :   ArchiveRestoreThread(v8::Isolate* isolate, int spawn_count)
    3744             :       : Thread(Options("ArchiveRestoreThread")),
    3745             :         isolate_(isolate),
    3746             :         debug_(reinterpret_cast<i::Isolate*>(isolate_)->debug()),
    3747             :         spawn_count_(spawn_count),
    3748          50 :         break_count_(0) {}
    3749             : 
    3750          25 :   void Run() override {
    3751          50 :     v8::Locker locker(isolate_);
    3752          25 :     isolate_->Enter();
    3753             : 
    3754          50 :     v8::HandleScope scope(isolate_);
    3755          25 :     v8::Local<v8::Context> context = v8::Context::New(isolate_);
    3756             :     v8::Context::Scope context_scope(context);
    3757             : 
    3758             :     v8::Local<v8::Function> test = CompileFunction(isolate_,
    3759             :                                                    "function test(n) {\n"
    3760             :                                                    "  debugger;\n"
    3761             :                                                    "  return n + 1;\n"
    3762             :                                                    "}\n",
    3763          25 :                                                    "test");
    3764             : 
    3765          25 :     debug_->SetDebugDelegate(this);
    3766          25 :     v8::internal::DisableBreak enable_break(debug_, false);
    3767             : 
    3768          25 :     v8::Local<v8::Value> args[1] = {v8::Integer::New(isolate_, spawn_count_)};
    3769             : 
    3770          75 :     int result = test->Call(context, context->Global(), 1, args)
    3771             :                      .ToLocalChecked()
    3772          50 :                      ->Int32Value(context)
    3773             :                      .FromJust();
    3774             : 
    3775             :     // Verify that test(spawn_count_) returned spawn_count_ + 1.
    3776          25 :     CHECK_EQ(spawn_count_ + 1, result);
    3777             : 
    3778          25 :     isolate_->Exit();
    3779          25 :   }
    3780             : 
    3781          50 :   void BreakProgramRequested(
    3782             :       v8::Local<v8::Context> context,
    3783             :       const std::vector<v8::debug::BreakpointId>&) override {
    3784          50 :     auto stack_traces = v8::debug::StackTraceIterator::Create(isolate_);
    3785          50 :     if (!stack_traces->Done()) {
    3786          50 :       v8::debug::Location location = stack_traces->GetSourceLocation();
    3787             : 
    3788          50 :       i::PrintF("ArchiveRestoreThread #%d hit breakpoint at line %d\n",
    3789          50 :                 spawn_count_, location.GetLineNumber());
    3790             : 
    3791          50 :       switch (location.GetLineNumber()) {
    3792             :         case 1:  // debugger;
    3793          25 :           CHECK_EQ(break_count_, 0);
    3794             : 
    3795             :           // Attempt to stop on the next line after the first debugger
    3796             :           // statement. If debug->{Archive,Restore}Debug() improperly reset
    3797             :           // thread-local debug information, the debugger will fail to stop
    3798             :           // before the test function returns.
    3799          25 :           debug_->PrepareStep(StepNext);
    3800             : 
    3801             :           // Spawning threads while handling the current breakpoint verifies
    3802             :           // that the parent thread correctly archived and restored the
    3803             :           // state necessary to stop on the next line. If not, then control
    3804             :           // will simply continue past the `return n + 1` statement.
    3805          25 :           MaybeSpawnChildThread();
    3806             : 
    3807          25 :           break;
    3808             : 
    3809             :         case 2:  // return n + 1;
    3810          25 :           CHECK_EQ(break_count_, 1);
    3811             :           break;
    3812             : 
    3813             :         default:
    3814           0 :           CHECK(false);
    3815             :       }
    3816             :     }
    3817             : 
    3818          50 :     ++break_count_;
    3819          50 :   }
    3820             : 
    3821          25 :   void MaybeSpawnChildThread() {
    3822          25 :     if (spawn_count_ > 1) {
    3823          40 :       v8::Unlocker unlocker(isolate_);
    3824             : 
    3825             :       // Spawn a thread that spawns a thread that spawns a thread (and so
    3826             :       // on) so that the ThreadManager is forced to archive and restore
    3827             :       // the current thread.
    3828          20 :       ArchiveRestoreThread child(isolate_, spawn_count_ - 1);
    3829          20 :       child.Start();
    3830          20 :       child.Join();
    3831             : 
    3832             :       // The child thread sets itself as the debug delegate, so we need to
    3833             :       // usurp it after the child finishes, or else future breakpoints
    3834             :       // will be delegated to a destroyed ArchiveRestoreThread object.
    3835          20 :       debug_->SetDebugDelegate(this);
    3836             : 
    3837             :       // This is the most important check in this test, since
    3838             :       // child.GetBreakCount() will return 1 if the debugger fails to stop
    3839             :       // on the `return n + 1` line after the grandchild thread returns.
    3840          20 :       CHECK_EQ(child.GetBreakCount(), 2);
    3841             :     }
    3842          25 :   }
    3843             : 
    3844             :   int GetBreakCount() { return break_count_; }
    3845             : 
    3846             :  private:
    3847             :   v8::Isolate* isolate_;
    3848             :   v8::internal::Debug* debug_;
    3849             :   const int spawn_count_;
    3850             :   int break_count_;
    3851             : };
    3852             : 
    3853       26644 : TEST(DebugArchiveRestore) {
    3854             :   v8::Isolate::CreateParams create_params;
    3855           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3856           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    3857             : 
    3858             :   ArchiveRestoreThread thread(isolate, 5);
    3859             :   // Instead of calling thread.Start() and thread.Join() here, we call
    3860             :   // thread.Run() directly, to make sure we exercise archive/restore
    3861             :   // logic on the *current* thread as well as other threads.
    3862           5 :   thread.Run();
    3863           5 :   CHECK_EQ(thread.GetBreakCount(), 2);
    3864             : 
    3865           5 :   isolate->Dispose();
    3866           5 : }
    3867             : 
    3868          10 : class DebugEventExpectNoException : public v8::debug::DebugDelegate {
    3869             :  public:
    3870           0 :   void ExceptionThrown(v8::Local<v8::Context> paused_context,
    3871             :                        v8::Local<v8::Value> exception,
    3872             :                        v8::Local<v8::Value> promise, bool is_uncaught,
    3873             :                        v8::debug::ExceptionType) override {
    3874           0 :     CHECK(false);
    3875             :   }
    3876             : };
    3877             : 
    3878           5 : static void TryCatchWrappedThrowCallback(
    3879             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    3880          10 :   v8::TryCatch try_catch(args.GetIsolate());
    3881             :   CompileRun("throw 'rejection';");
    3882           5 :   CHECK(try_catch.HasCaught());
    3883           5 : }
    3884             : 
    3885       26644 : TEST(DebugPromiseInterceptedByTryCatch) {
    3886           5 :   LocalContext env;
    3887           5 :   v8::Isolate* isolate = env->GetIsolate();
    3888          10 :   v8::HandleScope scope(isolate);
    3889           5 :   DebugEventExpectNoException delegate;
    3890           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    3891           5 :   v8::Local<v8::Context> context = env.local();
    3892           5 :   ChangeBreakOnException(false, true);
    3893             : 
    3894             :   v8::Local<v8::FunctionTemplate> fun =
    3895           5 :       v8::FunctionTemplate::New(isolate, TryCatchWrappedThrowCallback);
    3896          25 :   CHECK(env->Global()
    3897             :             ->Set(context, v8_str("fun"),
    3898             :                   fun->GetFunction(context).ToLocalChecked())
    3899             :             .FromJust());
    3900             : 
    3901             :   CompileRun("var p = new Promise(function(res, rej) { fun(); res(); });");
    3902             :   CompileRun(
    3903             :       "var r;"
    3904             :       "p.then(function() { r = 'resolved'; },"
    3905             :       "       function() { r = 'rejected'; });");
    3906          15 :   CHECK(CompileRun("r")->Equals(context, v8_str("resolved")).FromJust());
    3907           5 : }
    3908             : 
    3909          10 : class NoInterruptsOnDebugEvent : public v8::debug::DebugDelegate {
    3910             :  public:
    3911           5 :   void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
    3912             :                       bool has_compile_error) override {
    3913           5 :     ++after_compile_handler_depth_;
    3914             :     // Do not allow nested AfterCompile events.
    3915           5 :     CHECK_LE(after_compile_handler_depth_, 1);
    3916           5 :     v8::Isolate* isolate = CcTest::isolate();
    3917          10 :     v8::Isolate::AllowJavascriptExecutionScope allow_script(isolate);
    3918           5 :     isolate->RequestInterrupt(&HandleInterrupt, this);
    3919             :     CompileRun("function foo() {}; foo();");
    3920           5 :     --after_compile_handler_depth_;
    3921           5 :   }
    3922             : 
    3923             :  private:
    3924           5 :   static void HandleInterrupt(v8::Isolate* isolate, void* data) {
    3925             :     NoInterruptsOnDebugEvent* d = static_cast<NoInterruptsOnDebugEvent*>(data);
    3926           5 :     CHECK_EQ(0, d->after_compile_handler_depth_);
    3927           5 :   }
    3928             : 
    3929             :   int after_compile_handler_depth_ = 0;
    3930             : };
    3931             : 
    3932       26644 : TEST(NoInterruptsInDebugListener) {
    3933           5 :   LocalContext env;
    3934          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    3935           5 :   NoInterruptsOnDebugEvent delegate;
    3936           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    3937             :   CompileRun("void(0);");
    3938           5 : }
    3939             : 
    3940       26644 : TEST(BreakLocationIterator) {
    3941           5 :   LocalContext env;
    3942           5 :   v8::Isolate* isolate = env->GetIsolate();
    3943             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    3944          10 :   v8::HandleScope scope(isolate);
    3945             : 
    3946             :   v8::Local<v8::Value> result = CompileRun(
    3947             :       "function f() {\n"
    3948             :       "  debugger;   \n"
    3949             :       "  f();        \n"
    3950             :       "  debugger;   \n"
    3951             :       "}             \n"
    3952             :       "f");
    3953             :   Handle<i::Object> function_obj = v8::Utils::OpenHandle(*result);
    3954             :   Handle<i::JSFunction> function = Handle<i::JSFunction>::cast(function_obj);
    3955             :   Handle<i::SharedFunctionInfo> shared(function->shared(), i_isolate);
    3956             : 
    3957             :   EnableDebugger(isolate);
    3958           5 :   CHECK(i_isolate->debug()->EnsureBreakInfo(shared));
    3959           5 :   i_isolate->debug()->PrepareFunctionForDebugExecution(shared);
    3960             : 
    3961             :   Handle<i::DebugInfo> debug_info(shared->GetDebugInfo(), i_isolate);
    3962             : 
    3963             :   {
    3964           5 :     i::BreakIterator iterator(debug_info);
    3965           5 :     CHECK(iterator.GetBreakLocation().IsDebuggerStatement());
    3966           5 :     CHECK_EQ(17, iterator.GetBreakLocation().position());
    3967           5 :     iterator.Next();
    3968          10 :     CHECK(iterator.GetBreakLocation().IsDebugBreakSlot());
    3969           5 :     CHECK_EQ(32, iterator.GetBreakLocation().position());
    3970           5 :     iterator.Next();
    3971           5 :     CHECK(iterator.GetBreakLocation().IsCall());
    3972           5 :     CHECK_EQ(32, iterator.GetBreakLocation().position());
    3973           5 :     iterator.Next();
    3974           5 :     CHECK(iterator.GetBreakLocation().IsDebuggerStatement());
    3975           5 :     CHECK_EQ(47, iterator.GetBreakLocation().position());
    3976           5 :     iterator.Next();
    3977           5 :     CHECK(iterator.GetBreakLocation().IsReturn());
    3978           5 :     CHECK_EQ(60, iterator.GetBreakLocation().position());
    3979           5 :     iterator.Next();
    3980           5 :     CHECK(iterator.Done());
    3981             :   }
    3982             : 
    3983             :   DisableDebugger(isolate);
    3984           5 : }
    3985             : 
    3986          10 : class DebugStepOverFunctionWithCaughtExceptionListener
    3987             :     : public v8::debug::DebugDelegate {
    3988             :  public:
    3989          15 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    3990             :                              const std::vector<v8::debug::BreakpointId>&
    3991             :                                  inspector_break_points_hit) override {
    3992          15 :     ++break_point_hit_count;
    3993          15 :     if (break_point_hit_count >= 3) return;
    3994             :     PrepareStep(StepNext);
    3995             :   }
    3996             :   int break_point_hit_count = 0;
    3997             : };
    3998             : 
    3999       26644 : TEST(DebugStepOverFunctionWithCaughtException) {
    4000           5 :   i::FLAG_allow_natives_syntax = true;
    4001             : 
    4002           5 :   LocalContext env;
    4003           5 :   v8::Isolate* isolate = env->GetIsolate();
    4004          10 :   v8::HandleScope scope(isolate);
    4005           5 :   DebugStepOverFunctionWithCaughtExceptionListener delegate;
    4006           5 :   v8::debug::SetDebugDelegate(isolate, &delegate);
    4007             : 
    4008             :   CompileRun(
    4009             :       "function foo() {\n"
    4010             :       "  try { throw new Error(); } catch (e) {}\n"
    4011             :       "}\n"
    4012             :       "debugger;\n"
    4013             :       "foo();\n"
    4014             :       "foo();\n");
    4015             : 
    4016           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    4017           5 :   CHECK_EQ(3, delegate.break_point_hit_count);
    4018           5 : }
    4019             : 
    4020             : bool near_heap_limit_callback_called = false;
    4021           5 : size_t NearHeapLimitCallback(void* data, size_t current_heap_limit,
    4022             :                              size_t initial_heap_limit) {
    4023           5 :   near_heap_limit_callback_called = true;
    4024           5 :   return initial_heap_limit + 10u * i::MB;
    4025             : }
    4026             : 
    4027       26644 : UNINITIALIZED_TEST(DebugSetOutOfMemoryListener) {
    4028             :   v8::Isolate::CreateParams create_params;
    4029           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    4030             :   create_params.constraints.set_max_old_space_size(10);
    4031           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    4032             :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    4033             :   {
    4034             :     v8::Isolate::Scope i_scope(isolate);
    4035          10 :     v8::HandleScope scope(isolate);
    4036           5 :     LocalContext context(isolate);
    4037           5 :     isolate->AddNearHeapLimitCallback(NearHeapLimitCallback, nullptr);
    4038           5 :     CHECK(!near_heap_limit_callback_called);
    4039             :     // The following allocation fails unless the out-of-memory callback
    4040             :     // increases the heap limit.
    4041             :     int length = 10 * i::MB / i::kTaggedSize;
    4042           5 :     i_isolate->factory()->NewFixedArray(length, i::AllocationType::kOld);
    4043           5 :     CHECK(near_heap_limit_callback_called);
    4044           5 :     isolate->RemoveNearHeapLimitCallback(NearHeapLimitCallback, 0);
    4045             :   }
    4046           5 :   isolate->Dispose();
    4047           5 : }
    4048             : 
    4049       26644 : TEST(DebugCoverage) {
    4050             :   // Coverage needs feedback vectors.
    4051             :   if (i::FLAG_lite_mode) return;
    4052           5 :   i::FLAG_always_opt = false;
    4053           5 :   LocalContext env;
    4054           5 :   v8::Isolate* isolate = env->GetIsolate();
    4055          10 :   v8::HandleScope scope(isolate);
    4056             :   v8::debug::Coverage::SelectMode(isolate,
    4057           5 :                                   v8::debug::CoverageMode::kPreciseCount);
    4058             :   v8::Local<v8::String> source = v8_str(
    4059             :       "function f() {\n"
    4060             :       "}\n"
    4061             :       "f();\n"
    4062           5 :       "f();");
    4063           5 :   CompileRun(source);
    4064           5 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(isolate);
    4065           5 :   CHECK_EQ(1u, coverage.ScriptCount());
    4066           5 :   v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(0);
    4067           5 :   v8::Local<v8::debug::Script> script = script_data.GetScript();
    4068          15 :   CHECK(script->Source()
    4069             :             .ToLocalChecked()
    4070             :             ->Equals(env.local(), source)
    4071             :             .FromMaybe(false));
    4072             : 
    4073           5 :   CHECK_EQ(2u, script_data.FunctionCount());
    4074             :   v8::debug::Coverage::FunctionData function_data =
    4075           5 :       script_data.GetFunctionData(0);
    4076             :   v8::debug::Location start =
    4077           5 :       script->GetSourceLocation(function_data.StartOffset());
    4078             :   v8::debug::Location end =
    4079           5 :       script->GetSourceLocation(function_data.EndOffset());
    4080           5 :   CHECK_EQ(0, start.GetLineNumber());
    4081           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4082           5 :   CHECK_EQ(3, end.GetLineNumber());
    4083           5 :   CHECK_EQ(4, end.GetColumnNumber());
    4084           5 :   CHECK_EQ(1, function_data.Count());
    4085             : 
    4086          10 :   function_data = script_data.GetFunctionData(1);
    4087           5 :   start = script->GetSourceLocation(function_data.StartOffset());
    4088           5 :   end = script->GetSourceLocation(function_data.EndOffset());
    4089           5 :   CHECK_EQ(0, start.GetLineNumber());
    4090           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4091           5 :   CHECK_EQ(1, end.GetLineNumber());
    4092           5 :   CHECK_EQ(1, end.GetColumnNumber());
    4093           5 :   CHECK_EQ(2, function_data.Count());
    4094             : }
    4095             : 
    4096             : namespace {
    4097           5 : v8::debug::Coverage::ScriptData GetScriptDataAndDeleteCoverage(
    4098             :     v8::Isolate* isolate) {
    4099           5 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(isolate);
    4100           5 :   CHECK_EQ(1u, coverage.ScriptCount());
    4101          10 :   return coverage.GetScriptData(0);
    4102             : }
    4103             : }  // namespace
    4104             : 
    4105       26644 : TEST(DebugCoverageWithCoverageOutOfScope) {
    4106             :   // Coverage needs feedback vectors.
    4107             :   if (i::FLAG_lite_mode) return;
    4108           5 :   i::FLAG_always_opt = false;
    4109           5 :   LocalContext env;
    4110           5 :   v8::Isolate* isolate = env->GetIsolate();
    4111          10 :   v8::HandleScope scope(isolate);
    4112             :   v8::debug::Coverage::SelectMode(isolate,
    4113           5 :                                   v8::debug::CoverageMode::kPreciseCount);
    4114             :   v8::Local<v8::String> source = v8_str(
    4115             :       "function f() {\n"
    4116             :       "}\n"
    4117             :       "f();\n"
    4118           5 :       "f();");
    4119           5 :   CompileRun(source);
    4120             :   v8::debug::Coverage::ScriptData script_data =
    4121           5 :       GetScriptDataAndDeleteCoverage(isolate);
    4122           5 :   v8::Local<v8::debug::Script> script = script_data.GetScript();
    4123          15 :   CHECK(script->Source()
    4124             :             .ToLocalChecked()
    4125             :             ->Equals(env.local(), source)
    4126             :             .FromMaybe(false));
    4127             : 
    4128           5 :   CHECK_EQ(2u, script_data.FunctionCount());
    4129             :   v8::debug::Coverage::FunctionData function_data =
    4130           5 :       script_data.GetFunctionData(0);
    4131             : 
    4132           5 :   CHECK_EQ(0, function_data.StartOffset());
    4133           5 :   CHECK_EQ(26, function_data.EndOffset());
    4134             : 
    4135             :   v8::debug::Location start =
    4136           5 :       script->GetSourceLocation(function_data.StartOffset());
    4137             :   v8::debug::Location end =
    4138           5 :       script->GetSourceLocation(function_data.EndOffset());
    4139           5 :   CHECK_EQ(0, start.GetLineNumber());
    4140           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4141           5 :   CHECK_EQ(3, end.GetLineNumber());
    4142           5 :   CHECK_EQ(4, end.GetColumnNumber());
    4143           5 :   CHECK_EQ(1, function_data.Count());
    4144             : 
    4145          10 :   function_data = script_data.GetFunctionData(1);
    4146           5 :   start = script->GetSourceLocation(function_data.StartOffset());
    4147           5 :   end = script->GetSourceLocation(function_data.EndOffset());
    4148             : 
    4149           5 :   CHECK_EQ(0, function_data.StartOffset());
    4150           5 :   CHECK_EQ(16, function_data.EndOffset());
    4151             : 
    4152           5 :   CHECK_EQ(0, start.GetLineNumber());
    4153           5 :   CHECK_EQ(0, start.GetColumnNumber());
    4154           5 :   CHECK_EQ(1, end.GetLineNumber());
    4155           5 :   CHECK_EQ(1, end.GetColumnNumber());
    4156           5 :   CHECK_EQ(2, function_data.Count());
    4157             : }
    4158             : 
    4159             : namespace {
    4160           5 : v8::debug::Coverage::FunctionData GetFunctionDataAndDeleteCoverage(
    4161             :     v8::Isolate* isolate) {
    4162           5 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(isolate);
    4163           5 :   CHECK_EQ(1u, coverage.ScriptCount());
    4164             : 
    4165           5 :   v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(0);
    4166             : 
    4167           5 :   CHECK_EQ(2u, script_data.FunctionCount());
    4168             :   v8::debug::Coverage::FunctionData function_data =
    4169           5 :       script_data.GetFunctionData(0);
    4170           5 :   CHECK_EQ(1, function_data.Count());
    4171           5 :   CHECK_EQ(0, function_data.StartOffset());
    4172           5 :   CHECK_EQ(26, function_data.EndOffset());
    4173           5 :   return function_data;
    4174             : }
    4175             : }  // namespace
    4176             : 
    4177       26644 : TEST(DebugCoverageWithScriptDataOutOfScope) {
    4178             :   // Coverage needs feedback vectors.
    4179             :   if (i::FLAG_lite_mode) return;
    4180           5 :   i::FLAG_always_opt = false;
    4181           5 :   LocalContext env;
    4182           5 :   v8::Isolate* isolate = env->GetIsolate();
    4183          10 :   v8::HandleScope scope(isolate);
    4184             :   v8::debug::Coverage::SelectMode(isolate,
    4185           5 :                                   v8::debug::CoverageMode::kPreciseCount);
    4186             :   v8::Local<v8::String> source = v8_str(
    4187             :       "function f() {\n"
    4188             :       "}\n"
    4189             :       "f();\n"
    4190           5 :       "f();");
    4191           5 :   CompileRun(source);
    4192             : 
    4193             :   v8::debug::Coverage::FunctionData function_data =
    4194           5 :       GetFunctionDataAndDeleteCoverage(isolate);
    4195           5 :   CHECK_EQ(1, function_data.Count());
    4196           5 :   CHECK_EQ(0, function_data.StartOffset());
    4197           5 :   CHECK_EQ(26, function_data.EndOffset());
    4198             : }
    4199             : 
    4200       26644 : TEST(BuiltinsExceptionPrediction) {
    4201           5 :   v8::Isolate* isolate = CcTest::isolate();
    4202             :   i::Isolate* iisolate = CcTest::i_isolate();
    4203          10 :   v8::HandleScope handle_scope(isolate);
    4204           5 :   v8::Context::New(isolate);
    4205             : 
    4206             :   i::Builtins* builtins = iisolate->builtins();
    4207             :   bool fail = false;
    4208       15215 :   for (int i = 0; i < i::Builtins::builtin_count; i++) {
    4209        7605 :     i::Code builtin = builtins->builtin(i);
    4210        9975 :     if (builtin->kind() != i::Code::BUILTIN) continue;
    4211        5235 :     auto prediction = builtin->GetBuiltinCatchPrediction();
    4212             :     USE(prediction);
    4213             :   }
    4214             :   CHECK(!fail);
    4215           5 : }
    4216             : 
    4217       26644 : TEST(DebugGetPossibleBreakpointsReturnLocations) {
    4218           5 :   LocalContext env;
    4219           5 :   v8::Isolate* isolate = env->GetIsolate();
    4220          10 :   v8::HandleScope scope(isolate);
    4221             :   v8::Local<v8::String> source = v8_str(
    4222             :       "function fib(x) {\n"
    4223             :       "  if (x < 0) return;\n"
    4224             :       "  if (x === 0) return 1;\n"
    4225             :       "  if (x === 1) return fib(0);\n"
    4226             :       "  return x > 2 ? fib(x - 1) + fib(x - 2) : fib(1) + fib(0);\n"
    4227           5 :       "}");
    4228           5 :   CompileRun(source);
    4229           5 :   v8::PersistentValueVector<v8::debug::Script> scripts(isolate);
    4230           5 :   v8::debug::GetLoadedScripts(isolate, scripts);
    4231           5 :   CHECK_EQ(scripts.Size(), 1);
    4232             :   std::vector<v8::debug::BreakLocation> locations;
    4233          10 :   CHECK(scripts.Get(0)->GetPossibleBreakpoints(
    4234             :       v8::debug::Location(0, 17), v8::debug::Location(), true, &locations));
    4235             :   int returns_count = 0;
    4236         165 :   for (size_t i = 0; i < locations.size(); ++i) {
    4237          80 :     if (locations[i].type() == v8::debug::kReturnBreakLocation) {
    4238          20 :       ++returns_count;
    4239             :     }
    4240             :   }
    4241             :   // With Ignition we generate one return location per return statement,
    4242             :   // each has line = 5, column = 0 as statement position.
    4243           5 :   CHECK_EQ(returns_count, 4);
    4244           5 : }
    4245             : 
    4246       26644 : TEST(DebugEvaluateNoSideEffect) {
    4247           5 :   LocalContext env;
    4248          10 :   v8::HandleScope scope(env->GetIsolate());
    4249           5 :   EnableDebugger(env->GetIsolate());
    4250           5 :   i::Isolate* isolate = CcTest::i_isolate();
    4251             :   std::vector<i::Handle<i::JSFunction>> all_functions;
    4252             :   {
    4253          10 :     i::HeapIterator iterator(isolate->heap());
    4254       35217 :     for (i::HeapObject obj = iterator.next(); !obj.is_null();
    4255             :          obj = iterator.next()) {
    4256       67216 :       if (!obj->IsJSFunction()) continue;
    4257        3208 :       i::JSFunction fun = i::JSFunction::cast(obj);
    4258        3208 :       all_functions.emplace_back(fun, isolate);
    4259             :     }
    4260             :   }
    4261             : 
    4262             :   // Perform side effect check on all built-in functions. The side effect check
    4263             :   // itself contains additional sanity checks.
    4264        3213 :   for (i::Handle<i::JSFunction> fun : all_functions) {
    4265             :     bool failed = false;
    4266        3208 :     isolate->debug()->StartSideEffectCheckMode();
    4267        3208 :     failed = !isolate->debug()->PerformSideEffectCheck(
    4268        6416 :         fun, v8::Utils::OpenHandle(*env->Global()));
    4269        3208 :     isolate->debug()->StopSideEffectCheckMode();
    4270        3208 :     if (failed) isolate->clear_pending_exception();
    4271             :   }
    4272           5 :   DisableDebugger(env->GetIsolate());
    4273           5 : }
    4274             : 
    4275             : namespace {
    4276          10 : i::MaybeHandle<i::Script> FindScript(
    4277             :     i::Isolate* isolate, const std::vector<i::Handle<i::Script>>& scripts,
    4278             :     const char* name) {
    4279             :   Handle<i::String> i_name =
    4280          10 :       isolate->factory()->NewStringFromAsciiChecked(name);
    4281          25 :   for (const auto& script : scripts) {
    4282          25 :     if (!script->name()->IsString()) continue;
    4283          25 :     if (i_name->Equals(i::String::cast(script->name()))) return script;
    4284             :   }
    4285           0 :   return i::MaybeHandle<i::Script>();
    4286             : }
    4287             : }  // anonymous namespace
    4288             : 
    4289       26644 : UNINITIALIZED_TEST(LoadedAtStartupScripts) {
    4290           5 :   i::FLAG_expose_gc = true;
    4291             : 
    4292             :   v8::Isolate::CreateParams create_params;
    4293           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    4294           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    4295           5 :   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
    4296             :   {
    4297             :     v8::Isolate::Scope i_scope(isolate);
    4298          10 :     v8::HandleScope scope(isolate);
    4299           5 :     LocalContext context(isolate);
    4300             : 
    4301             :     std::vector<i::Handle<i::Script>> scripts;
    4302             :     CompileWithOrigin(v8_str("function foo(){}"), v8_str("normal.js"),
    4303           5 :                       v8_bool(false));
    4304             :     std::unordered_map<int, int> count_by_type;
    4305             :     {
    4306             :       i::DisallowHeapAllocation no_gc;
    4307           5 :       i::Script::Iterator iterator(i_isolate);
    4308          60 :       for (i::Script script = iterator.Next(); !script.is_null();
    4309             :            script = iterator.Next()) {
    4310          35 :         if (script->type() == i::Script::TYPE_NATIVE &&
    4311          10 :             script->name()->IsUndefined(i_isolate)) {
    4312             :           continue;
    4313             :         }
    4314          30 :         ++count_by_type[script->type()];
    4315          15 :         scripts.emplace_back(script, i_isolate);
    4316             :       }
    4317             :     }
    4318          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_NATIVE], 0);
    4319          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_EXTENSION], 2);
    4320          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_NORMAL], 1);
    4321          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_WASM], 0);
    4322          10 :     CHECK_EQ(count_by_type[i::Script::TYPE_INSPECTOR], 0);
    4323             : 
    4324             :     i::Handle<i::Script> gc_script =
    4325          10 :         FindScript(i_isolate, scripts, "v8/gc").ToHandleChecked();
    4326           5 :     CHECK_EQ(gc_script->type(), i::Script::TYPE_EXTENSION);
    4327             : 
    4328             :     i::Handle<i::Script> normal_script =
    4329          10 :         FindScript(i_isolate, scripts, "normal.js").ToHandleChecked();
    4330           5 :     CHECK_EQ(normal_script->type(), i::Script::TYPE_NORMAL);
    4331             :   }
    4332           5 :   isolate->Dispose();
    4333           5 : }
    4334             : 
    4335       26644 : TEST(SourceInfo) {
    4336           5 :   LocalContext env;
    4337          10 :   v8::HandleScope scope(env->GetIsolate());
    4338             :   const char* source =
    4339             :       "//\n"
    4340             :       "function a() { b(); };\n"
    4341             :       "function    b() {\n"
    4342             :       "  c(true);\n"
    4343             :       "};\n"
    4344             :       "  function c(x) {\n"
    4345             :       "    if (x) {\n"
    4346             :       "      return 1;\n"
    4347             :       "    } else {\n"
    4348             :       "      return 1;\n"
    4349             :       "    }\n"
    4350             :       "  };\n"
    4351             :       "function d(x) {\n"
    4352             :       "  x = 1 ;\n"
    4353             :       "  x = 2 ;\n"
    4354             :       "  x = 3 ;\n"
    4355             :       "  x = 4 ;\n"
    4356             :       "  x = 5 ;\n"
    4357             :       "  x = 6 ;\n"
    4358             :       "  x = 7 ;\n"
    4359             :       "  x = 8 ;\n"
    4360             :       "  x = 9 ;\n"
    4361             :       "  x = 10;\n"
    4362             :       "  x = 11;\n"
    4363             :       "  x = 12;\n"
    4364             :       "  x = 13;\n"
    4365             :       "  x = 14;\n"
    4366             :       "  x = 15;\n"
    4367             :       "}\n";
    4368             :   v8::Local<v8::Script> v8_script =
    4369          10 :       v8::Script::Compile(env.local(), v8_str(source)).ToLocalChecked();
    4370             :   i::Handle<i::Script> i_script(
    4371          10 :       i::Script::cast(v8::Utils::OpenHandle(*v8_script)->shared()->script()),
    4372           5 :       CcTest::i_isolate());
    4373             :   v8::Local<v8::debug::Script> script =
    4374             :       v8::ToApiHandle<v8::debug::Script>(i_script);
    4375             : 
    4376             :   // Test that when running through source positions the position, line and
    4377             :   // column progresses as expected.
    4378           5 :   v8::debug::Location prev_location = script->GetSourceLocation(0);
    4379           5 :   CHECK_EQ(prev_location.GetLineNumber(), 0);
    4380           5 :   CHECK_EQ(prev_location.GetColumnNumber(), 0);
    4381         995 :   for (int offset = 1; offset < 100; ++offset) {
    4382         495 :     v8::debug::Location location = script->GetSourceLocation(offset);
    4383         495 :     if (prev_location.GetLineNumber() == location.GetLineNumber()) {
    4384         460 :       CHECK_EQ(location.GetColumnNumber(), prev_location.GetColumnNumber() + 1);
    4385             :     } else {
    4386          35 :       CHECK_EQ(location.GetLineNumber(), prev_location.GetLineNumber() + 1);
    4387          35 :       CHECK_EQ(location.GetColumnNumber(), 0);
    4388             :     }
    4389         495 :     prev_location = location;
    4390             :   }
    4391             : 
    4392             :   // Every line of d() is the same length.  Verify we can loop through all
    4393             :   // positions and find the right line # for each.
    4394             :   // The position of the first line of d(), i.e. "x = 1 ;".
    4395             :   const int start_line_d = 13;
    4396             :   const int start_code_d =
    4397             :       static_cast<int>(strstr(source, "  x = 1 ;") - source);
    4398             :   const int num_lines_d = 15;
    4399             :   const int line_length_d = 10;
    4400             :   int p = start_code_d;
    4401         155 :   for (int line = 0; line < num_lines_d; ++line) {
    4402        1575 :     for (int column = 0; column < line_length_d; ++column) {
    4403         750 :       v8::debug::Location location = script->GetSourceLocation(p);
    4404         750 :       CHECK_EQ(location.GetLineNumber(), start_line_d + line);
    4405         750 :       CHECK_EQ(location.GetColumnNumber(), column);
    4406         750 :       ++p;
    4407             :     }
    4408             :   }
    4409             : 
    4410             :   // Test first positon.
    4411           5 :   CHECK_EQ(script->GetSourceLocation(0).GetLineNumber(), 0);
    4412           5 :   CHECK_EQ(script->GetSourceLocation(0).GetColumnNumber(), 0);
    4413             : 
    4414             :   // Test second positon.
    4415           5 :   CHECK_EQ(script->GetSourceLocation(1).GetLineNumber(), 0);
    4416           5 :   CHECK_EQ(script->GetSourceLocation(1).GetColumnNumber(), 1);
    4417             : 
    4418             :   // Test first positin in function a().
    4419             :   const int start_a =
    4420             :       static_cast<int>(strstr(source, "function a") - source) + 10;
    4421           5 :   CHECK_EQ(script->GetSourceLocation(start_a).GetLineNumber(), 1);
    4422           5 :   CHECK_EQ(script->GetSourceLocation(start_a).GetColumnNumber(), 10);
    4423             : 
    4424             :   // Test first positin in function b().
    4425             :   const int start_b =
    4426             :       static_cast<int>(strstr(source, "function    b") - source) + 13;
    4427           5 :   CHECK_EQ(script->GetSourceLocation(start_b).GetLineNumber(), 2);
    4428           5 :   CHECK_EQ(script->GetSourceLocation(start_b).GetColumnNumber(), 13);
    4429             : 
    4430             :   // Test first positin in function c().
    4431             :   const int start_c =
    4432             :       static_cast<int>(strstr(source, "function c") - source) + 10;
    4433           5 :   CHECK_EQ(script->GetSourceLocation(start_c).GetLineNumber(), 5);
    4434           5 :   CHECK_EQ(script->GetSourceLocation(start_c).GetColumnNumber(), 12);
    4435             : 
    4436             :   // Test first positin in function d().
    4437             :   const int start_d =
    4438             :       static_cast<int>(strstr(source, "function d") - source) + 10;
    4439           5 :   CHECK_EQ(script->GetSourceLocation(start_d).GetLineNumber(), 12);
    4440           5 :   CHECK_EQ(script->GetSourceLocation(start_d).GetColumnNumber(), 10);
    4441             : 
    4442             :   // Test offsets.
    4443           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(1, 10)), start_a);
    4444           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(2, 13)), start_b);
    4445           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(3, 0)), start_b + 5);
    4446           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(3, 2)), start_b + 7);
    4447           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(4, 0)), start_b + 16);
    4448           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(5, 12)), start_c);
    4449           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(6, 0)), start_c + 6);
    4450           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(7, 0)), start_c + 19);
    4451           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(8, 0)), start_c + 35);
    4452           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(9, 0)), start_c + 48);
    4453           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(10, 0)), start_c + 64);
    4454           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(11, 0)), start_c + 70);
    4455           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(12, 10)), start_d);
    4456           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(13, 0)), start_d + 6);
    4457         155 :   for (int i = 1; i <= num_lines_d; ++i) {
    4458          75 :     CHECK_EQ(script->GetSourceOffset(v8::debug::Location(start_line_d + i, 0)),
    4459             :              6 + (i * line_length_d) + start_d);
    4460             :   }
    4461           5 :   CHECK_EQ(script->GetSourceOffset(v8::debug::Location(start_line_d + 17, 0)),
    4462             :            start_d + 158);
    4463             : 
    4464             :   // Make sure invalid inputs work properly.
    4465             :   const int last_position = static_cast<int>(strlen(source)) - 1;
    4466           5 :   CHECK_EQ(script->GetSourceLocation(-1).GetLineNumber(), 0);
    4467           5 :   CHECK_EQ(script->GetSourceLocation(last_position + 2).GetLineNumber(),
    4468             :            i::kNoSourcePosition);
    4469             : 
    4470             :   // Test last position.
    4471           5 :   CHECK_EQ(script->GetSourceLocation(last_position).GetLineNumber(), 28);
    4472           5 :   CHECK_EQ(script->GetSourceLocation(last_position).GetColumnNumber(), 1);
    4473           5 :   CHECK_EQ(script->GetSourceLocation(last_position + 1).GetLineNumber(), 29);
    4474           5 :   CHECK_EQ(script->GetSourceLocation(last_position + 1).GetColumnNumber(), 0);
    4475           5 : }
    4476             : 
    4477             : namespace {
    4478          15 : class SetBreakpointOnScriptCompiled : public v8::debug::DebugDelegate {
    4479             :  public:
    4480          15 :   void ScriptCompiled(v8::Local<v8::debug::Script> script, bool is_live_edited,
    4481             :                       bool has_compile_error) override {
    4482             :     v8::Local<v8::String> name;
    4483          40 :     if (!script->SourceURL().ToLocal(&name)) return;
    4484           5 :     v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
    4485          15 :     if (!name->Equals(context, v8_str("test")).FromJust()) return;
    4486           5 :     CHECK(!has_compile_error);
    4487           5 :     v8::debug::Location loc(1, 2);
    4488           5 :     CHECK(script->SetBreakpoint(v8_str(""), &loc, &id_));
    4489           5 :     CHECK_EQ(loc.GetLineNumber(), 1);
    4490           5 :     CHECK_EQ(loc.GetColumnNumber(), 10);
    4491             :   }
    4492             : 
    4493           5 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    4494             :                              const std::vector<v8::debug::BreakpointId>&
    4495             :                                  inspector_break_points_hit) override {
    4496           5 :     ++break_count_;
    4497           5 :     CHECK_EQ(inspector_break_points_hit[0], id_);
    4498           5 :   }
    4499             : 
    4500             :   int break_count() const { return break_count_; }
    4501             : 
    4502             :  private:
    4503             :   int break_count_ = 0;
    4504             :   v8::debug::BreakpointId id_;
    4505             : };
    4506             : }  // anonymous namespace
    4507             : 
    4508       26644 : TEST(Regress517592) {
    4509           5 :   LocalContext env;
    4510          10 :   v8::HandleScope handle_scope(env->GetIsolate());
    4511             :   SetBreakpointOnScriptCompiled delegate;
    4512           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), &delegate);
    4513             :   CompileRun(
    4514             :       v8_str("eval('var foo = function foo() {\\n' +\n"
    4515             :              "'  var a = 1;\\n' +\n"
    4516             :              "'}\\n' +\n"
    4517           5 :              "'//@ sourceURL=test')"));
    4518           5 :   CHECK_EQ(delegate.break_count(), 0);
    4519           5 :   CompileRun(v8_str("foo()"));
    4520           5 :   CHECK_EQ(delegate.break_count(), 1);
    4521           5 :   v8::debug::SetDebugDelegate(env->GetIsolate(), nullptr);
    4522           5 : }
    4523             : 
    4524       26644 : TEST(GetPrivateFields) {
    4525           5 :   LocalContext env;
    4526           5 :   v8::Isolate* v8_isolate = CcTest::isolate();
    4527             :   v8::internal::Isolate* isolate = CcTest::i_isolate();
    4528          10 :   v8::HandleScope scope(v8_isolate);
    4529           5 :   v8::Local<v8::Context> context = env.local();
    4530           5 :   v8::internal::FLAG_harmony_class_fields = true;
    4531           5 :   v8::internal::FLAG_harmony_private_fields = true;
    4532             :   v8::Local<v8::String> source = v8_str(
    4533             :       "var X = class {\n"
    4534             :       "  #foo = 1;\n"
    4535             :       "  #bar = function() {};\n"
    4536             :       "}\n"
    4537           5 :       "var x = new X()");
    4538           5 :   CompileRun(source);
    4539             :   v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(
    4540          10 :       env->Global()
    4541          15 :           ->Get(context, v8_str(env->GetIsolate(), "x"))
    4542           5 :           .ToLocalChecked());
    4543             :   v8::Local<v8::Array> private_names =
    4544           5 :       v8::debug::GetPrivateFields(context, object).ToLocalChecked();
    4545             : 
    4546          25 :   for (int i = 0; i < 4; i = i + 2) {
    4547             :     Handle<v8::internal::JSReceiver> private_name =
    4548          10 :         v8::Utils::OpenHandle(*private_names->Get(context, i)
    4549             :                                    .ToLocalChecked()
    4550          10 :                                    ->ToObject(context)
    4551             :                                    .ToLocalChecked());
    4552             :     Handle<v8::internal::JSValue> private_value =
    4553             :         Handle<v8::internal::JSValue>::cast(private_name);
    4554             :     Handle<v8::internal::Symbol> priv_symbol(
    4555             :         v8::internal::Symbol::cast(private_value->value()), isolate);
    4556          10 :     CHECK(priv_symbol->is_private_name());
    4557             :   }
    4558             : 
    4559             :   source = v8_str(
    4560             :       "var Y = class {\n"
    4561             :       "  #baz = 2;\n"
    4562             :       "}\n"
    4563             :       "var X = class extends Y{\n"
    4564             :       "  #foo = 1;\n"
    4565             :       "  #bar = function() {};\n"
    4566             :       "}\n"
    4567           5 :       "var x = new X()");
    4568           5 :   CompileRun(source);
    4569             :   object = v8::Local<v8::Object>::Cast(
    4570          10 :       env->Global()
    4571          15 :           ->Get(context, v8_str(env->GetIsolate(), "x"))
    4572           5 :           .ToLocalChecked());
    4573           5 :   private_names = v8::debug::GetPrivateFields(context, object).ToLocalChecked();
    4574             : 
    4575          35 :   for (int i = 0; i < 6; i = i + 2) {
    4576             :     Handle<v8::internal::JSReceiver> private_name =
    4577          15 :         v8::Utils::OpenHandle(*private_names->Get(context, i)
    4578             :                                    .ToLocalChecked()
    4579          15 :                                    ->ToObject(context)
    4580             :                                    .ToLocalChecked());
    4581             :     Handle<v8::internal::JSValue> private_value =
    4582             :         Handle<v8::internal::JSValue>::cast(private_name);
    4583             :     Handle<v8::internal::Symbol> priv_symbol(
    4584             :         v8::internal::Symbol::cast(private_value->value()), isolate);
    4585          15 :     CHECK(priv_symbol->is_private_name());
    4586             :   }
    4587             : 
    4588             :   source = v8_str(
    4589             :       "var Y = class {\n"
    4590             :       "  constructor() {"
    4591             :       "    return new Proxy({}, {});"
    4592             :       "  }"
    4593             :       "}\n"
    4594             :       "var X = class extends Y{\n"
    4595             :       "  #foo = 1;\n"
    4596             :       "  #bar = function() {};\n"
    4597             :       "}\n"
    4598           5 :       "var x = new X()");
    4599           5 :   CompileRun(source);
    4600             :   object = v8::Local<v8::Object>::Cast(
    4601          10 :       env->Global()
    4602          15 :           ->Get(context, v8_str(env->GetIsolate(), "x"))
    4603           5 :           .ToLocalChecked());
    4604           5 :   private_names = v8::debug::GetPrivateFields(context, object).ToLocalChecked();
    4605             : 
    4606          25 :   for (int i = 0; i < 4; i = i + 2) {
    4607             :     Handle<v8::internal::JSReceiver> private_name =
    4608          10 :         v8::Utils::OpenHandle(*private_names->Get(context, i)
    4609             :                                    .ToLocalChecked()
    4610          10 :                                    ->ToObject(context)
    4611             :                                    .ToLocalChecked());
    4612             :     Handle<v8::internal::JSValue> private_value =
    4613             :         Handle<v8::internal::JSValue>::cast(private_name);
    4614             :     Handle<v8::internal::Symbol> priv_symbol(
    4615             :         v8::internal::Symbol::cast(private_value->value()), isolate);
    4616          10 :     CHECK(priv_symbol->is_private_name());
    4617             :   }
    4618       79922 : }

Generated by: LCOV version 1.10