static TRI_action_result_t ExecuteActionVocbase(
    TRI_vocbase_t* vocbase, v8::Isolate* isolate, TRI_action_t const* action,
    v8::Handle<v8::Function> callback, GeneralRequest* request,
    GeneralResponse* response) {
  v8::HandleScope scope(isolate);
  v8::TryCatch tryCatch(isolate);

  if (response == nullptr) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response");
  }

  TRI_GET_GLOBALS();

  v8::Handle<v8::Object> req =
      TRI_RequestCppToV8(isolate, v8g, request, action);

  // create the response object
  v8::Handle<v8::Object> res = v8::Object::New(isolate);

  // register request & response in the context
  v8g->_currentRequest = req;
  v8g->_currentResponse = res;

  // execute the callback
  v8::Handle<v8::Value> args[2] = {req, res};

  // handle C++ exceptions that happen during dynamic script execution
  ErrorCode errorCode = TRI_ERROR_NO_ERROR;
  std::string errorMessage;

  try {
    callback->Call(TRI_IGETC, callback, 2, args)
        .FromMaybe(v8::Local<v8::Value>());
    ;
    errorCode = TRI_ERROR_NO_ERROR;
  } catch (arangodb::basics::Exception const& ex) {
    errorCode = ex.code();
    errorMessage = ex.what();
  } catch (std::bad_alloc const&) {
    errorCode = TRI_ERROR_OUT_OF_MEMORY;
  } catch (...) {
    errorCode = TRI_ERROR_INTERNAL;
  }

  // invalidate request / response objects
  v8g->_currentRequest = v8::Undefined(isolate);
  v8g->_currentResponse = v8::Undefined(isolate);

  // convert the result
  TRI_action_result_t result;
  result.isValid = true;

  if (errorCode != TRI_ERROR_NO_ERROR) {
    result.isValid = false;
    result.canceled = false;

    response->setResponseCode(rest::ResponseCode::SERVER_ERROR);

    if (errorMessage.empty()) {
      errorMessage = TRI_errno_string(errorCode);
    }

    VPackBuffer<uint8_t> buffer;
    VPackBuilder b(buffer);
    b.add(VPackValue(errorMessage));
    response->addPayload(std::move(buffer));
  }

  else if (v8g->_canceled) {
    result.isValid = false;
    result.canceled = true;
  }

  else if (tryCatch.HasCaught()) {
    if (tryCatch.CanContinue()) {
      response->setResponseCode(rest::ResponseCode::SERVER_ERROR);

      std::string jsError = TRI_StringifyV8Exception(isolate, &tryCatch);
      LOG_TOPIC("b8286", WARN, arangodb::Logger::V8)
          << "Caught an error while executing an action: " << jsError;
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
      VPackBuilder b;
      b.add(VPackValue(TRI_StringifyV8Exception(isolate, &tryCatch)));
      response->addPayload(b.slice());
#endif
    } else {
      v8g->_canceled = true;
      result.isValid = false;
      result.canceled = true;
    }
  }

  else {
    ResponseV8ToCpp(isolate, v8g, request, res, response);
  }

  return result;
}
static TRI_action_result_t ExecuteActionVocbase(
    TRI_vocbase_t* vocbase, v8::Isolate* isolate, TRI_action_t const* action,
    v8::Handle<v8::Function> callback, GeneralRequest* request,
    GeneralResponse* response) {
  v8::HandleScope scope(isolate);
  v8::TryCatch tryCatch(isolate);

  if (response == nullptr) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response");
  }

  TRI_GET_GLOBALS();

  v8::Handle<v8::Object> req =
      TRI_RequestCppToV8(isolate, v8g, request, action);

   
  v8::Handle<v8::Object> res = v8::Object::New(isolate);

   
  v8g->_currentRequest = req;
  v8g->_currentResponse = res;

   
  v8::Handle<v8::Value> args[2] = {req, res};

   
  ErrorCode errorCode = TRI_ERROR_NO_ERROR;
  std::string errorMessage;

  try {
    callback->Call(TRI_IGETC, callback, 2, args)
        .FromMaybe(v8::Local<v8::Value>());
    ;
    errorCode = TRI_ERROR_NO_ERROR;
  } catch (arangodb::basics::Exception const& ex) {
    errorCode = ex.code();
    errorMessage = ex.what();
  } catch (std::bad_alloc const&) {
    errorCode = TRI_ERROR_OUT_OF_MEMORY;
  } catch (...) {
    errorCode = TRI_ERROR_INTERNAL;
  }

   
  v8g->_currentRequest = v8::Undefined(isolate);
  v8g->_currentResponse = v8::Undefined(isolate);

   
  TRI_action_result_t result;
  result.isValid = true;

  if (errorCode != TRI_ERROR_NO_ERROR) {
    result.isValid = false;
    result.canceled = false;

    response->setResponseCode(rest::ResponseCode::SERVER_ERROR);

    if (errorMessage.empty()) {
      errorMessage = TRI_errno_string(errorCode);
    }

    VPackBuffer<uint8_t> buffer;
    VPackBuilder b(buffer);
    b.add(VPackValue(errorMessage));
    response->addPayload(std::move(buffer));
  }

  else if (v8g->_canceled) {
    result.isValid = false;
    result.canceled = true;
  }

  else if (tryCatch.HasCaught()) {
    if (tryCatch.CanContinue()) {
      response->setResponseCode(rest::ResponseCode::SERVER_ERROR);

      std::string jsError = TRI_StringifyV8Exception(isolate, &tryCatch);
      LOG_TOPIC("b8286", WARN, arangodb::Logger::V8)
          << "Caught an error while executing an action: " << jsError;
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
      VPackBuilder b;
      b.add(VPackValue(TRI_StringifyV8Exception(isolate, &tryCatch)));
      response->addPayload(b.slice());
#endif
    } else {
      v8g->_canceled = true;
      result.isValid = false;
      result.canceled = true;
    }
  }

  else {
    ResponseV8ToCpp(isolate, v8g, request, res, response);
  }

  return result;
}