Fix 'Unexpected EOF' in old bridge
Summary: This is caused by receiving \u2028/2029 in callbacks/function calls. The correct solution is to not evaluate these strings as scripts but instead parse them as json and pass them through the JSC API. Reviewed By: lexs Differential Revision: D3543098 fbshipit-source-id: 4d8acce1d510bb17361d32103d4738fc0208b0a8
This commit is contained in:
parent
7b718b03eb
commit
6d3c7b8a4c
|
@ -68,25 +68,6 @@ static JSValueRef nativeInjectHMRUpdate(
|
|||
const JSValueRef arguments[],
|
||||
JSValueRef *exception);
|
||||
|
||||
static std::string executeJSCallWithJSC(
|
||||
JSGlobalContextRef ctx,
|
||||
const std::string& methodName,
|
||||
const std::vector<folly::dynamic>& arguments) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceSection s(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE, "JSCExecutor.executeJSCall",
|
||||
"method", methodName);
|
||||
#endif
|
||||
|
||||
// Evaluate script with JSC
|
||||
folly::dynamic jsonArgs(arguments.begin(), arguments.end());
|
||||
auto js = folly::to<std::string>(
|
||||
"__fbBatchedBridge.", methodName, ".apply(null, ",
|
||||
folly::toJson(jsonArgs), ")");
|
||||
auto result = evaluateScript(ctx, String(js.c_str()), nullptr);
|
||||
return Value(ctx, result).toJSONString();
|
||||
}
|
||||
|
||||
std::unique_ptr<JSExecutor> JSCExecutorFactory::createJSExecutor(Bridge *bridge) {
|
||||
return std::unique_ptr<JSExecutor>(new JSCExecutor(bridge, cacheDir_, m_jscConfig));
|
||||
}
|
||||
|
@ -202,6 +183,8 @@ void JSCExecutor::terminateOnJSVMThread() {
|
|||
|
||||
m_batchedBridge.reset();
|
||||
m_flushedQueueObj.reset();
|
||||
m_callFunctionObj.reset();
|
||||
m_invokeCallbackObj.reset();
|
||||
|
||||
s_globalContextRefToJSCExecutor.erase(m_context);
|
||||
JSGlobalContextRelease(m_context);
|
||||
|
@ -266,6 +249,8 @@ bool JSCExecutor::ensureBatchedBridgeObject() {
|
|||
}
|
||||
m_batchedBridge = folly::make_unique<Object>(batchedBridgeValue.asObject());
|
||||
m_flushedQueueObj = folly::make_unique<Object>(m_batchedBridge->getProperty("flushedQueue").asObject());
|
||||
m_callFunctionObj = folly::make_unique<Object>(m_batchedBridge->getProperty("callFunctionReturnFlushedQueue").asObject());
|
||||
m_invokeCallbackObj = folly::make_unique<Object>(m_batchedBridge->getProperty("invokeCallbackAndReturnFlushedQueue").asObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -290,6 +275,10 @@ void JSCExecutor::flush() {
|
|||
}
|
||||
|
||||
void JSCExecutor::callFunction(const std::string& moduleId, const std::string& methodId, const folly::dynamic& arguments) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "JSCExecutor.callFunction");
|
||||
#endif
|
||||
|
||||
if (!ensureBatchedBridgeObject()) {
|
||||
throwJSExecutionException(
|
||||
"Couldn't call JS module %s, method %s: bridge configuration isn't available. This "
|
||||
|
@ -298,27 +287,35 @@ void JSCExecutor::callFunction(const std::string& moduleId, const std::string& m
|
|||
methodId.c_str());
|
||||
}
|
||||
|
||||
std::vector<folly::dynamic> call {
|
||||
moduleId,
|
||||
methodId,
|
||||
std::move(arguments),
|
||||
String argsString = String(folly::toJson(std::move(arguments)).c_str());
|
||||
String moduleIdStr(moduleId.c_str());
|
||||
String methodIdStr(methodId.c_str());
|
||||
JSValueRef args[] = {
|
||||
JSValueMakeString(m_context, moduleIdStr),
|
||||
JSValueMakeString(m_context, methodIdStr),
|
||||
Value::fromJSON(m_context, argsString)
|
||||
};
|
||||
std::string calls = executeJSCallWithJSC(m_context, "callFunctionReturnFlushedQueue", std::move(call));
|
||||
m_bridge->callNativeModules(*this, calls, true);
|
||||
auto result = m_callFunctionObj->callAsFunction(3, args);
|
||||
m_bridge->callNativeModules(*this, result.toJSONString(), true);
|
||||
}
|
||||
|
||||
void JSCExecutor::invokeCallback(const double callbackId, const folly::dynamic& arguments) {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "JSCExecutor.invokeCallback");
|
||||
#endif
|
||||
|
||||
if (!ensureBatchedBridgeObject()) {
|
||||
throwJSExecutionException(
|
||||
"Couldn't invoke JS callback %d: bridge configuration isn't available. This shouldn't be possible. Congratulations.", (int) callbackId);
|
||||
}
|
||||
|
||||
std::vector<folly::dynamic> call {
|
||||
(double) callbackId,
|
||||
std::move(arguments)
|
||||
String argsString = String(folly::toJson(std::move(arguments)).c_str());
|
||||
JSValueRef args[] = {
|
||||
JSValueMakeNumber(m_context, callbackId),
|
||||
Value::fromJSON(m_context, argsString)
|
||||
};
|
||||
std::string calls = executeJSCallWithJSC(m_context, "invokeCallbackAndReturnFlushedQueue", std::move(call));
|
||||
m_bridge->callNativeModules(*this, calls, true);
|
||||
auto result = m_invokeCallbackObj->callAsFunction(2, args);
|
||||
m_bridge->callNativeModules(*this, result.toJSONString(), true);
|
||||
}
|
||||
|
||||
void JSCExecutor::setGlobalVariable(const std::string& propName, const std::string& jsonValue) {
|
||||
|
|
|
@ -91,6 +91,8 @@ private:
|
|||
folly::dynamic m_jscConfig;
|
||||
std::unique_ptr<Object> m_batchedBridge;
|
||||
std::unique_ptr<Object> m_flushedQueueObj;
|
||||
std::unique_ptr<Object> m_callFunctionObj;
|
||||
std::unique_ptr<Object> m_invokeCallbackObj;
|
||||
|
||||
/**
|
||||
* WebWorker constructor. Must be invoked from thread this Executor will run on.
|
||||
|
|
Loading…
Reference in New Issue