// Copyright 2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/api.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/v8.h"
#include "test/cctest/cctest.h"

#include "src/base/platform/platform.h"


v8::base::Semaphore* semaphore = NULL;


void Signal(const v8::FunctionCallbackInfo<v8::Value>& args) {
  semaphore->Signal();
}


void TerminateCurrentThread(const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  args.GetIsolate()->TerminateExecution();
}


void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK(false);
}


void Loop(const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  v8::MaybeLocal<v8::Value> result =
      CompileRun(args.GetIsolate()->GetCurrentContext(),
                 "try { doloop(); fail(); } catch(e) { fail(); }");
  CHECK(result.IsEmpty());
  CHECK(args.GetIsolate()->IsExecutionTerminating());
}


void DoLoop(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  v8::MaybeLocal<v8::Value> result =
      CompileRun(args.GetIsolate()->GetCurrentContext(),
                 "function f() {"
                 "  var term = true;"
                 "  try {"
                 "    while(true) {"
                 "      if (term) terminate();"
                 "      term = false;"
                 "    }"
                 "    fail();"
                 "  } catch(e) {"
                 "    fail();"
                 "  }"
                 "}"
                 "f()");
  CHECK(result.IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(try_catch.Exception()->IsNull());
  CHECK(try_catch.Message().IsEmpty());
  CHECK(!try_catch.CanContinue());
  CHECK(args.GetIsolate()->IsExecutionTerminating());
}


void DoLoopNoCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  v8::MaybeLocal<v8::Value> result =
      CompileRun(args.GetIsolate()->GetCurrentContext(),
                 "var term = true;"
                 "while(true) {"
                 "  if (term) terminate();"
                 "  term = false;"
                 "}");
  CHECK(result.IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(try_catch.Exception()->IsNull());
  CHECK(try_catch.Message().IsEmpty());
  CHECK(!try_catch.CanContinue());
  CHECK(args.GetIsolate()->IsExecutionTerminating());
}


v8::Local<v8::ObjectTemplate> CreateGlobalTemplate(
    v8::Isolate* isolate, v8::FunctionCallback terminate,
    v8::FunctionCallback doloop) {
  v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
  global->Set(v8_str("terminate"),
              v8::FunctionTemplate::New(isolate, terminate));
  global->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
  global->Set(v8_str("loop"), v8::FunctionTemplate::New(isolate, Loop));
  global->Set(v8_str("doloop"), v8::FunctionTemplate::New(isolate, doloop));
  return global;
}


// Test that a single thread of JavaScript execution can terminate
// itself.
TEST(TerminateOnlyV8ThreadFromThreadItself) {
  v8::HandleScope scope(CcTest::isolate());
  v8::Local<v8::ObjectTemplate> global =
      CreateGlobalTemplate(CcTest::isolate(), TerminateCurrentThread, DoLoop);
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  // Run a loop that will be infinite if thread termination does not work.
  v8::MaybeLocal<v8::Value> result =
      CompileRun(CcTest::isolate()->GetCurrentContext(),
                 "try { loop(); fail(); } catch(e) { fail(); }");
  CHECK(result.IsEmpty());
  // Test that we can run the code again after thread termination.
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  result = CompileRun(CcTest::isolate()->GetCurrentContext(),
                      "try { loop(); fail(); } catch(e) { fail(); }");
  CHECK(result.IsEmpty());
}


// Test that a single thread of JavaScript execution can terminate
// itself in a loop that performs no calls.
TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
  v8::HandleScope scope(CcTest::isolate());
  v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
      CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall);
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  // Run a loop that will be infinite if thread termination does not work.
  static const char* source = "try { loop(); fail(); } catch(e) { fail(); }";
  v8::MaybeLocal<v8::Value> result =
      CompileRun(CcTest::isolate()->GetCurrentContext(), source);
  CHECK(result.IsEmpty());
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  // Test that we can run the code again after thread termination.
  result = CompileRun(CcTest::isolate()->GetCurrentContext(), source);
  CHECK(result.IsEmpty());
}


