static void JS_DefineAction(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);
  TRI_GET_GLOBALS();

  if (args.Length() != 3) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "defineAction(<name>, <callback>, <parameter>)");
  }

  V8SecurityFeature& v8security = v8g->_server.getFeature<V8SecurityFeature>();

  if (!v8security.isAllowedToDefineHttpAction(isolate)) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(
        TRI_ERROR_FORBIDDEN, "operation only allowed for internal scripts");
  }

  // extract the action name
  TRI_Utf8ValueNFC utf8name(isolate, args[0]);

  if (*utf8name == nullptr) {
    TRI_V8_THROW_TYPE_ERROR("<name> must be an UTF-8 string");
  }

  std::string name = *utf8name;

  // extract the action callback
  if (!args[1]->IsFunction()) {
    TRI_V8_THROW_TYPE_ERROR("<callback> must be a function");
  }

  v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(args[1]);

  // extract the options
  v8::Handle<v8::Object> options;

  if (args[2]->IsObject()) {
    options = args[2]->ToObject(TRI_IGETC).FromMaybe(v8::Local<v8::Object>());
  } else {
    options = v8::Object::New(isolate);
  }

  // create an action with the given options
  auto action =
      std::make_shared<v8_action_t>(v8g->_server.getFeature<ActionFeature>());
  ParseActionOptions(isolate, v8g, action.get(), options);

  // store an action with the given name
  // note: this may return a previous action for the same name
  std::shared_ptr<TRI_action_t> actionForName =
      TRI_DefineActionVocBase(name, action);

  v8_action_t* v8ActionForName =
      dynamic_cast<v8_action_t*>(actionForName.get());

  if (v8ActionForName != nullptr) {
    v8ActionForName->createCallback(isolate, callback);
  } else {
    LOG_TOPIC("43be9", WARN, arangodb::Logger::FIXME)
        << "cannot create callback for V8 action";
  }

  TRI_V8_RETURN_UNDEFINED();
  TRI_V8_TRY_CATCH_END
}
static void JS_DefineAction(v8::FunctionCallbackInfo<v8::Value> const& args) {
  TRI_V8_TRY_CATCH_BEGIN(isolate);
  v8::HandleScope scope(isolate);
  TRI_GET_GLOBALS();

  if (args.Length() != 3) {
    TRI_V8_THROW_EXCEPTION_USAGE(
        "defineAction(<name>, <callback>, <parameter>)");
  }

  V8SecurityFeature& v8security = v8g->_server.getFeature<V8SecurityFeature>();

  if (!v8security.isAllowedToDefineHttpAction(isolate)) {
    TRI_V8_THROW_EXCEPTION_MESSAGE(
        TRI_ERROR_FORBIDDEN, "operation only allowed for internal scripts");
  }

   
  TRI_Utf8ValueNFC utf8name(isolate, args[0]);

  if (*utf8name == nullptr) {
    TRI_V8_THROW_TYPE_ERROR("<name> must be an UTF-8 string");
  }

  std::string name = *utf8name;

   
  if (!args[1]->IsFunction()) {
    TRI_V8_THROW_TYPE_ERROR("<callback> must be a function");
  }

  v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(args[1]);

   
  v8::Handle<v8::Object> options;

  if (args[2]->IsObject()) {
    options = args[2]->ToObject(TRI_IGETC).FromMaybe(v8::Local<v8::Object>());
  } else {
    options = v8::Object::New(isolate);
  }

   
  auto action =
      std::make_shared<v8_action_t>(v8g->_server.getFeature<ActionFeature>());
  ParseActionOptions(isolate, v8g, action.get(), options);

   
   
  std::shared_ptr<TRI_action_t> actionForName =
      TRI_DefineActionVocBase(name, action);

  v8_action_t* v8ActionForName =
      dynamic_cast<v8_action_t*>(actionForName.get());

  if (v8ActionForName != nullptr) {
    v8ActionForName->createCallback(isolate, callback);
  } else {
    LOG_TOPIC("43be9", WARN, arangodb::Logger::FIXME)
        << "cannot create callback for V8 action";
  }

  TRI_V8_RETURN_UNDEFINED();
  TRI_V8_TRY_CATCH_END
}