Add JSI<->C++ bridging conversion for folly::dynamic (#37237)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/37237

Enables bridging conversions to/from jsi::Value and folly::dynamic.

Changelog:
[Internal] - Add JSI<->C++ bridging conversion for folly::dynamic

Reviewed By: javache

Differential Revision: D45544843

fbshipit-source-id: 89e773705a11eb3c5818cd081ef8c63436dc3340
This commit is contained in:
Genki Kondo
2023-05-04 14:56:14 -07:00
committed by Facebook GitHub Bot
parent a89b572768
commit d3fbcbb04d
3 changed files with 113 additions and 0 deletions
@@ -11,6 +11,7 @@
#include <react/bridging/Array.h>
#include <react/bridging/Bool.h>
#include <react/bridging/Class.h>
#include <react/bridging/Dynamic.h>
#include <react/bridging/Error.h>
#include <react/bridging/Function.h>
#include <react/bridging/Number.h>
@@ -0,0 +1,26 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <folly/dynamic.h>
#include <jsi/JSIDynamic.h>
namespace facebook::react {
template <>
struct Bridging<folly::dynamic> {
static folly::dynamic fromJs(jsi::Runtime &rt, const jsi::Value &value) {
return jsi::dynamicFromValue(rt, value);
}
static jsi::Value toJs(jsi::Runtime &rt, const folly::dynamic &value) {
return jsi::valueFromDynamic(rt, value);
}
};
} // namespace facebook::react
@@ -532,4 +532,90 @@ TEST_F(BridgingTest, supportTest) {
EXPECT_FALSE((bridging::supportsToJs<std::vector<int>, jsi::Function>));
}
TEST_F(BridgingTest, dynamicTest) {
// Null
auto nullFromJsResult =
bridging::fromJs<folly::dynamic>(rt, jsi::Value::null(), invoker);
EXPECT_TRUE(nullFromJsResult.isNull());
auto nullToJsResult = bridging::toJs<folly::dynamic>(rt, nullptr, invoker);
EXPECT_TRUE(nullToJsResult.isNull());
// Boolean
auto booleanFromJsResult =
bridging::fromJs<folly::dynamic>(rt, jsi::Value(true), invoker);
EXPECT_TRUE(booleanFromJsResult.isBool());
EXPECT_TRUE(booleanFromJsResult.asBool());
auto booleanToJsResult = bridging::toJs<folly::dynamic>(rt, true, invoker);
EXPECT_TRUE(booleanToJsResult.isBool());
EXPECT_TRUE(booleanToJsResult.asBool());
// Number
auto numberFromJsResult =
bridging::fromJs<folly::dynamic>(rt, jsi::Value(1.2), invoker);
EXPECT_TRUE(numberFromJsResult.isNumber());
EXPECT_DOUBLE_EQ(1.2, numberFromJsResult.asDouble());
auto numberToJsResult = bridging::toJs<folly::dynamic>(rt, 1.2, invoker);
EXPECT_TRUE(numberToJsResult.isNumber());
EXPECT_DOUBLE_EQ(1.2, numberToJsResult.asNumber());
// String
auto stringFromJsResult = bridging::fromJs<folly::dynamic>(
rt, jsi::Value(jsi::String::createFromAscii(rt, "hello")), invoker);
EXPECT_TRUE(stringFromJsResult.isString());
EXPECT_EQ("hello"s, stringFromJsResult.asString());
auto stringToJsResult = bridging::toJs<folly::dynamic>(rt, "hello", invoker);
EXPECT_TRUE(stringToJsResult.isString());
EXPECT_EQ("hello"s, stringToJsResult.asString(rt).utf8(rt));
// Array
auto arrayFromJsResult = bridging::fromJs<folly::dynamic>(
rt,
jsi::Value(jsi::Array::createWithElements(rt, "foo", "bar")),
invoker);
EXPECT_TRUE(arrayFromJsResult.isArray());
EXPECT_EQ(2, arrayFromJsResult.size());
EXPECT_EQ("foo"s, arrayFromJsResult[0].asString());
EXPECT_EQ("bar"s, arrayFromJsResult[1].asString());
auto arrayToJsResult = bridging::toJs<folly::dynamic>(
rt, folly::dynamic::array("foo", "bar"), invoker);
EXPECT_TRUE(arrayToJsResult.isObject());
EXPECT_TRUE(arrayToJsResult.asObject(rt).isArray(rt));
auto arrayToJsResultArray = arrayToJsResult.asObject(rt).asArray(rt);
EXPECT_EQ(2, arrayToJsResultArray.size(rt));
EXPECT_EQ(
"foo"s,
arrayToJsResultArray.getValueAtIndex(rt, 0).asString(rt).utf8(rt));
EXPECT_EQ(
"bar"s,
arrayToJsResultArray.getValueAtIndex(rt, 1).asString(rt).utf8(rt));
// Object
auto jsiObject = jsi::Object(rt);
jsiObject.setProperty(rt, "foo", "bar");
auto objectFromJsResult = bridging::fromJs<folly::dynamic>(
rt, jsi::Value(std::move(jsiObject)), invoker);
EXPECT_TRUE(objectFromJsResult.isObject());
EXPECT_EQ(1, objectFromJsResult.size());
EXPECT_EQ("bar"s, objectFromJsResult["foo"].asString());
auto objectToJsResult = bridging::toJs<folly::dynamic>(
rt, folly::dynamic::object("foo", "bar"), invoker);
EXPECT_TRUE(objectToJsResult.isObject());
auto objectToJsResultObject = objectToJsResult.asObject(rt);
EXPECT_EQ(
"bar"s,
objectToJsResultObject.getProperty(rt, "foo").asString(rt).utf8(rt));
// Undefined
auto undefinedFromJsResult =
bridging::fromJs<folly::dynamic>(rt, jsi::Value::undefined(), invoker);
EXPECT_TRUE(undefinedFromJsResult.isNull());
}
} // namespace facebook::react