class TerminatorThread : public v8::base::Thread {
 public:
  explicit TerminatorThread(i::Isolate* isolate)
      : Thread(Options("TerminatorThread")),
        isolate_(reinterpret_cast<v8::Isolate*>(isolate)) {}
  void Run() {
    semaphore->Wait();
    CHECK(!isolate_->IsExecutionTerminating());
    isolate_->TerminateExecution();
  }

 private:
  v8::Isolate* isolate_;
};


// Test that a single thread of JavaScript execution can be terminated
// from the side by another thread.
TEST(TerminateOnlyV8ThreadFromOtherThread) {
  semaphore = new v8::base::Semaphore(0);
  TerminatorThread thread(CcTest::i_isolate());
  thread.Start();

  v8::HandleScope scope(CcTest::isolate());
  v8::Local<v8::ObjectTemplate> global =
      CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop);
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  // Run a loop that will be infinite if thread termination does not work.
  v8::MaybeLocal<v8::Value> result =
      CompileRun(CcTest::isolate()->GetCurrentContext(),
                 "try { loop(); fail(); } catch(e) { fail(); }");
  CHECK(result.IsEmpty());
  thread.Join();
  delete semaphore;
  semaphore = NULL;
}

// Test that execution can be terminated from within JSON.stringify.
TEST(TerminateJsonStringify) {
  semaphore = new v8::base::Semaphore(0);
  TerminatorThread thread(CcTest::i_isolate());
  thread.Start();

  v8::HandleScope scope(CcTest::isolate());
  v8::Local<v8::ObjectTemplate> global =
      CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop);
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  v8::MaybeLocal<v8::Value> result =
      CompileRun(CcTest::isolate()->GetCurrentContext(),
                 "var x = [];"
                 "x[2**31]=1;"
                 "terminate();"
                 "JSON.stringify(x);"
                 "fail();");
  CHECK(result.IsEmpty());
  thread.Join();
  delete semaphore;
  semaphore = NULL;
}

int call_count = 0;


void TerminateOrReturnObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
  if (++call_count == 10) {
    CHECK(!args.GetIsolate()->IsExecutionTerminating());
    args.GetIsolate()->TerminateExecution();
    return;
  }
  v8::Local<v8::Object> result = v8::Object::New(args.GetIsolate());
  v8::Maybe<bool> val =
      result->Set(args.GetIsolate()->GetCurrentContext(), v8_str("x"),
                  v8::Integer::New(args.GetIsolate(), 42));
  CHECK(val.FromJust());
  args.GetReturnValue().Set(result);
}


void LoopGetProperty(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  v8::MaybeLocal<v8::Value> result =
      CompileRun(args.GetIsolate()->GetCurrentContext(),
                 "function f() {"
                 "  try {"
                 "    while(true) {"
                 "      terminate_or_return_object().x;"
                 "    }"
                 "    fail();"
                 "  } catch(e) {"
                 "    (function() {})();"  // trigger stack check.
                 "    fail();"
                 "  }"
                 "}"
                 "f()");
  CHECK(result.IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(try_catch.Exception()->IsNull());
  CHECK(try_catch.Message().IsEmpty());
  CHECK(!try_catch.CanContinue());
  CHECK(args.GetIsolate()->IsExecutionTerminating());
}


// Test that we correctly handle termination exceptions if they are
// triggered by the creation of error objects in connection with ICs.
TEST(TerminateLoadICException) {
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
  global->Set(v8_str("terminate_or_return_object"),
              v8::FunctionTemplate::New(isolate, TerminateOrReturnObject));
  global->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
  global->Set(v8_str("loop"),
              v8::FunctionTemplate::New(isolate, LoopGetProperty));

  v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!isolate->IsExecutionTerminating());
  // Run a loop that will be infinite if thread termination does not work.
  static const char* source = "try { loop(); fail(); } catch(e) { fail(); }";
  call_count = 0;
  v8::MaybeLocal<v8::Value> result =
      CompileRun(isolate->GetCurrentContext(), source);
  CHECK(result.IsEmpty());
  // Test that we can run the code again after thread termination.
  CHECK(!isolate->IsExecutionTerminating());
  call_count = 0;
  result = CompileRun(isolate->GetCurrentContext(), source);
  CHECK(result.IsEmpty());
}


