예제 #1
0
// the result is wrapped in a Javascript variable SYS_ARANGO
V8ClientConnection* V8ShellFeature::setup(
    v8::Local<v8::Context>& context, bool createConnection,
    std::vector<std::string> const& positionals, bool* promptError) {
  std::unique_ptr<V8ClientConnection> v8connection;

  ClientFeature* client = nullptr;

  if (createConnection) {
    client = dynamic_cast<ClientFeature*>(server()->feature("Client"));

    if (client != nullptr && client->isEnabled()) {
      auto connection = client->createConnection();
      v8connection = std::make_unique<V8ClientConnection>(
          connection, client->databaseName(), client->username(),
          client->password(), client->requestTimeout());
    } else {
      client = nullptr;
    }
  }

  initMode(ShellFeature::RunMode::INTERACTIVE, positionals);

  if (createConnection && client != nullptr) {
    v8connection->initServer(_isolate, context, client);
  }

  bool pe = printHello(v8connection.get());
  loadModules(ShellFeature::RunMode::INTERACTIVE);

  if (promptError != nullptr) {
    *promptError = pe;
  }

  return v8connection.release();
}
예제 #2
0
int V8ShellFeature::runShell(std::vector<std::string> const& positionals) {
  v8::Locker locker{_isolate};

  v8::Isolate::Scope isolate_scope(_isolate);
  v8::HandleScope handle_scope(_isolate);

  v8::Local<v8::Context> context =
      v8::Local<v8::Context>::New(_isolate, _context);

  v8::Context::Scope context_scope{context};

  bool promptError;
  auto v8connection = setup(context, true, positionals, &promptError);
  std::unique_ptr<V8ClientConnection> guard(v8connection);

  V8LineEditor v8LineEditor(_isolate, context, "." + _name + ".history");

  if (v8connection != nullptr) {
    v8LineEditor.setSignalFunction(
        [&v8connection]() { v8connection->setInterrupted(true); });
  }

  v8LineEditor.open(_console->autoComplete());

  v8::Local<v8::String> name(
      TRI_V8_ASCII_STRING2(_isolate, TRI_V8_SHELL_COMMAND_NAME));

  uint64_t nrCommands = 0;

  ClientFeature* client = server()->getFeature<ClientFeature>("Client");

  if (!client->isEnabled()) {
    client = nullptr;
  }

  bool const isBatch = isatty(STDIN_FILENO) == 0;
  bool lastEmpty = isBatch;

  while (true) {
    _console->setPromptError(promptError);
    auto prompt = _console->buildPrompt(client);

    ShellBase::EofType eof = ShellBase::EOF_NONE;
    std::string input =
        v8LineEditor.prompt(prompt._colored, prompt._plain, eof);

    if (eof == ShellBase::EOF_FORCE_ABORT || (eof == ShellBase::EOF_ABORT && lastEmpty)) {
      break;
    }

    if (input.empty()) {
      promptError = false;
      lastEmpty = true;
      continue;
    }
    lastEmpty = isBatch;

    _console->log(prompt._plain + input + "\n");

    std::string i = StringUtils::trim(input);

    if (i == "exit" || i == "quit" || i == "exit;" || i == "quit;") {
      break;
    }

    if (i == "help" || i == "help;") {
      input = "help()";
    }

    v8LineEditor.addHistory(input);

    v8::TryCatch tryCatch;

    _console->startPager();

    // assume the command succeeds
    promptError = false;

    // execute command and register its result in __LAST__
    v8LineEditor.setExecutingCommand(true);

    v8::Handle<v8::Value> v = TRI_ExecuteJavaScriptString(
        _isolate, context, TRI_V8_STRING2(_isolate, input.c_str()), name, true);

    v8LineEditor.setExecutingCommand(false);

    if (v.IsEmpty()) {
      context->Global()->Set(TRI_V8_ASCII_STRING2(_isolate, "_last"),
                             v8::Undefined(_isolate));
    } else {
      context->Global()->Set(TRI_V8_ASCII_STRING2(_isolate, "_last"), v);
    }

    // command failed
    if (tryCatch.HasCaught()) {
      std::string exception;

      if (!tryCatch.CanContinue() || tryCatch.HasTerminated()) {
        exception = "command locally aborted\n";
      } else {
        exception = TRI_StringifyV8Exception(_isolate, &tryCatch);
      }

      _console->printErrorLine(exception);
      _console->log(exception);

      // this will change the prompt for the next round
      promptError = true;
    }

    if (v8connection != nullptr) {
      v8connection->setInterrupted(false);
    }

    _console->stopPager();
    _console->printLine("");

    _console->log("\n");

    // make sure the last command result makes it into the log file
    _console->flushLog();

    // gc
    if (++nrCommands >= _gcInterval ||
        V8PlatformFeature::isOutOfMemory(_isolate)) {
      nrCommands = 0;
      TRI_RunGarbageCollectionV8(_isolate, 500.0);

      // needs to be reset after the garbage collection
      V8PlatformFeature::resetOutOfMemory(_isolate);
    }
  }
      
  if (!_console->quiet()) {
    _console->printLine("");
    _console->printByeBye();
  }

  return promptError ? TRI_ERROR_INTERNAL : TRI_ERROR_NO_ERROR;
}