源码目录:
cpp
packages/react-native/ReactCommon/react/bridging/tests/ClassTest.cpp
源码:
cpp
/*
* 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.
*/
#include "BridgingTest.h"
#include <utility>
namespace facebook::react {
using namespace std::literals;
struct TestClass {
explicit TestClass(std::shared_ptr<CallInvoker> invoker)
: invoker_(std::move(invoker)) {}
double add(jsi::Runtime& /*unused*/, int a, float b) {
return a + b;
}
jsi::Object getObject(jsi::Runtime& /*unused*/, jsi::Object obj) {
return obj;
}
AsyncPromise<std::string> getPromise(jsi::Runtime& rt, std::string result) {
auto promise = AsyncPromise<std::string>(rt, invoker_);
promise.resolve(std::move(result));
return promise;
}
std::string callFunc(
jsi::Runtime& /*unused*/,
SyncCallback<std::string(int)> func,
int num) {
return func(num);
}
void callAsync(jsi::Runtime& /*unused*/, const AsyncCallback<>& callback) {
callback();
}
private:
std::shared_ptr<CallInvoker> invoker_;
};
TEST_F(BridgingTest, callFromJsTest) {
auto instance = TestClass(invoker);
EXPECT_EQ(
3.0,
bridging::callFromJs<double>(
rt, &TestClass::add, invoker, &instance, 1, 2.0));
auto object = jsi::Object(rt);
EXPECT_TRUE(
jsi::Object::strictEquals(
rt,
object,
bridging::callFromJs<jsi::Object>(
rt, &TestClass::getObject, invoker, &instance, object)));
auto promise = bridging::callFromJs<jsi::Object>(
rt,
&TestClass::getPromise,
invoker,
&instance,
jsi::String::createFromAscii(rt, "hi"));
auto then = promise.getPropertyAsFunction(rt, "then");
std::string result;
then.callWithThis(
rt,
promise,
bridging::toJs(
rt, [&](std::string res) { result = std::move(res); }, invoker));
flushQueue();
EXPECT_EQ("hi"s, result);
auto func = function("(num) => String(num)");
EXPECT_EQ(
"1"s,
bridging::callFromJs<jsi::String>(
rt, &TestClass::callFunc, invoker, &instance, func, 1)
.utf8(rt));
bool called = false;
func = bridging::toJs(rt, [&] { called = true; }, invoker);
bridging::callFromJs<void>(
rt, &TestClass::callAsync, invoker, &instance, func);
flushQueue();
EXPECT_TRUE(called);
}
struct MethodReturnTypeCastingTestObject {
public:
explicit MethodReturnTypeCastingTestObject(int value) : value_(value) {}
int toInteger() const {
return value_;
}
private:
int value_;
};
template <>
struct Bridging<MethodReturnTypeCastingTestObject> {
static MethodReturnTypeCastingTestObject fromJs(
jsi::Runtime& /*rt*/,
const jsi::Value& value) {
return MethodReturnTypeCastingTestObject(
static_cast<int>(value.asNumber()));
}
static int toJs(
jsi::Runtime& /*rt*/,
const MethodReturnTypeCastingTestObject& value) {
return value.toInteger();
}
};
struct MethodReturnTypeCastingTestClass {
explicit MethodReturnTypeCastingTestClass(
std::shared_ptr<CallInvoker> invoker)
: invoker_(std::move(invoker)) {}
// This is the key, return type is not a primitive, but an object with defined
// bridging template.
MethodReturnTypeCastingTestObject
add(jsi::Runtime& /*unused*/, int a, int b) {
return MethodReturnTypeCastingTestObject(a + b);
}
private:
std::shared_ptr<CallInvoker> invoker_;
};
TEST_F(BridgingTest, methodReturnTypeCastingTest) {
auto instance = MethodReturnTypeCastingTestClass(invoker);
EXPECT_EQ(
2,
bridging::callFromJs<int>(
rt,
&MethodReturnTypeCastingTestClass::add,
invoker,
&instance,
1,
1));
}
} // namespace facebook::react
概述
本文档是 BridgingTest 测试套件的补充说明,聚焦验证 bridging::callFromJs 接口的功能正确性 ,覆盖两类核心场景:一是类成员方法的跨语言调用(支持基础类型、JSI 对象、Promise、同步 / 异步回调等参数与返回值);二是自定义桥接类型的返回值自动转换能力。该测试基于 Google Test(GTest)框架,继承 BridgingTest 基类提供的 JS 运行时与测试工具,确保 C++ 类成员方法通过桥接接口被正确调度,且类型转换符合预期。
测试环境与依赖
核心依赖
- 基础测试框架:Google Test(GTest)
- 父类测试环境 :
BridgingTest(提供 Hermes JS 运行时rt、测试用调用器invoker、flushQueue异步任务刷新等能力) - 桥接核心接口 :
bridging::callFromJs(核心测试对象,用于跨语言调用 C++ 类成员方法) - 辅助类型 :
jsi::Runtime/jsi::Object/jsi::Function/AsyncPromise等 JSI 与 React 桥接核心类型
继承关系
所有测试用例均继承 BridgingTest 基类,直接复用其初始化的 JS 运行时、调用器及辅助方法(如 function 用于创建 JS 函数实例)。
自定义辅助类型说明
测试中定义了 3 个自定义结构体 / 类及 1 个桥接模板特化,用于支撑测试场景,其详细信息如下:
1. 测试类:TestClass
类概述
cpp
struct TestClass;
用于提供各类待测试的成员方法,覆盖不同参数类型、返回值类型的场景,构造函数接收 std::shared_ptr<CallInvoker> 用于初始化 AsyncPromise。
核心成员方法
| 方法签名 | 返回值类型 | 功能描述 | 适用测试场景 |
|---|---|---|---|
double add(jsi::Runtime&, int a, float b) |
double |
返回 a + b 的计算结果 |
基础类型参数与返回值测试 |
jsi::Object getObject(jsi::Runtime&, jsi::Object obj) |
jsi::Object |
直接返回传入的 JSI 对象 | JSI 对象参数与返回值测试 |
AsyncPromise<std::string> getPromise(jsi::Runtime&, std::string result) |
AsyncPromise<std::string> |
创建并立即 resolve 的 Promise,返回指定字符串结果 |
Promise 类型返回值测试 |
std::string callFunc(jsi::Runtime&, SyncCallback<std::string(int)> func, int num) |
std::string |
调用同步回调并返回其执行结果 | 同步回调参数测试 |
void callAsync(jsi::Runtime&, const AsyncCallback<>& callback) |
void |
调用异步回调 | 异步回调参数测试 |
私有成员
| 成员名称 | 类型 | 功能描述 |
|---|---|---|
invoker_ |
std::shared_ptr<CallInvoker> |
存储调用器实例,用于创建 AsyncPromise |
2. 自定义桥接类型:MethodReturnTypeCastingTestObject
结构体概述
cpp
struct MethodReturnTypeCastingTestObject;
自定义值对象,用于验证「非基础类型返回值」的桥接转换能力,内部存储一个 int 类型值。
核心成员
| 成员 / 方法 | 类型 / 签名 | 功能描述 |
|---|---|---|
value_ |
int(私有) |
存储核心整数值 |
| 构造函数 | explicit MethodReturnTypeCastingTestObject(int value) |
初始化 value_ |
toInteger() const |
int |
返回 value_,用于桥接转换为 JS 可识别类型 |
3. 桥接模板特化:Bridging<MethodReturnTypeCastingTestObject>
模板概述
cpp
template <>
struct Bridging<MethodReturnTypeCastingTestObject>;
为 MethodReturnTypeCastingTestObject 提供自定义桥接逻辑,支持 JS→C++ 与 C++→JS 的类型转换,是返回值自动转换的核心依赖。
核心静态方法
| 方法签名 | 功能描述 |
|---|---|
static MethodReturnTypeCastingTestObject fromJs(jsi::Runtime&, const jsi::Value& value) |
JS 数值类型转自定义对象:将 jsi::Value 转为 int 后初始化 MethodReturnTypeCastingTestObject |
static int toJs(jsi::Runtime&, const MethodReturnTypeCastingTestObject& value) |
自定义对象转 JS 基础类型:调用 toInteger() 返回内部 int 值 |
4. 测试类:MethodReturnTypeCastingTestClass
类概述
cpp
struct MethodReturnTypeCastingTestClass;
用于提供返回 MethodReturnTypeCastingTestObject 类型的成员方法,验证自定义桥接类型的返回值转换能力。
核心成员
| 成员 / 方法 | 类型 / 签名 | 功能描述 |
|---|---|---|
invoker_ |
std::shared_ptr<CallInvoker>(私有) |
存储调用器实例(构造函数初始化) |
add(jsi::Runtime&, int a, int b) |
MethodReturnTypeCastingTestObject |
返回 a + b 初始化后的 MethodReturnTypeCastingTestObject 实例 |
测试用例详情
1. 类成员方法跨语言调用测试(callFromJsTest)
测试目标
验证 bridging::callFromJs 接口能正确调度 TestClass 的各类成员方法,支持:
- 基础类型(
int/float/double)的参数传递与返回值接收 - JSI 对象(
jsi::Object)的参数传递与返回值一致性校验 AsyncPromise类型返回值的桥接与 JS 端then回调的执行- 同步回调(
SyncCallback)的参数传递与结果返回 - 异步回调(
AsyncCallback)的参数传递与异步执行
测试场景与预期结果
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
基础类型方法调用(add) |
1. 创建 TestClass 实例 instance2. 调用 bridging::callFromJs<double>(rt, &TestClass::add, invoker, &instance, 1, 2.0) |
返回值为 3.0,与 1 + 2.0 计算结果一致 |
JSI 对象方法调用(getObject) |
1. 创建 jsi::Object 实例 object2. 调用 bridging::callFromJs<jsi::Object>(rt, &TestClass::getObject, invoker, &instance, object)3. 通过 jsi::Object::strictEquals 校验返回值与原始对象 |
返回值与原始 object 严格相等,无对象拷贝异常 |
Promise 方法调用(getPromise) |
1. 调用 bridging::callFromJs<jsi::Object> 获取 JS Promise 实例 promise2. 获取 Promise 的 then 方法,传入自定义回调(存储结果到 std::string result)3. 调用 flushQueue 刷新异步任务队列 |
result 值为 "hi",与 getPromise 传入的参数一致 |
同步回调方法调用(callFunc) |
1. 创建 JS 函数 func(功能:接收 num 并返回其字符串形式)2. 调用 bridging::callFromJs<jsi::String>(rt, &TestClass::callFunc, invoker, &instance, func, 1)3. 转换返回值为 std::string |
返回值为 "1",与 JS 函数执行结果一致 |
异步回调方法调用(callAsync) |
1. 创建异步回调 func(功能:将 bool called 设为 true)2. 调用 bridging::callFromJs<void>(rt, &TestClass::callAsync, invoker, &instance, func)3. 调用 flushQueue 刷新异步任务队列 |
called 值为 true,说明异步回调已执行 |
2. 自定义桥接类型返回值转换测试(methodReturnTypeCastingTest)
测试目标
验证 bridging::callFromJs 支持「自定义桥接类型返回值」到指定基础类型的自动转换,即 MethodReturnTypeCastingTestClass::add 返回 MethodReturnTypeCastingTestObject,通过 Bridging<MethodReturnTypeCastingTestObject> 模板,自动转换为 int 类型返回值。
测试场景与预期结果
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
| 自定义类型返回值转换 | 1. 创建 MethodReturnTypeCastingTestClass 实例 instance2. 调用 bridging::callFromJs<int>(rt, &MethodReturnTypeCastingTestClass::add, invoker, &instance, 1, 1)3. 校验返回值 |
返回值为 2,与 1 + 1 计算结果一致,说明 MethodReturnTypeCastingTestObject 已通过自定义桥接模板转换为 int |
核心原理
MethodReturnTypeCastingTestClass::add返回MethodReturnTypeCastingTestObject(1+1)(内部value_为2)bridging::callFromJs检测到目标返回类型为int,自动调用Bridging<MethodReturnTypeCastingTestObject>::toJs方法- 该方法调用
toInteger()返回2,最终作为bridging::callFromJs的返回值
核心测试点总结
| 测试维度 | 覆盖场景 | 核心验证目标 |
|---|---|---|
| 方法调度正确性 | 基础类型、JSI 对象、Promise、同步 / 异步回调参数的成员方法 | bridging::callFromJs 能正确传递参数并调度类成员方法 |
| 类型转换完整性 | 基础类型、自定义桥接类型的返回值 | 支持基础类型直接返回,支持自定义桥接类型到指定类型的自动转换 |
| 异步逻辑可靠性 | 异步回调、Promise | 异步任务能通过 flushQueue 正常执行,结果符合预期 |
| 对象一致性 | JSI 对象参数传递 | JSI 对象跨方法调用后保持一致性,无非法拷贝或修改 |
注意事项
- 异步任务必须刷新队列 :涉及
AsyncPromise、AsyncCallback的测试场景,需调用flushQueue()执行待调度的异步任务,否则断言会因结果未更新而失败。 - 自定义类型需提供桥接模板 :若需支持
bridging::callFromJs对自定义类型的参数 / 返回值转换,必须特化Bridging模板,实现fromJs(JS→C++)与toJs(C++→JS)方法。 - 成员方法参数约束 :
bridging::callFromJs要求成员方法的第一个参数必须为jsi::Runtime&,后续参数为业务参数,否则会触发编译错误。 - 返回值类型匹配 :
bridging::callFromJs的模板参数需与目标返回类型一致(或可通过自定义桥接模板转换为该类型),否则会触发类型不匹配错误。