Better folly::dynamic ==> JSValue conversion
Reviewed By: lexs Differential Revision: D3347854 fbshipit-source-id: 95b81152d1b0d5fe41e01991c44f5d1110be7ddb
This commit is contained in:
parent
e1b3bbdb04
commit
654e4bed2e
|
@ -46,8 +46,11 @@ Object.keys(RemoteModules).forEach((moduleName) => {
|
|||
get: () => {
|
||||
let module = RemoteModules[moduleName];
|
||||
if (module && typeof module.moduleID === 'number' && global.nativeRequireModuleConfig) {
|
||||
const json = global.nativeRequireModuleConfig(moduleName);
|
||||
const config = json && JSON.parse(json);
|
||||
// The old bridge (still used by iOS) will send the config as
|
||||
// a JSON string that needs parsing, so we set config according
|
||||
// to the type of response we got.
|
||||
const rawConfig = global.nativeRequireModuleConfig(moduleName);
|
||||
const config = typeof rawConfig === 'string' ? JSON.parse(rawConfig) : rawConfig;
|
||||
module = config && BatchedBridge.processModuleConfig(config, module.moduleID);
|
||||
RemoteModules[moduleName] = module;
|
||||
}
|
||||
|
|
|
@ -596,7 +596,7 @@ JSValueRef JSCExecutor::nativeRequireModuleConfig(
|
|||
|
||||
std::string moduleName = Value(m_context, arguments[0]).toString().str();
|
||||
folly::dynamic config = m_delegate->getModuleConfig(moduleName);
|
||||
return JSValueMakeString(m_context, String(folly::toJson(config).c_str()));
|
||||
return Value::fromDynamic(m_context, config);
|
||||
}
|
||||
|
||||
JSValueRef JSCExecutor::nativeFlushQueueImmediate(
|
||||
|
@ -681,7 +681,7 @@ JSValueRef JSCExecutor::nativeCallSyncHook(
|
|||
if (result.isUndefined) {
|
||||
return JSValueMakeUndefined(m_context);
|
||||
}
|
||||
return Value::fromJSON(m_context, String(folly::toJson(result.result).c_str()));
|
||||
return Value::fromDynamic(m_context, result.result);
|
||||
}
|
||||
|
||||
static JSValueRef nativeInjectHMRUpdate(
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "JSCHelpers.h"
|
||||
|
||||
// See the comment under Value::fromDynamic()
|
||||
#define USE_FAST_FOLLY_DYNAMIC_CONVERSION !defined(__APPLE__) && defined(WITH_FB_JSC_TUNING)
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
|
@ -51,9 +54,78 @@ Value Value::fromJSON(JSContextRef ctx, const String& json) throw(JSException) {
|
|||
return Value(ctx, result);
|
||||
}
|
||||
|
||||
Value Value::fromDynamic(JSContextRef ctx, folly::dynamic value) throw(JSException) {
|
||||
JSValueRef Value::fromDynamic(JSContextRef ctx, const folly::dynamic& value) {
|
||||
// JavaScriptCore's iOS APIs have their own version of this direct conversion.
|
||||
// In addition, using this requires exposing some of JSC's private APIs,
|
||||
// so it's limited to non-apple platforms and to builds that use the custom JSC.
|
||||
// Otherwise, we use the old way of converting through JSON.
|
||||
#if USE_FAST_FOLLY_DYNAMIC_CONVERSION
|
||||
// Defer GC during the creation of the JSValue, as we don't want
|
||||
// intermediate objects to be collected.
|
||||
// We could use JSValueProtect(), but it will make the process much slower.
|
||||
JSDeferredGCRef deferGC = JSDeferGarbageCollection(ctx);
|
||||
// Set a global lock for the whole process,
|
||||
// instead of re-acquiring the lock for each operation.
|
||||
JSLock(ctx);
|
||||
JSValueRef jsVal = Value::fromDynamicInner(ctx, value);
|
||||
JSUnlock(ctx);
|
||||
JSResumeGarbageCollection(ctx, deferGC);
|
||||
return jsVal;
|
||||
#else
|
||||
auto json = folly::toJson(value);
|
||||
return fromJSON(ctx, String(json.c_str()));
|
||||
#endif
|
||||
}
|
||||
|
||||
JSValueRef Value::fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj) {
|
||||
switch (obj.type()) {
|
||||
// For premitive types (and strings), just create and return an equivalent JSValue
|
||||
case folly::dynamic::Type::NULLT:
|
||||
return JSValueMakeNull(ctx);
|
||||
|
||||
case folly::dynamic::Type::BOOL:
|
||||
return JSValueMakeBoolean(ctx, obj.getBool());
|
||||
|
||||
case folly::dynamic::Type::DOUBLE:
|
||||
return JSValueMakeNumber(ctx, obj.getDouble());
|
||||
|
||||
case folly::dynamic::Type::INT64:
|
||||
return JSValueMakeNumber(ctx, obj.asDouble());
|
||||
|
||||
case folly::dynamic::Type::STRING:
|
||||
return JSValueMakeString(ctx, String(obj.getString().c_str()));
|
||||
|
||||
case folly::dynamic::Type::ARRAY: {
|
||||
// Collect JSValue for every element in the array
|
||||
JSValueRef vals[obj.size()];
|
||||
for (size_t i = 0; i < obj.size(); ++i) {
|
||||
vals[i] = fromDynamicInner(ctx, obj[i]);
|
||||
}
|
||||
// Create a JSArray with the values
|
||||
JSValueRef arr = JSObjectMakeArray(ctx, obj.size(), vals, nullptr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
case folly::dynamic::Type::OBJECT: {
|
||||
// Create an empty object
|
||||
JSObjectRef jsObj = JSObjectMake(ctx, nullptr, nullptr);
|
||||
// Create a JSValue for each of the object's children and set them in the object
|
||||
for (auto it = obj.items().begin(); it != obj.items().end(); ++it) {
|
||||
JSObjectSetProperty(
|
||||
ctx,
|
||||
jsObj,
|
||||
String(it->first.asString().c_str()),
|
||||
fromDynamicInner(ctx, it->second),
|
||||
kJSPropertyAttributeNone,
|
||||
nullptr);
|
||||
}
|
||||
return jsObj;
|
||||
}
|
||||
default:
|
||||
// Assert not reached
|
||||
LOG(FATAL) << "Trying to convert a folly object of unsupported type.";
|
||||
return JSValueMakeNull(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
Object Value::asObject() {
|
||||
|
|
|
@ -284,11 +284,12 @@ public:
|
|||
|
||||
std::string toJSONString(unsigned indent = 0) const throw(JSException);
|
||||
static Value fromJSON(JSContextRef ctx, const String& json) throw(JSException);
|
||||
static Value fromDynamic(JSContextRef ctx, folly::dynamic value) throw(JSException);
|
||||
static JSValueRef fromDynamic(JSContextRef ctx, const folly::dynamic& value);
|
||||
JSContextRef context() const;
|
||||
protected:
|
||||
JSContextRef m_context;
|
||||
JSValueRef m_value;
|
||||
static JSValueRef fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj);
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
Loading…
Reference in New Issue