void SandboxJSExecutor::loadApplicationScript(std::unique_ptr<const JSBigString> script, uint64_t /*scriptVersion*/, std::string sourceURL, std::string&& /*bytecodeFileName*/) {
  auto requestId = GetNextRequestId();
  task_completion_event<void> callback;
  m_callbacks.emplace(requestId, callback);

  folly::dynamic request = folly::dynamic::object
    ("script", script->c_str())
    ("inject", m_injectedObjects)
    ("url", sourceURL);

  try {
    SendMessageAsync(requestId, "executeApplicationScript", request).then([callback](bool success) {
      if (success) {
        // Return task to wait for reply.
        return task<void>(callback);
      } else {
        throw new exception("Failed to send");
      }
    }).get();
  }
  //TODO: handle exceptions in a better way
  catch (exception& e) {
    m_errorCallback(e.what());
    SetState(State::Error);
  }
}
// NOTE: This function synchronously waiting until get reply back from the sandbox.
// TODO: Indefinite waiting can cause SDX to become unresponsive. We need to implement timeout mechanism.
void SandboxJSExecutor::Call(const std::string& methodName, folly::dynamic& arguments) {
  auto requestId = GetNextRequestId();
  task_completion_event<void> callback;
  m_callbacks.emplace(requestId, callback);

  try {
    std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now();

    SendMessageAsync(requestId, methodName, arguments).then([callback](bool sent) {
      if (sent) {
        // Return task to wait for reply.
        return task<void>(callback);
      } else {
        throw new exception("Failed to send");
      }
    }).get();  // wait until get reply

    std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count();

    char buffer[256];
    sprintf_s(buffer, "(%03I64d) CallFunction, elapsed time = %d us\n", requestId, (int)duration);
    OutputDebugStringA(buffer);
  }
  //TODO: handle exceptions in a better way
  catch (exception& e) {
    m_errorCallback(e.what());
    SetState(State::Error);
  }
}
Example #3
0
void Connection::handleError(const boost::system::error_code& error)
{
    if(error != asio::error::operation_aborted) {
        m_error = error;
        if(m_errorCallback)
            m_errorCallback(error);
        if(m_connected || m_connecting)
            close();
    }
}
task<bool> SandboxJSExecutor::ConnectAsync(std::shared_ptr<SandboxEndpoint> endpoint,
    const std::function<void(std::string)>& errorCallback) {
  m_errorCallback = std::move(errorCallback);
  auto t = task_from_result();

  return t.then([=]() -> bool {
    int retryCount = ConnectRetryCount;
    while (true) {
      try {
        cancellation_token_source timer_cts;
        auto timeoutT = create_delayed_task(std::chrono::milliseconds(ConnectTimeoutMilliseconds), [=]() -> string {
          throw std::runtime_error("timeout");
        }, timer_cts.get_token());

        if (!IsConnected()) {
          try {
            m_sandboxEndpoint = nullptr;
          }
          catch (std::exception& /*e*/) {
            // Don't care what happens with the old client at this point
          }

          // TODO: Pass as param
          m_sandboxEndpoint = endpoint;

          m_sandboxEndpoint->RegisterReplyHandler([this](int64_t replyId) {
            OnReplyMessage(replyId);
          });

          m_sandboxEndpoint->RegisterNativeModuleCallHandler([this](folly::dynamic&& calls) {
            OnNativeModuleCallMessage(std::move(calls));
          });

          if (m_sandboxEndpoint->Start(EndpointType::Host))
          {
            SetState(State::Connected);
            timer_cts.cancel();
          }
        } else {
          PrepareJavaScriptRuntimeAsync().then([=](bool success) {
            if (success) {
              SetState(State::Running);
              timer_cts.cancel();
            } else {
              SetState(State::Error);
            }
          });
        }

        auto status = timeoutT.wait();

        if (status != canceled) {
          throw new std::exception("Timeout");
        }

        if (IsRunning()) {
          return true;
        }
      }
      catch (std::exception& /*e*/) {
        retryCount--;
        if (retryCount == 0) {
          m_errorCallback(IsConnected() ? "Timeout: preparing JS runtime" : "Timeout: Failed to connect to dev server");
          SetState(State::Error);
          return false;
        }
      }
    }
  });
}