v8::Persistent<v8::String> reenter_script_1;
v8::Persistent<v8::String> reenter_script_2;

void ReenterAfterTermination(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  v8::Isolate* isolate = args.GetIsolate();
  CHECK(!isolate->IsExecutionTerminating());
  v8::Local<v8::String> script =
      v8::Local<v8::String>::New(isolate, reenter_script_1);
  v8::MaybeLocal<v8::Value> result = CompileRun(script);
  CHECK(result.IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(try_catch.Exception()->IsNull());
  CHECK(try_catch.Message().IsEmpty());
  CHECK(!try_catch.CanContinue());
  CHECK(isolate->IsExecutionTerminating());
  script = v8::Local<v8::String>::New(isolate, reenter_script_2);
  v8::MaybeLocal<v8::Script> compiled_script =
      v8::Script::Compile(isolate->GetCurrentContext(), script);
  CHECK(compiled_script.IsEmpty());
}


// Test that reentry into V8 while the termination exception is still pending
// (has not yet unwound the 0-level JS frame) does not crash.
TEST(TerminateAndReenterFromThreadItself) {
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
      isolate, TerminateCurrentThread, ReenterAfterTermination);
  v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!v8::Isolate::GetCurrent()->IsExecutionTerminating());
  // Create script strings upfront as it won't work when terminating.
  reenter_script_1.Reset(isolate, v8_str(
                                      "function f() {"
                                      "  var term = true;"
                                      "  try {"
                                      "    while(true) {"
                                      "      if (term) terminate();"
                                      "      term = false;"
                                      "    }"
                                      "    fail();"
                                      "  } catch(e) {"
                                      "    fail();"
                                      "  }"
                                      "}"
                                      "f()"));
  reenter_script_2.Reset(isolate, v8_str("function f() { fail(); } f()"));
  CompileRun("try { loop(); fail(); } catch(e) { fail(); }");
  CHECK(!isolate->IsExecutionTerminating());
  // Check we can run JS again after termination.
  CHECK(CompileRun("function f() { return true; } f()")->IsTrue());
  reenter_script_1.Reset();
  reenter_script_2.Reset();
}


void DoLoopCancelTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
  v8::TryCatch try_catch(args.GetIsolate());
  CHECK(!v8::Isolate::GetCurrent()->IsExecutionTerminating());
  v8::MaybeLocal<v8::Value> result =
      CompileRun(args.GetIsolate()->GetCurrentContext(),
                 "var term = true;"
                 "while(true) {"
                 "  if (term) terminate();"
                 "  term = false;"
                 "}"
                 "fail();");
  CHECK(result.IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(try_catch.Exception()->IsNull());
  CHECK(try_catch.Message().IsEmpty());
  CHECK(!try_catch.CanContinue());
  CHECK(v8::Isolate::GetCurrent()->IsExecutionTerminating());
  CHECK(try_catch.HasTerminated());
  CcTest::isolate()->CancelTerminateExecution();
  CHECK(!v8::Isolate::GetCurrent()->IsExecutionTerminating());
}


// Test that a single thread of JavaScript execution can terminate
// itself and then resume execution.
TEST(TerminateCancelTerminateFromThreadItself) {
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
      isolate, TerminateCurrentThread, DoLoopCancelTerminate);
  v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!CcTest::isolate()->IsExecutionTerminating());
  // Check that execution completed with correct return value.
  v8::Local<v8::Value> result =
      CompileRun(isolate->GetCurrentContext(),
                 "try { doloop(); } catch(e) { fail(); } 'completed';")
          .ToLocalChecked();
  CHECK(result->Equals(isolate->GetCurrentContext(), v8_str("completed"))
            .FromJust());
}


