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:
Andy Street
2016-07-21 09:55:09 +02:00
committed by Mike Grabowski
parent 926d6f3704
commit 843ef1a5da
2 changed files with 29 additions and 30 deletions
+27 -30
View File
@@ -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.