Permalink
Browse files

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
  • Loading branch information...
1 parent 7b718b0 commit 6d3c7b8a4c1d1a0552a21cfabe03a8d1f344d1ed @astreet astreet committed with Facebook Github Bot 7 Jul 11, 2016
Showing with 29 additions and 30 deletions.
  1. +27 −30 ReactAndroid/src/main/jni/react/JSCExecutor.cpp
  2. +2 −0 ReactAndroid/src/main/jni/react/JSCExecutor.h
@@ -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 @@ class JSCExecutor : public JSExecutor {
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.

0 comments on commit 6d3c7b8

Please sign in to comment.