void MicrotaskShouldNotRun(const v8::FunctionCallbackInfo<v8::Value>& info) {
  CHECK(false);
}


void MicrotaskLoopForever(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::HandleScope scope(isolate);
  // Enqueue another should-not-run task to ensure we clean out the queue
  // when we terminate.
  isolate->EnqueueMicrotask(
      v8::Function::New(isolate->GetCurrentContext(), MicrotaskShouldNotRun)
          .ToLocalChecked());
  CompileRun("terminate(); while (true) { }");
  CHECK(v8::Isolate::GetCurrent()->IsExecutionTerminating());
}


TEST(TerminateFromOtherThreadWhileMicrotaskRunning) {
  semaphore = new v8::base::Semaphore(0);
  TerminatorThread thread(CcTest::i_isolate());
  thread.Start();

  v8::Isolate* isolate = CcTest::isolate();
  isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global =
      CreateGlobalTemplate(CcTest::isolate(), Signal, DoLoop);
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global);
  v8::Context::Scope context_scope(context);
  isolate->EnqueueMicrotask(
      v8::Function::New(isolate->GetCurrentContext(), MicrotaskLoopForever)
          .ToLocalChecked());
  // The second task should never be run because we bail out if we're
  // terminating.
  isolate->EnqueueMicrotask(
      v8::Function::New(isolate->GetCurrentContext(), MicrotaskShouldNotRun)
          .ToLocalChecked());
  isolate->RunMicrotasks();

  isolate->CancelTerminateExecution();
  isolate->RunMicrotasks();  // should not run MicrotaskShouldNotRun

  thread.Join();
  delete semaphore;
  semaphore = NULL;
}


static int callback_counter = 0;


static void CounterCallback(v8::Isolate* isolate, void* data) {
  callback_counter++;
}


TEST(PostponeTerminateException) {
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global =
      CreateGlobalTemplate(CcTest::isolate(), TerminateCurrentThread, DoLoop);
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global);
  v8::Context::Scope context_scope(context);

  v8::TryCatch try_catch(isolate);
  static const char* terminate_and_loop =
      "terminate(); for (var i = 0; i < 10000; i++);";

  { // Postpone terminate execution interrupts.
    i::PostponeInterruptsScope p1(CcTest::i_isolate(),
                                  i::StackGuard::TERMINATE_EXECUTION);

    // API interrupts should still be triggered.
    CcTest::isolate()->RequestInterrupt(&CounterCallback, NULL);
    CHECK_EQ(0, callback_counter);
    CompileRun(terminate_and_loop);
    CHECK(!try_catch.HasTerminated());
    CHECK_EQ(1, callback_counter);

    { // Postpone API interrupts as well.
      i::PostponeInterruptsScope p2(CcTest::i_isolate(),
                                    i::StackGuard::API_INTERRUPT);

      // None of the two interrupts should trigger.
      CcTest::isolate()->RequestInterrupt(&CounterCallback, NULL);
      CompileRun(terminate_and_loop);
      CHECK(!try_catch.HasTerminated());
      CHECK_EQ(1, callback_counter);
    }

    // Now the previously requested API interrupt should trigger.
    CompileRun(terminate_and_loop);
    CHECK(!try_catch.HasTerminated());
    CHECK_EQ(2, callback_counter);
  }

  // Now the previously requested terminate execution interrupt should trigger.
  CompileRun("for (var i = 0; i < 10000; i++);");
  CHECK(try_catch.HasTerminated());
  CHECK_EQ(2, callback_counter);
}


TEST(ErrorObjectAfterTermination) {
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
  v8::Context::Scope context_scope(context);
  isolate->TerminateExecution();
  v8::Local<v8::Value> error = v8::Exception::Error(v8_str("error"));
  CHECK(error->IsNativeError());
}


