Add some more helper methods to Value

Reviewed By: mhorowitz

Differential Revision: D4197278

fbshipit-source-id: 9a538ff2747d32a54d42627a9f78e4a348dce639
This commit is contained in:
Pieter De Baets 2016-11-18 06:25:24 -08:00 committed by Facebook Github Bot
parent 1604f10889
commit 674d86cdcb
13 changed files with 121 additions and 133 deletions

View File

@ -73,12 +73,11 @@ inline JSObjectCallAsFunctionCallback exceptionWrapMethod() {
const JSValueRef arguments[], const JSValueRef arguments[],
JSValueRef *exception) { JSValueRef *exception) {
try { try {
auto globalObj = JSContextGetGlobalObject(ctx); auto executor = Object::getGlobalObject(ctx).getPrivate<JSCExecutor>();
auto executor = static_cast<JSCExecutor*>(JSObjectGetPrivate(globalObj));
return (executor->*method)(argumentCount, arguments); return (executor->*method)(argumentCount, arguments);
} catch (...) { } catch (...) {
*exception = translatePendingCppExceptionToJSError(ctx, function); *exception = translatePendingCppExceptionToJSError(ctx, function);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
} }
}; };
@ -95,12 +94,11 @@ inline JSObjectGetPropertyCallback exceptionWrapMethod() {
JSStringRef propertyName, JSStringRef propertyName,
JSValueRef *exception) { JSValueRef *exception) {
try { try {
auto globalObj = JSContextGetGlobalObject(ctx); auto executor = Object::getGlobalObject(ctx).getPrivate<JSCExecutor>();
auto executor = static_cast<JSCExecutor*>(JSObjectGetPrivate(globalObj));
return (executor->*method)(object, propertyName); return (executor->*method)(object, propertyName);
} catch (...) { } catch (...) {
*exception = translatePendingCppExceptionToJSError(ctx, object); *exception = translatePendingCppExceptionToJSError(ctx, object);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
} }
}; };
@ -121,7 +119,7 @@ static JSValueRef nativeInjectHMRUpdate(
String execJSString = Value(ctx, arguments[0]).toString(); String execJSString = Value(ctx, arguments[0]).toString();
String jsURL = Value(ctx, arguments[1]).toString(); String jsURL = Value(ctx, arguments[1]).toString();
evaluateScript(ctx, execJSString, jsURL); evaluateScript(ctx, execJSString, jsURL);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
#endif #endif
@ -235,7 +233,7 @@ void JSCExecutor::initOnJSVMThread() throw(JSException) {
JSClassRelease(globalClass); JSClassRelease(globalClass);
// Add a pointer to ourselves so we can retrieve it later in our hooks // Add a pointer to ourselves so we can retrieve it later in our hooks
JSObjectSetPrivate(JSContextGetGlobalObject(m_context), this); Object::getGlobalObject(m_context).setPrivate(this);
#ifdef WITH_INSPECTOR #ifdef WITH_INSPECTOR
Inspector::instance().registerGlobalContext("main", m_context); Inspector::instance().registerGlobalContext("main", m_context);
@ -493,7 +491,7 @@ void JSCExecutor::invokeCallback(const double callbackId, const folly::dynamic&
auto result = [&] { auto result = [&] {
try { try {
return m_invokeCallbackAndReturnFlushedQueueJS->callAsFunction({ return m_invokeCallbackAndReturnFlushedQueueJS->callAsFunction({
JSValueMakeNumber(m_context, callbackId), Value::makeNumber(m_context, callbackId),
Value::fromDynamic(m_context, std::move(arguments)) Value::fromDynamic(m_context, std::move(arguments))
}); });
} catch (...) { } catch (...) {
@ -530,13 +528,8 @@ void JSCExecutor::setGlobalVariable(std::string propName, std::unique_ptr<const
SystraceSection s("JSCExecutor.setGlobalVariable", SystraceSection s("JSCExecutor.setGlobalVariable",
"propName", propName); "propName", propName);
auto globalObject = JSContextGetGlobalObject(m_context); auto valueToInject = Value::fromJSON(m_context, jsStringFromBigString(*jsonValue));
String jsPropertyName(propName.c_str()); Object::getGlobalObject(m_context).setProperty(propName.c_str(), valueToInject);
String jsValueJSON = jsStringFromBigString(*jsonValue);
auto valueToInject = JSValueMakeFromJSONString(m_context, jsValueJSON);
JSObjectSetProperty(m_context, globalObject, jsPropertyName, valueToInject, 0, NULL);
} catch (...) { } catch (...) {
std::throw_with_nested(std::runtime_error("Error setting global variable: " + propName)); std::throw_with_nested(std::runtime_error("Error setting global variable: " + propName));
} }
@ -736,7 +729,7 @@ JSValueRef JSCExecutor::nativePostMessage(
JSValueRef msg = arguments[0]; JSValueRef msg = arguments[0];
postMessageToOwner(msg); postMessageToOwner(msg);
return JSValueMakeUndefined(m_context); return Value::makeUndefined(m_context);
} }
JSValueRef JSCExecutor::nativeRequire( JSValueRef JSCExecutor::nativeRequire(
@ -754,7 +747,7 @@ JSValueRef JSCExecutor::nativeRequire(
} }
loadModule(moduleId); loadModule(moduleId);
return JSValueMakeUndefined(m_context); return Value::makeUndefined(m_context);
} }
JSValueRef JSCExecutor::nativeFlushQueueImmediate( JSValueRef JSCExecutor::nativeFlushQueueImmediate(
@ -765,7 +758,7 @@ JSValueRef JSCExecutor::nativeFlushQueueImmediate(
} }
flushQueueImmediate(Value(m_context, arguments[0])); flushQueueImmediate(Value(m_context, arguments[0]));
return JSValueMakeUndefined(m_context); return Value::makeUndefined(m_context);
} }
JSValueRef JSCExecutor::nativeStartWorker( JSValueRef JSCExecutor::nativeStartWorker(
@ -782,7 +775,7 @@ JSValueRef JSCExecutor::nativeStartWorker(
int workerId = addWebWorker(scriptFile, worker, globalObj); int workerId = addWebWorker(scriptFile, worker, globalObj);
return JSValueMakeNumber(m_context, workerId); return Value::makeNumber(m_context, workerId);
} }
JSValueRef JSCExecutor::nativePostMessageToWorker( JSValueRef JSCExecutor::nativePostMessageToWorker(
@ -799,7 +792,7 @@ JSValueRef JSCExecutor::nativePostMessageToWorker(
postMessageToOwnedWebWorker((int) workerDouble, arguments[1]); postMessageToOwnedWebWorker((int) workerDouble, arguments[1]);
return JSValueMakeUndefined(m_context); return Value::makeUndefined(m_context);
} }
JSValueRef JSCExecutor::nativeTerminateWorker( JSValueRef JSCExecutor::nativeTerminateWorker(
@ -816,7 +809,7 @@ JSValueRef JSCExecutor::nativeTerminateWorker(
terminateOwnedWebWorker((int) workerDouble); terminateOwnedWebWorker((int) workerDouble);
return JSValueMakeUndefined(m_context); return Value::makeUndefined(m_context);
} }
JSValueRef JSCExecutor::nativeCallSyncHook( JSValueRef JSCExecutor::nativeCallSyncHook(
@ -836,7 +829,7 @@ JSValueRef JSCExecutor::nativeCallSyncHook(
methodId, methodId,
argsJson); argsJson);
if (result.isUndefined) { if (result.isUndefined) {
return JSValueMakeUndefined(m_context); return Value::makeUndefined(m_context);
} }
return Value::fromDynamic(m_context, result.result); return Value::fromDynamic(m_context, result.result);
} }

View File

@ -11,6 +11,8 @@
#include <jschelpers/Value.h> #include <jschelpers/Value.h>
#include "JSCLegacyProfiler.h" #include "JSCLegacyProfiler.h"
using namespace facebook::react;
static JSValueRef nativeProfilerStart( static JSValueRef nativeProfilerStart(
JSContextRef ctx, JSContextRef ctx,
JSObjectRef function, JSObjectRef function,
@ -20,11 +22,11 @@ static JSValueRef nativeProfilerStart(
JSValueRef* exception) { JSValueRef* exception) {
if (argumentCount < 1) { if (argumentCount < 1) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"nativeProfilerStart: requires at least 1 argument"); "nativeProfilerStart: requires at least 1 argument");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
JSStringRef title = JSValueToStringCopy(ctx, arguments[0], exception); JSStringRef title = JSValueToStringCopy(ctx, arguments[0], exception);
@ -34,7 +36,7 @@ static JSValueRef nativeProfilerStart(
JSStartProfiling(ctx, title); JSStartProfiling(ctx, title);
#endif #endif
JSStringRelease(title); JSStringRelease(title);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
static JSValueRef nativeProfilerEnd( static JSValueRef nativeProfilerEnd(
@ -46,11 +48,11 @@ static JSValueRef nativeProfilerEnd(
JSValueRef* exception) { JSValueRef* exception) {
if (argumentCount < 1) { if (argumentCount < 1) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"nativeProfilerEnd: requires at least 1 argument"); "nativeProfilerEnd: requires at least 1 argument");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
std::string writeLocation("/sdcard/"); std::string writeLocation("/sdcard/");
@ -64,7 +66,7 @@ static JSValueRef nativeProfilerEnd(
JSStringRef title = JSValueToStringCopy(ctx, arguments[0], exception); JSStringRef title = JSValueToStringCopy(ctx, arguments[0], exception);
JSEndProfilingAndRender(ctx, title, writeLocation.c_str()); JSEndProfilingAndRender(ctx, title, writeLocation.c_str());
JSStringRelease(title); JSStringRelease(title);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
namespace facebook { namespace facebook {

View File

@ -10,11 +10,14 @@
#include <fbsystrace.h> #include <fbsystrace.h>
#include <jschelpers/JSCHelpers.h> #include <jschelpers/JSCHelpers.h>
#include <jschelpers/Value.h>
#include "JSCTracing.h" #include "JSCTracing.h"
static const char *ENABLED_FBSYSTRACE_PROFILE_NAME = "__fbsystrace__"; static const char *ENABLED_FBSYSTRACE_PROFILE_NAME = "__fbsystrace__";
using namespace facebook::react;
static JSValueRef nativeTraceBeginLegacy( static JSValueRef nativeTraceBeginLegacy(
JSContextRef ctx, JSContextRef ctx,
JSObjectRef function, JSObjectRef function,
@ -23,9 +26,9 @@ static JSValueRef nativeTraceBeginLegacy(
const JSValueRef arguments[], const JSValueRef arguments[],
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_LIKELY(argumentCount >= 1)) { if (FBSYSTRACE_LIKELY(argumentCount >= 1)) {
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
} }
@ -37,7 +40,7 @@ static JSValueRef nativeTraceBeginLegacy(
#endif #endif
JSStringRelease(title); JSStringRelease(title);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
static JSValueRef nativeTraceEndLegacy( static JSValueRef nativeTraceEndLegacy(
@ -48,9 +51,9 @@ static JSValueRef nativeTraceEndLegacy(
const JSValueRef arguments[], const JSValueRef arguments[],
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_LIKELY(argumentCount >= 1)) { if (FBSYSTRACE_LIKELY(argumentCount >= 1)) {
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
} }
@ -58,7 +61,7 @@ static JSValueRef nativeTraceEndLegacy(
JSEndProfiling(ctx, title); JSEndProfiling(ctx, title);
JSStringRelease(title); JSStringRelease(title);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
namespace facebook { namespace facebook {

View File

@ -10,6 +10,8 @@
#include <jschelpers/JSCHelpers.h> #include <jschelpers/JSCHelpers.h>
#include <jschelpers/Value.h> #include <jschelpers/Value.h>
using namespace facebook::react;
static JSValueRef nativeCaptureHeap( static JSValueRef nativeCaptureHeap(
JSContextRef ctx, JSContextRef ctx,
JSObjectRef function, JSObjectRef function,
@ -19,18 +21,18 @@ static JSValueRef nativeCaptureHeap(
JSValueRef* exception) { JSValueRef* exception) {
if (argumentCount < 1) { if (argumentCount < 1) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"nativeCaptureHeap requires the path to save the capture"); "nativeCaptureHeap requires the path to save the capture");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
JSStringRef outputFilename = JSValueToStringCopy(ctx, arguments[0], exception); JSStringRef outputFilename = JSValueToStringCopy(ctx, arguments[0], exception);
std::string finalFilename = facebook::react::String::ref(outputFilename).str(); std::string finalFilename = facebook::react::String::ref(outputFilename).str();
JSCaptureHeap(ctx, finalFilename.c_str(), exception); JSCaptureHeap(ctx, finalFilename.c_str(), exception);
JSStringRelease(outputFilename); JSStringRelease(outputFilename);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
#endif // WITH_FB_MEMORY_PROFILING #endif // WITH_FB_MEMORY_PROFILING

View File

@ -20,7 +20,7 @@ JSValueRef JSCNativeModules::getModule(JSContextRef context, JSStringRef jsName)
auto module = createModule(moduleName, context); auto module = createModule(moduleName, context);
if (!module.hasValue()) { if (!module.hasValue()) {
return JSValueMakeUndefined(context); return Value::makeUndefined(context);
} }
// Protect since we'll be holding on to this value, even though JS may not // Protect since we'll be holding on to this value, even though JS may not
@ -53,7 +53,7 @@ folly::Optional<Object> JSCNativeModules::createModule(const std::string& name,
Value moduleInfo = m_genNativeModuleJS->callAsFunction({ Value moduleInfo = m_genNativeModuleJS->callAsFunction({
Value::fromDynamic(context, result->config), Value::fromDynamic(context, result->config),
JSValueMakeNumber(context, result->index) Value::makeNumber(context, result->index)
}); });
CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null"; CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null";

View File

@ -10,6 +10,8 @@
#include <jschelpers/JSCHelpers.h> #include <jschelpers/JSCHelpers.h>
#include <jschelpers/Value.h> #include <jschelpers/Value.h>
using namespace facebook::react;
static JSValueRef nativeGetHeapStats( static JSValueRef nativeGetHeapStats(
JSContextRef ctx, JSContextRef ctx,
JSObjectRef function, JSObjectRef function,
@ -21,10 +23,10 @@ static JSValueRef nativeGetHeapStats(
JSGetHeapStats(ctx, &heapStats); JSGetHeapStats(ctx, &heapStats);
auto result = facebook::react::Object::create(ctx); auto result = facebook::react::Object::create(ctx);
result.setProperty("size", {ctx, JSValueMakeNumber(ctx, heapStats.size)}); result.setProperty("size", {ctx, Value::makeNumber(ctx, heapStats.size)});
result.setProperty("extra_size", {ctx, JSValueMakeNumber(ctx, heapStats.extraSize)}); result.setProperty("extra_size", {ctx, Value::makeNumber(ctx, heapStats.extraSize)});
result.setProperty("capacity", {ctx, JSValueMakeNumber(ctx, heapStats.capacity)}); result.setProperty("capacity", {ctx, Value::makeNumber(ctx, heapStats.capacity)});
result.setProperty("object_count", {ctx, JSValueMakeNumber(ctx, heapStats.objectCount)}); result.setProperty("object_count", {ctx, Value::makeNumber(ctx, heapStats.objectCount)});
return (JSObjectRef) result; return (JSObjectRef) result;
} }
@ -42,10 +44,10 @@ static JSValueRef nativeGetGCStats(
auto result = facebook::react::Object::create(ctx); auto result = facebook::react::Object::create(ctx);
result.setProperty( result.setProperty(
"last_full_gc_length", "last_full_gc_length",
{ctx, JSValueMakeNumber(ctx, gcStats.lastFullGCLength)}); {ctx, Value::makeNumber(ctx, gcStats.lastFullGCLength)});
result.setProperty( result.setProperty(
"last_eden_gc_length", "last_eden_gc_length",
{ctx, JSValueMakeNumber(ctx, gcStats.lastEdenGCLength)}); {ctx, Value::makeNumber(ctx, gcStats.lastEdenGCLength)});
return (JSObjectRef) result; return (JSObjectRef) result;
} }

View File

@ -10,8 +10,10 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <jschelpers/JSCHelpers.h> #include <jschelpers/JSCHelpers.h>
#include <jschelpers/Value.h>
using std::min; using std::min;
using namespace facebook::react;
static int64_t int64FromJSValue( static int64_t int64FromJSValue(
JSContextRef ctx, JSContextRef ctx,
@ -85,16 +87,16 @@ static JSValueRef nativeTraceBeginSection(
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_UNLIKELY(argumentCount < 2)) { if (FBSYSTRACE_UNLIKELY(argumentCount < 2)) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"nativeTraceBeginSection: requires at least 2 arguments"); "nativeTraceBeginSection: requires at least 2 arguments");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH];
@ -113,7 +115,7 @@ static JSValueRef nativeTraceBeginSection(
flush: flush:
fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1));
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
static JSValueRef nativeTraceEndSection( static JSValueRef nativeTraceEndSection(
@ -125,16 +127,16 @@ static JSValueRef nativeTraceEndSection(
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_UNLIKELY(argumentCount < 1)) { if (FBSYSTRACE_UNLIKELY(argumentCount < 1)) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"nativeTraceEndSection: requires at least 1 argument"); "nativeTraceEndSection: requires at least 1 argument");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
if (FBSYSTRACE_LIKELY(argumentCount == 1)) { if (FBSYSTRACE_LIKELY(argumentCount == 1)) {
@ -155,7 +157,7 @@ flush:
fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1));
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
static JSValueRef beginOrEndAsync( static JSValueRef beginOrEndAsync(
@ -169,16 +171,16 @@ static JSValueRef beginOrEndAsync(
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_UNLIKELY(argumentCount < 3)) { if (FBSYSTRACE_UNLIKELY(argumentCount < 3)) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"beginOrEndAsync: requires at least 3 arguments"); "beginOrEndAsync: requires at least 3 arguments");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH];
@ -219,7 +221,7 @@ static JSValueRef beginOrEndAsync(
flush: flush:
fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1));
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
static JSValueRef stageAsync( static JSValueRef stageAsync(
@ -232,16 +234,16 @@ static JSValueRef stageAsync(
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_UNLIKELY(argumentCount < 4)) { if (FBSYSTRACE_UNLIKELY(argumentCount < 4)) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"stageAsync: requires at least 4 arguments"); "stageAsync: requires at least 4 arguments");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH];
@ -260,7 +262,7 @@ static JSValueRef stageAsync(
fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1)); fbsystrace_trace_raw(buf, min(pos, sizeof(buf)-1));
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
static JSValueRef nativeTraceBeginAsyncSection( static JSValueRef nativeTraceBeginAsyncSection(
@ -378,16 +380,16 @@ static JSValueRef nativeTraceCounter(
JSValueRef* exception) { JSValueRef* exception) {
if (FBSYSTRACE_UNLIKELY(argumentCount < 3)) { if (FBSYSTRACE_UNLIKELY(argumentCount < 3)) {
if (exception) { if (exception) {
*exception = facebook::react::makeJSCException( *exception = Value::makeError(
ctx, ctx,
"nativeTraceCounter: requires at least 3 arguments"); "nativeTraceCounter: requires at least 3 arguments");
} }
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception); uint64_t tag = facebook::react::tracingTagFromJSValue(ctx, arguments[0], exception);
if (!fbsystrace_is_tracing(tag)) { if (!fbsystrace_is_tracing(tag)) {
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH]; char buf[FBSYSTRACE_MAX_MESSAGE_LENGTH];
@ -398,7 +400,7 @@ static JSValueRef nativeTraceCounter(
fbsystrace_counter(tag, buf, value); fbsystrace_counter(tag, buf, value);
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
namespace facebook { namespace facebook {
@ -411,9 +413,7 @@ uint64_t tracingTagFromJSValue(
// XXX validate that this is a lossless conversion. // XXX validate that this is a lossless conversion.
// XXX should we just have separate functions for bridge, infra, and apps, // XXX should we just have separate functions for bridge, infra, and apps,
// then drop this argument to save time? // then drop this argument to save time?
(void)exception; return static_cast<uint64_t>(Value(ctx, value).asNumber());
uint64_t tag = (uint64_t) JSValueToNumber(ctx, value, NULL);
return tag;
} }
void addNativeTracingHooks(JSGlobalContextRef ctx) { void addNativeTracingHooks(JSGlobalContextRef ctx) {

View File

@ -112,19 +112,17 @@ JSValueRef JSCWebWorker::nativePostMessage(
const JSValueRef arguments[], const JSValueRef arguments[],
JSValueRef *exception) { JSValueRef *exception) {
if (argumentCount != 1) { if (argumentCount != 1) {
*exception = makeJSCException(ctx, "postMessage got wrong number of arguments"); *exception = Value::makeError(ctx, "postMessage got wrong number of arguments");
return JSValueMakeUndefined(ctx); return Value::makeUndefined(ctx);
} }
JSValueRef msg = arguments[0]; JSValueRef msg = arguments[0];
JSCWebWorker *webWorker = s_globalContextRefToJSCWebWorker.at(JSContextGetGlobalContext(ctx)); JSCWebWorker *webWorker = s_globalContextRefToJSCWebWorker.at(JSContextGetGlobalContext(ctx));
if (webWorker->isTerminated()) { if (!webWorker->isTerminated()) {
return JSValueMakeUndefined(ctx); webWorker->postMessageToOwner(msg);
} }
webWorker->postMessageToOwner(msg); return Value::makeUndefined(ctx);
return JSValueMakeUndefined(ctx);
} }
/*static*/ /*static*/

View File

@ -28,8 +28,8 @@ static void prepare() {
TEST(Value, Undefined) { TEST(Value, Undefined) {
prepare(); prepare();
JSGlobalContextRef ctx = JSGlobalContextCreateInGroup(nullptr, nullptr); JSGlobalContextRef ctx = JSGlobalContextCreateInGroup(nullptr, nullptr);
Value v(ctx, JSValueMakeUndefined(ctx)); auto v = Value::makeUndefined(ctx);
auto s = react::String::adopt(JSValueToStringCopy(ctx, v, nullptr)); auto s = String::adopt(JSValueToStringCopy(ctx, v, nullptr));
EXPECT_EQ("undefined", s.str()); EXPECT_EQ("undefined", s.str());
JSGlobalContextRelease(ctx); JSGlobalContextRelease(ctx);
} }

View File

@ -55,18 +55,16 @@ JSObjectRef makeFunction(
JSContextRef ctx, JSContextRef ctx,
const char* name, const char* name,
JSFunction function) { JSFunction function) {
return makeFunction(ctx, JSStringCreateWithUTF8CString(name), std::move(function)); return makeFunction(ctx, String(name), std::move(function));
} }
void installGlobalFunction( void installGlobalFunction(
JSGlobalContextRef ctx, JSGlobalContextRef ctx,
const char* name, const char* name,
JSFunction function) { JSFunction function) {
auto jsName = JSStringCreateWithUTF8CString(name); auto jsName = String(name);
auto functionObj = makeFunction(ctx, jsName, std::move(function)); auto functionObj = makeFunction(ctx, jsName, std::move(function));
JSObjectRef globalObject = JSContextGetGlobalObject(ctx); Object::getGlobalObject(ctx).setProperty(jsName, Value(ctx, functionObj));
JSObjectSetProperty(ctx, globalObject, jsName, functionObj, 0, NULL);
JSStringRelease(jsName);
} }
JSObjectRef makeFunction( JSObjectRef makeFunction(
@ -81,12 +79,10 @@ void installGlobalFunction(
JSGlobalContextRef ctx, JSGlobalContextRef ctx,
const char* name, const char* name,
JSObjectCallAsFunctionCallback callback) { JSObjectCallAsFunctionCallback callback) {
JSStringRef jsName = JSStringCreateWithUTF8CString(name); String jsName(name);
JSObjectRef functionObj = JSObjectMakeFunctionWithCallback( JSObjectRef functionObj = JSObjectMakeFunctionWithCallback(
ctx, jsName, callback); ctx, jsName, callback);
JSObjectRef globalObject = JSContextGetGlobalObject(ctx); Object::getGlobalObject(ctx).setProperty(jsName, Value(ctx, functionObj));
JSObjectSetProperty(ctx, globalObject, jsName, functionObj, 0, NULL);
JSStringRelease(jsName);
} }
void installGlobalProxy( void installGlobalProxy(
@ -96,38 +92,22 @@ void installGlobalProxy(
JSClassDefinition proxyClassDefintion = kJSClassDefinitionEmpty; JSClassDefinition proxyClassDefintion = kJSClassDefinitionEmpty;
proxyClassDefintion.className = "_FBProxyClass"; proxyClassDefintion.className = "_FBProxyClass";
proxyClassDefintion.getProperty = callback; proxyClassDefintion.getProperty = callback;
JSClassRef proxyClass = JSClassCreate(&proxyClassDefintion); JSClassRef proxyClass = JSClassCreate(&proxyClassDefintion);
JSObjectRef proxyObj = JSObjectMake(ctx, proxyClass, nullptr); JSObjectRef proxyObj = JSObjectMake(ctx, proxyClass, nullptr);
JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
JSStringRef jsName = JSStringCreateWithUTF8CString(name);
JSObjectSetProperty(ctx, globalObject, jsName, proxyObj, 0, NULL);
JSStringRelease(jsName);
JSClassRelease(proxyClass); JSClassRelease(proxyClass);
Object::getGlobalObject(ctx).setProperty(name, Value(ctx, proxyObj));
} }
void removeGlobal(JSGlobalContextRef ctx, const char* name) { void removeGlobal(JSGlobalContextRef ctx, const char* name) {
JSStringRef jsName = JSStringCreateWithUTF8CString(name); Object::getGlobalObject(ctx).setProperty(name, Value::makeUndefined(ctx));
JSObjectRef globalObject = JSContextGetGlobalObject(ctx);
JSObjectSetProperty(ctx, globalObject, jsName, nullptr, 0, nullptr);
JSStringRelease(jsName);
}
JSValueRef makeJSCException(
JSContextRef ctx,
const char* exception_text) {
JSStringRef message = JSStringCreateWithUTF8CString(exception_text);
JSValueRef exceptionString = JSValueMakeString(ctx, message);
JSStringRelease(message);
return JSValueToObject(ctx, exceptionString, NULL);
} }
JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef source) { JSValueRef evaluateScript(JSContextRef context, JSStringRef script, JSStringRef source) {
#ifdef WITH_FBSYSTRACE #ifdef WITH_FBSYSTRACE
fbsystrace::FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "evaluateScript"); fbsystrace::FbSystraceSection s(TRACE_TAG_REACT_CXX_BRIDGE, "evaluateScript");
#endif #endif
JSValueRef exn, result; JSValueRef exn, result;
result = JSEvaluateScript(context, script, NULL, source, 0, &exn); result = JSEvaluateScript(context, script, NULL, source, 0, &exn);
if (result == nullptr) { if (result == nullptr) {
@ -149,7 +129,6 @@ JSValueRef evaluateSourceCode(JSContextRef context, JSSourceCodeRef source, JSSt
void formatAndThrowJSException(JSContextRef context, JSValueRef exn, JSStringRef source) { void formatAndThrowJSException(JSContextRef context, JSValueRef exn, JSStringRef source) {
Value exception = Value(context, exn); Value exception = Value(context, exn);
std::string exceptionText = exception.toString().str(); std::string exceptionText = exception.toString().str();
// The null/empty-ness of source tells us if the JS came from a // The null/empty-ness of source tells us if the JS came from a
@ -187,17 +166,6 @@ void formatAndThrowJSException(JSContextRef context, JSValueRef exn, JSStringRef
} }
} }
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) { JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation) {
std::ostringstream msg; std::ostringstream msg;
try { try {
@ -206,13 +174,13 @@ JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *e
throw; // We probably shouldn't try to handle this in JS throw; // We probably shouldn't try to handle this in JS
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
msg << "C++ Exception in '" << exceptionLocation << "': " << ex.what(); msg << "C++ Exception in '" << exceptionLocation << "': " << ex.what();
return makeJSError(ctx, msg.str().c_str()); return Value::makeError(ctx, msg.str().c_str());
} catch (const char* ex) { } catch (const char* ex) {
msg << "C++ Exception (thrown as a char*) in '" << exceptionLocation << "': " << ex; msg << "C++ Exception (thrown as a char*) in '" << exceptionLocation << "': " << ex;
return makeJSError(ctx, msg.str().c_str()); return Value::makeError(ctx, msg.str().c_str());
} catch (...) { } catch (...) {
msg << "Unknown C++ Exception in '" << exceptionLocation << "'"; msg << "Unknown C++ Exception in '" << exceptionLocation << "'";
return makeJSError(ctx, msg.str().c_str()); return Value::makeError(ctx, msg.str().c_str());
} }
} }
@ -221,7 +189,7 @@ JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, JSObjectRef j
auto functionName = Object(ctx, jsFunctionCause).getProperty("name").toString().str(); auto functionName = Object(ctx, jsFunctionCause).getProperty("name").toString().str();
return translatePendingCppExceptionToJSError(ctx, functionName.c_str()); return translatePendingCppExceptionToJSError(ctx, functionName.c_str());
} catch (...) { } catch (...) {
return makeJSError(ctx, "Failed to get function name while handling exception"); return Value::makeError(ctx, "Failed to get function name while handling exception");
} }
} }

View File

@ -62,10 +62,6 @@ void installGlobalProxy(
void removeGlobal(JSGlobalContextRef ctx, const char* name); void removeGlobal(JSGlobalContextRef ctx, const char* name);
JSValueRef makeJSCException(
JSContextRef ctx,
const char* exception_text);
JSValueRef evaluateScript( JSValueRef evaluateScript(
JSContextRef ctx, JSContextRef ctx,
JSStringRef script, JSStringRef script,
@ -83,8 +79,6 @@ void formatAndThrowJSException(
JSValueRef exn, JSValueRef exn,
JSStringRef sourceURL); JSStringRef sourceURL);
JSValueRef makeJSError(JSContextRef ctx, const char *error);
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation); JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, const char *exceptionLocation);
JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, JSObjectRef jsFunctionCause); JSValueRef translatePendingCppExceptionToJSError(JSContextRef ctx, JSObjectRef jsFunctionCause);

View File

@ -144,6 +144,18 @@ Object Value::asObject() {
return ret; return ret;
} }
Value Value::makeError(JSContextRef ctx, const char *error)
{
JSValueRef exn;
JSValueRef args[] = { Value(ctx, String(error)) };
JSObjectRef errorObj = JSObjectMakeError(ctx, 1, args, &exn);
if (!errorObj) {
std::string exceptionText = Value(ctx, exn).toString().str();
throwJSExecutionException("Exception calling object as function: %s", exceptionText.c_str());
}
return Value(ctx, errorObj);
}
Object::operator Value() const { Object::operator Value() const {
return Value(m_context, m_obj); return Value(m_context, m_obj);
} }
@ -153,7 +165,7 @@ Value Object::callAsFunction(std::initializer_list<JSValueRef> args) const {
} }
Value Object::callAsFunction(const Object& thisObj, std::initializer_list<JSValueRef> args) const { Value Object::callAsFunction(const Object& thisObj, std::initializer_list<JSValueRef> args) const {
return callAsFunction((JSObjectRef) thisObj, args.size(), args.begin()); return callAsFunction((JSObjectRef)thisObj, args.size(), args.begin());
} }
Value Object::callAsFunction(int nArgs, const JSValueRef args[]) const { Value Object::callAsFunction(int nArgs, const JSValueRef args[]) const {
@ -161,7 +173,7 @@ Value Object::callAsFunction(int nArgs, const JSValueRef args[]) const {
} }
Value Object::callAsFunction(const Object& thisObj, int nArgs, const JSValueRef args[]) const { Value Object::callAsFunction(const Object& thisObj, int nArgs, const JSValueRef args[]) const {
return callAsFunction((JSObjectRef) thisObj, nArgs, args); return callAsFunction(static_cast<JSObjectRef>(thisObj), nArgs, args);
} }
Value Object::callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef args[]) const { Value Object::callAsFunction(JSObjectRef thisObj, int nArgs, const JSValueRef args[]) const {

View File

@ -208,6 +208,10 @@ public:
return static_cast<ReturnType*>(JSObjectGetPrivate(m_obj)); return static_cast<ReturnType*>(JSObjectGetPrivate(m_obj));
} }
void setPrivate(void* data) const {
JSObjectSetPrivate(m_obj, data);
}
JSContextRef context() const { JSContextRef context() const {
return m_context; return m_context;
} }
@ -294,6 +298,16 @@ public:
return String::adopt(JSValueToStringCopy(context(), m_value, nullptr)); return String::adopt(JSValueToStringCopy(context(), m_value, nullptr));
} }
static Value makeError(JSContextRef ctx, const char *error);
static Value makeNumber(JSContextRef ctx, double value) {
return Value(ctx, JSValueMakeNumber(ctx, value));
}
static Value makeUndefined(JSContextRef ctx) {
return Value(ctx, JSValueMakeUndefined(ctx));
}
std::string toJSONString(unsigned indent = 0) const; std::string toJSONString(unsigned indent = 0) const;
static Value fromJSON(JSContextRef ctx, const String& json); static Value fromJSON(JSContextRef ctx, const String& json);
static JSValueRef fromDynamic(JSContextRef ctx, const folly::dynamic& value); static JSValueRef fromDynamic(JSContextRef ctx, const folly::dynamic& value);