Red box c++ exceptions thrown while executing sync hooks

Summary: Also adds support for creating JS Error objects. When we clean up the way global functions are installed on JSC, we'll be able to use this pattern to auto-catch all c++ exceptions at this level.

Reviewed By: lexs

Differential Revision: D3276663

fbshipit-source-id: bf3561690013019a25e2be5a4d1b69ba9e002c72
This commit is contained in:
Andy Street 2016-05-10 05:02:56 -07:00 committed by Facebook Github Bot 3
parent ca1caf2713
commit 6ec5b953cb
5 changed files with 52 additions and 6 deletions

View File

@ -628,14 +628,19 @@ JSValueRef JSCExecutor::nativeCallSyncHook(
return JSValueMakeUndefined(ctx);
}
MethodCallResult result = executor->m_bridge->callSerializableNativeHook(
moduleId,
methodId,
argsJson);
if (result.isUndefined) {
try {
MethodCallResult result = executor->m_bridge->callSerializableNativeHook(
moduleId,
methodId,
argsJson);
if (result.isUndefined) {
return JSValueMakeUndefined(ctx);
}
return Value::fromJSON(ctx, String(folly::toJson(result.result).c_str()));
} catch (...) {
*exception = translatePendingCppExceptionToJSError(ctx, "nativeCallSyncHook");
return JSValueMakeUndefined(ctx);
}
return Value::fromJSON(ctx, String(folly::toJson(result.result).c_str()));
}
static JSValueRef nativeInjectHMRUpdate(

View File

@ -52,4 +52,32 @@ JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef
return result;
}
JSValueRef makeJSError(JSContextRef ctx, const char *error) {
JSValueRef nestedException = nullptr;
JSValueRef args[] = { Value(ctx, String(error)) };
JSObjectRef errorObj = JSObjectMakeError(ctx, 1, args, &nestedException);
if (nestedException != nullptr) {
return std::move(args[0]);
}
return errorObj;
}
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation) {
std::ostringstream msg;
try {
throw;
} catch (const std::bad_alloc& ex) {
throw; // We probably shouldn't try to handle this in JS
} catch (const std::exception& ex) {
msg << "C++ Exception in '" << exceptionLocation << "': " << ex.what();
return makeJSError(ctx, msg.str().c_str());
} catch (const char* ex) {
msg << "C++ Exception (thrown as a char*) in '" << exceptionLocation << "': " << ex;
return makeJSError(ctx, msg.str().c_str());
} catch (...) {
msg << "Unknown C++ Exception in '" << exceptionLocation << "'";
return makeJSError(ctx, msg.str().c_str());
}
}
} }

View File

@ -9,6 +9,8 @@
#include <stdexcept>
#include <algorithm>
#include "Value.h"
namespace facebook {
namespace react {
@ -43,4 +45,8 @@ JSValueRef evaluateScript(
JSStringRef script,
JSStringRef sourceURL);
JSValueRef makeJSError(JSContextRef ctx, const char *error);
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation);
} }

View File

@ -13,6 +13,12 @@ Value::Value(JSContextRef context, JSValueRef value) :
{
}
Value::Value(JSContextRef context, JSStringRef str) :
m_context(context),
m_value(JSValueMakeString(context, str))
{
}
Value::Value(Value&& other) :
m_context(other.m_context),
m_value(other.m_value)

View File

@ -171,6 +171,7 @@ private:
class Value : public noncopyable {
public:
Value(JSContextRef context, JSValueRef value);
Value(JSContextRef context, JSStringRef value);
Value(Value&&);
operator JSValueRef() const {