void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  v8::Local<v8::Object> global = CcTest::global();
  v8::Local<v8::Function> loop = v8::Local<v8::Function>::Cast(
      global->Get(CcTest::isolate()->GetCurrentContext(), v8_str("loop"))
          .ToLocalChecked());
  i::MaybeHandle<i::Object> exception;
  i::MaybeHandle<i::Object> result =
      i::Execution::TryCall(CcTest::i_isolate(), v8::Utils::OpenHandle((*loop)),
                            v8::Utils::OpenHandle((*global)), 0, nullptr,
                            i::Execution::MessageHandling::kReport, &exception);
  CHECK(result.is_null());
  // TryCall ignores terminate execution, but rerequests the interrupt.
  CHECK(!args.GetIsolate()->IsExecutionTerminating());
  CHECK(CompileRun("1 + 1;").IsEmpty());
}


TEST(TerminationInInnerTryCall) {
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global_template = CreateGlobalTemplate(
      CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall);
  global_template->Set(
      v8_str("inner_try_call_terminate"),
      v8::FunctionTemplate::New(isolate, InnerTryCallTerminate));
  v8::Local<v8::Context> context =
      v8::Context::New(CcTest::isolate(), NULL, global_template);
  v8::Context::Scope context_scope(context);
  {
    v8::TryCatch try_catch(isolate);
    CompileRun("inner_try_call_terminate()");
    CHECK(try_catch.HasTerminated());
  }
  v8::Maybe<int32_t> result = CompileRun("2 + 2")->Int32Value(
      v8::Isolate::GetCurrent()->GetCurrentContext());
  CHECK_EQ(4, result.FromJust());
  CHECK(!v8::Isolate::GetCurrent()->IsExecutionTerminating());
}


TEST(TerminateAndTryCall) {
  i::FLAG_allow_natives_syntax = true;
  v8::Isolate* isolate = CcTest::isolate();
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
      isolate, TerminateCurrentThread, DoLoopCancelTerminate);
  v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!isolate->IsExecutionTerminating());
  v8::TryCatch try_catch(isolate);
  CHECK(!isolate->IsExecutionTerminating());
  // Terminate execution has been triggered inside TryCall, but re-requested
  // to trigger later.
  CHECK(CompileRun("terminate(); reference_error();").IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(!isolate->IsExecutionTerminating());
  v8::Local<v8::Value> value =
      CcTest::global()
          ->Get(isolate->GetCurrentContext(), v8_str("terminate"))
          .ToLocalChecked();
  CHECK(value->IsFunction());
  // The first stack check after terminate has been re-requested fails.
  CHECK(CompileRun("1 + 1").IsEmpty());
  CHECK(!isolate->IsExecutionTerminating());
  // V8 then recovers.
  v8::Maybe<int32_t> result = CompileRun("2 + 2")->Int32Value(
      v8::Isolate::GetCurrent()->GetCurrentContext());
  CHECK_EQ(4, result.FromJust());
  CHECK(!isolate->IsExecutionTerminating());
}

class ConsoleImpl : public v8::debug::ConsoleDelegate {
 private:
  void Log(const v8::debug::ConsoleCallArguments& args,
           const v8::debug::ConsoleContext&) override {
    CompileRun("1 + 1");
  }
};

TEST(TerminateConsole) {
  i::FLAG_allow_natives_syntax = true;
  v8::Isolate* isolate = CcTest::isolate();
  ConsoleImpl console;
  v8::debug::SetConsoleDelegate(isolate, &console);
  v8::HandleScope scope(isolate);
  v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
      isolate, TerminateCurrentThread, DoLoopCancelTerminate);
  v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
  v8::Context::Scope context_scope(context);
  CHECK(!isolate->IsExecutionTerminating());
  v8::TryCatch try_catch(isolate);
  CHECK(!isolate->IsExecutionTerminating());
  CHECK(CompileRun("terminate(); console.log(); fail();").IsEmpty());
  CHECK(try_catch.HasCaught());
  CHECK(!isolate->IsExecutionTerminating());
}
