Add API for sync function calls

Reviewed By: javache

Differential Revision: D3897526

fbshipit-source-id: cadead316996ca7c1dd2b0d60d87945f5452640c
This commit is contained in:
Marc Horowitz 2016-09-26 16:01:43 -07:00 committed by Facebook Github Bot 7
parent 6071e8ca2c
commit d7a2d3a957
4 changed files with 66 additions and 1 deletions

View File

@ -55,6 +55,11 @@ class Instance {
void callJSCallback(ExecutorToken token, uint64_t callbackId, folly::dynamic&& params);
MethodCallResult callSerializableNativeHook(ExecutorToken token, unsigned int moduleId,
unsigned int methodId, folly::dynamic&& args);
// This method is experimental, and may be modified or removed.
template <typename T>
Value callFunctionSync(const std::string& module, const std::string& method, T&& args) {
return nativeToJsBridge_->callFunctionSync(module, method, std::forward<T>(args));
}
ExecutorToken getMainExecutorToken();
void handleMemoryPressureUiHidden();

View File

@ -118,7 +118,6 @@ JSCExecutor::JSCExecutor(std::shared_ptr<ExecutorDelegate> delegate,
folly::dynamic::object
("remoteModuleConfig", std::move(nativeModuleConfig));
SystraceSection t("setGlobalVariable");
setGlobalVariable(
"__fbBatchedBridgeConfig",
@ -344,6 +343,7 @@ void JSCExecutor::bindBridge() throw(JSException) {
m_callFunctionReturnFlushedQueueJS = batchedBridge.getProperty("callFunctionReturnFlushedQueue").asObject();
m_invokeCallbackAndReturnFlushedQueueJS = batchedBridge.getProperty("invokeCallbackAndReturnFlushedQueue").asObject();
m_flushedQueueJS = batchedBridge.getProperty("flushedQueue").asObject();
m_callFunctionReturnResultAndFlushedQueueJS = batchedBridge.getProperty("callFunctionReturnResultAndFlushedQueue").asObject();
}
void JSCExecutor::callNativeModules(Value&& value) {
@ -405,6 +405,26 @@ void JSCExecutor::invokeCallback(const double callbackId, const folly::dynamic&
callNativeModules(std::move(result));
}
Value JSCExecutor::callFunctionSyncWithValue(
const std::string& module, const std::string& method, Value args) {
SystraceSection s("JSCExecutor::callFunction");
Object result = m_callFunctionReturnResultAndFlushedQueueJS->callAsFunction({
Value(m_context, String::createExpectingAscii(module)),
Value(m_context, String::createExpectingAscii(method)),
std::move(args),
}).asObject();
Value length = result.getProperty("length");
if (!length.isNumber() || length.asInteger() != 2) {
std::runtime_error("Return value of a callFunction must be an array of size 2");
}
callNativeModules(result.getPropertyAtIndex(1));
return result.getPropertyAtIndex(0);
}
void JSCExecutor::setGlobalVariable(std::string propName, std::unique_ptr<const JSBigString> jsonValue) {
try {
SystraceSection s("JSCExecutor.setGlobalVariable",

View File

@ -74,6 +74,12 @@ public:
virtual void invokeCallback(
const double callbackId,
const folly::dynamic& arguments) override;
template <typename T>
Value callFunctionSync(
const std::string& module, const std::string& method, T&& args) {
return callFunctionSyncWithValue(module, method,
toValue(m_context, std::forward<T>(args)));
}
virtual void setGlobalVariable(
std::string propName,
std::unique_ptr<const JSBigString> jsonValue) override;
@ -101,6 +107,7 @@ private:
folly::Optional<Object> m_invokeCallbackAndReturnFlushedQueueJS;
folly::Optional<Object> m_callFunctionReturnFlushedQueueJS;
folly::Optional<Object> m_flushedQueueJS;
folly::Optional<Object> m_callFunctionReturnResultAndFlushedQueueJS;
/**
* WebWorker constructor. Must be invoked from thread this Executor will run on.
@ -115,6 +122,9 @@ private:
const folly::dynamic& jscConfig);
void initOnJSVMThread() throw(JSException);
// This method is experimental, and may be modified or removed.
Value callFunctionSyncWithValue(
const std::string& module, const std::string& method, Value value);
void terminateOnJSVMThread();
void bindBridge() throw(JSException);
void callNativeModules(Value&&);

View File

@ -11,6 +11,7 @@
#include "Executor.h"
#include "ExecutorToken.h"
#include "JSCExecutor.h"
#include "JSModulesUnbundle.h"
#include "MessageQueueThread.h"
#include "MethodCall.h"
@ -80,6 +81,35 @@ public:
*/
void invokeCallback(ExecutorToken executorToken, double callbackId, folly::dynamic&& args);
/**
* Executes a JS method on the given executor synchronously, returning its
* return value. JSException will be thrown if JS throws an exception;
* another standard exception may be thrown for C++ bridge failures, or if
* the executor is not capable of synchronous calls.
*
* This method is experimental, and may be modified or removed.
*
* loadApplicationScriptSync() must be called and finished executing
* before callFunctionSync().
*/
template <typename T>
Value callFunctionSync(const std::string& module, const std::string& method, T&& args) {
if (*m_destroyed) {
throw std::logic_error(
folly::to<std::string>("Synchronous call to ", module, ".", method,
" after bridge is destroyed"));
}
JSCExecutor *jscExecutor = dynamic_cast<JSCExecutor*>(m_mainExecutor);
if (!jscExecutor) {
throw std::invalid_argument(
folly::to<std::string>("Executor type ", typeid(*m_mainExecutor).name(),
" does not support synchronous calls"));
}
return jscExecutor->callFunctionSync(module, method, std::forward<T>(args));
}
/**
* Starts the JS application. If unbundle is non-null, then it is
* used to fetch JavaScript modules as individual scripts.