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:
parent
ca1caf2713
commit
6ec5b953cb
|
@ -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(
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
@ -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);
|
||||
|
||||
} }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue