// 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/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"));
  // TODO(yangguo): crbug/403509. Check for empty handle instead.
  CHECK(error->IsUndefined());
}


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> result =
      i::Execution::TryCall(CcTest::i_isolate(), v8::Utils::OpenHandle((*loop)),
                            v8::Utils::OpenHandle((*global)), 0, NULL, NULL);
  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());
}
