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); return JSValueMakeUndefined(ctx);
} }
MethodCallResult result = executor->m_bridge->callSerializableNativeHook( try {
moduleId, MethodCallResult result = executor->m_bridge->callSerializableNativeHook(
methodId, moduleId,
argsJson); methodId,
if (result.isUndefined) { 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 JSValueMakeUndefined(ctx);
} }
return Value::fromJSON(ctx, String(folly::toJson(result.result).c_str()));
} }
static JSValueRef nativeInjectHMRUpdate( static JSValueRef nativeInjectHMRUpdate(

View File

@ -52,4 +52,32 @@ JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef
return result; 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 <stdexcept>
#include <algorithm> #include <algorithm>
#include "Value.h"
namespace facebook { namespace facebook {
namespace react { namespace react {
@ -43,4 +45,8 @@ JSValueRef evaluateScript(
JSStringRef script, JSStringRef script,
JSStringRef sourceURL); 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) : Value::Value(Value&& other) :
m_context(other.m_context), m_context(other.m_context),
m_value(other.m_value) m_value(other.m_value)

View File

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