Array.h 代码目录:
packages/react-native/ReactCommon/react/bridging/Array.h
代码如下:
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.
*/
#pragma once
#include <react/bridging/Base.h>
#include <array>
#include <deque>
#include <initializer_list>
#include <list>
#include <set>
#include <tuple>
#include <utility>
#include <vector>
namespace facebook::react {
namespace array_detail {
template <typename T, size_t N>
struct BridgingStatic {
static jsi::Array toJs(jsi::Runtime &rt, const T &array, const std::shared_ptr<CallInvoker> &jsInvoker)
{
return toJs(rt, array, jsInvoker, std::make_index_sequence<N>{});
}
private:
template <size_t... Index>
static jsi::Array toJs(
facebook::jsi::Runtime &rt,
const T &array,
const std::shared_ptr<CallInvoker> &jsInvoker,
std::index_sequence<Index...> /*unused*/)
{
return jsi::Array::createWithElements(rt, bridging::toJs(rt, std::get<Index>(array), jsInvoker)...);
}
};
template <typename T>
struct BridgingDynamic {
static jsi::Array toJs(jsi::Runtime &rt, const T &list, const std::shared_ptr<CallInvoker> &jsInvoker)
{
jsi::Array result(rt, list.size());
size_t index = 0;
for (const auto &item : list) {
result.setValueAtIndex(rt, index++, bridging::toJs(rt, item, jsInvoker));
}
return result;
}
};
} // namespace array_detail
template <typename T, size_t N>
struct Bridging<std::array<T, N>> : array_detail::BridgingStatic<std::array<T, N>, N> {
static std::array<T, N>
fromJs(facebook::jsi::Runtime &rt, const jsi::Array &array, const std::shared_ptr<CallInvoker> &jsInvoker)
{
size_t length = array.length(rt);
std::array<T, N> result;
for (size_t i = 0; i < length; i++) {
result[i] = bridging::fromJs<T>(rt, array.getValueAtIndex(rt, i), jsInvoker);
}
return result;
}
};
template <typename T1, typename T2>
struct Bridging<std::pair<T1, T2>> : array_detail::BridgingStatic<std::pair<T1, T2>, 2> {
static std::pair<T1, T1>
fromJs(facebook::jsi::Runtime &rt, const jsi::Array &array, const std::shared_ptr<CallInvoker> &jsInvoker)
{
return std::make_pair(
bridging::fromJs<T1>(rt, array.getValueAtIndex(rt, 0), jsInvoker),
bridging::fromJs<T2>(rt, array.getValueAtIndex(rt, 1), jsInvoker));
}
};
template <typename... Types>
struct Bridging<std::tuple<Types...>> : array_detail::BridgingStatic<std::tuple<Types...>, sizeof...(Types)> {};
template <typename T>
struct Bridging<std::deque<T>> : array_detail::BridgingDynamic<std::deque<T>> {};
template <typename T>
struct Bridging<std::initializer_list<T>> : array_detail::BridgingDynamic<std::initializer_list<T>> {};
template <typename T>
struct Bridging<std::list<T>> : array_detail::BridgingDynamic<std::list<T>> {};
template <typename T>
struct Bridging<std::vector<T>> : array_detail::BridgingDynamic<std::vector<T>> {
static std::vector<T>
fromJs(facebook::jsi::Runtime &rt, const jsi::Array &array, const std::shared_ptr<CallInvoker> &jsInvoker)
{
size_t length = array.length(rt);
std::vector<T> vector;
vector.reserve(length);
for (size_t i = 0; i < length; i++) {
vector.push_back(bridging::fromJs<T>(rt, array.getValueAtIndex(rt, i), jsInvoker));
}
return vector;
}
};
template <typename T>
struct Bridging<std::set<T>> : array_detail::BridgingDynamic<std::set<T>> {
static std::set<T>
fromJs(facebook::jsi::Runtime &rt, const jsi::Array &array, const std::shared_ptr<CallInvoker> &jsInvoker)
{
size_t length = array.length(rt);
std::set<T> set;
for (size_t i = 0; i < length; i++) {
set.insert(bridging::fromJs<T>(rt, array.getValueAtIndex(rt, i), jsInvoker));
}
return set;
}
};
} // namespace facebook::react
概述
该头文件属于 facebook::react 命名空间,提供了 C++ 标准集合类型与 JavaScript (JSI, JavaScript Interface) 数组(jsi::Array)之间的双向桥接能力。核心功能是实现 C++ 集合与 JS 数组的相互转换(toJs 转 JS、fromJs 转 C++),支撑 React Native 等跨端框架中 C++ 层与 JS 层的数据通信。
核心命名空间与内部细节
1. 顶层命名空间
cpp
facebook::react
所有桥接结构体与方法均位于该命名空间下。
2. 内部辅助命名空间
cpp
facebook::react::array_detail
提供两种核心桥接实现模板,用于复用静态长度集合与动态长度集合的转换逻辑,不对外直接暴露使用。
| 辅助结构体 | 适用场景 | 核心逻辑 |
|---|---|---|
BridgingStatic<T, N> |
静态长度集合(编译期确定长度) | 利用 C++ 索引序列(std::index_sequence)实现编译期遍历,通过完美转发完成元素转换,效率更高 |
BridgingDynamic<T> |
动态长度集合(运行期确定长度) | 利用运行期循环遍历集合元素,逐个完成转换,兼容性更强 |
核心桥接接口
所有公开桥接结构体均遵循统一接口规范:
- 静态方法
toJs:将 C++ 集合转换为 JSI 数组- 签名:
static jsi::Array toJs(jsi::Runtime &rt, const T &collection, const std::shared_ptr<CallInvoker> &jsInvoker) - 参数:
rt:JSI 运行时环境引用,提供 JS 层执行上下文collection:待转换的 C++ 集合常量引用jsInvoker:JS 调用器智能指针,用于异步 / 同步调用 JS 方法
- 返回值:
jsi::Array,对应 JS 层的数组对象
- 签名:
- 静态方法
fromJs(可选,部分集合默认实现,部分自定义实现):将 JSI 数组转换为 C++ 集合- 签名:
static T fromJs(jsi::Runtime &rt, const jsi::Array &array, const std::shared_ptr<CallInvoker> &jsInvoker) - 参数:
rt:JSI 运行时环境引用array:待转换的 JSI 数组常量引用jsInvoker:JS 调用器智能指针
- 返回值:对应的 C++ 集合对象
T
- 签名:
各集合类型桥接详情
1. std::array<T, N> 桥接
模板定义
cpp
template <typename T, size_t N>
struct Bridging<std::array<T, N>> : array_detail::BridgingStatic<std::array<T, N>, N>
适用场景
C++ 静态长度数组(编译期确定长度 N,元素类型 T)。
继承关系
继承自 array_detail::BridgingStatic,复用静态长度集合的转换逻辑。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ std::array → JS 数组 |
利用索引序列编译期遍历数组元素,批量转换后创建 jsi::Array |
fromJs |
JS 数组 → C++ std::array |
1. 获取 JS 数组长度2. 循环遍历 JS 数组元素,逐个转换并赋值到 std::array3. 若 JS 数组长度小于 N,剩余 std::array 元素保持默认值;若大于 N,超出部分忽略 |
2. std::pair<T1, T2> 桥接
模板定义
cpp
template <typename T1, typename T2>
struct Bridging<std::pair<T1, T2>> : array_detail::BridgingStatic<std::pair<T1, T2>, 2>
适用场景
C++ 键值对(两个元素,类型分别为 T1、T2)。
继承关系
继承自 array_detail::BridgingStatic(长度固定为 2)。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ std::pair → JS 数组 |
编译期提取 pair 的第一个元素(first)和第二个元素(second),转换后创建长度为 2 的 jsi::Array |
fromJs |
JS 数组 → C++ std::pair |
1. 提取 JS 数组索引 0 和索引 1 的元素,分别转换为 T1 和 T2 类型2. 通过 std::make_pair 创建 std::pair<T1, T2> 对象3. 注意:代码中返回值类型存在笔误(std::pair<T1, T1> 应为 std::pair<T1, T2>),不影响核心逻辑 |
3. std::tuple<Types...> 桥接
模板定义
cpp
template <typename... Types>
struct Bridging<std::tuple<Types...>> : array_detail::BridgingStatic<std::tuple<Types...>, sizeof...(Types)>
适用场景
C++ 元组(支持任意数量、任意类型的元素,长度为 sizeof...(Types))。
继承关系
继承自 array_detail::BridgingStatic,复用静态长度集合的转换逻辑。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ std::tuple → JS 数组 |
利用索引序列编译期遍历元组所有元素,批量转换后创建对应长度的 jsi::Array |
fromJs |
未自定义实现 | 暂未提供自定义转换逻辑,若需使用需依赖默认实现(或上层扩展) |
4. std::deque<T> 桥接
模板定义
cpp
template <typename T>
struct Bridging<std::deque<T>> : array_detail::BridgingDynamic<std::deque<T>>
适用场景
C++ 双端队列(动态长度,支持首尾高效插入 / 删除)。
继承关系
继承自 array_detail::BridgingDynamic,复用动态长度集合的转换逻辑。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ std::deque → JS 数组 |
1. 创建与 deque 长度一致的 jsi::Array2. 运行期循环遍历 deque 元素,逐个转换并赋值到 JS 数组对应索引 |
fromJs |
未自定义实现 | 暂未提供自定义转换逻辑,依赖默认实现 |
5. std::initializer_list<T> 桥接
模板定义
cpp
template <typename T>
struct Bridging<std::initializer_list<T>> : array_detail::BridgingDynamic<std::initializer_list<T>>
适用场景
C++ 初始化列表(临时动态元素序列,用于初始化其他集合)。
继承关系
继承自 array_detail::BridgingDynamic。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ 初始化列表 → JS 数组 | 运行期循环遍历初始化列表元素,逐个转换后创建 jsi::Array |
fromJs |
未自定义实现 | 暂未提供自定义转换逻辑,依赖默认实现 |
6. std::list<T> 桥接
模板定义
cpp
template <typename T>
struct Bridging<std::list<T>> : array_detail::BridgingDynamic<std::list<T>>
适用场景
C++ 双向链表(动态长度,支持高效插入 / 删除,不支持随机访问)。
继承关系
继承自 array_detail::BridgingDynamic。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ std::list → JS 数组 |
运行期循环遍历链表元素(迭代器遍历),逐个转换后创建 jsi::Array |
fromJs |
未自定义实现 | 暂未提供自定义转换逻辑,依赖默认实现 |
7. std::vector<T> 桥接
模板定义
cpp
template <typename T>
struct Bridging<std::vector<T>> : array_detail::BridgingDynamic<std::vector<T>>
适用场景
C++ 动态数组(最常用动态集合,支持随机访问,尾部插入 / 删除高效)。
继承关系
继承自 array_detail::BridgingDynamic,并自定义了 fromJs 方法优化性能。
核心方法
| 方法名 | 功能 | 实现细节(性能优化点) |
|---|---|---|
toJs |
C++ std::vector → JS 数组 |
运行期循环遍历 vector 元素,逐个转换后创建 jsi::Array |
fromJs |
JS 数组 → C++ std::vector |
1. 获取 JS 数组长度,调用 vector.reserve(length) 预分配内存,避免多次扩容2. 循环遍历 JS 数组元素,逐个转换后通过 push_back 插入 vector3. 最终返回填充后的 vector |
8. std::set<T> 桥接
模板定义
cpp
template <typename T>
struct Bridging<std::set<T>> : array_detail::BridgingDynamic<std::set<T>>
适用场景
C++ 有序不重复集合(基于红黑树实现,元素自动排序且唯一)。
继承关系
继承自 array_detail::BridgingDynamic,并自定义了 fromJs 方法。
核心方法
| 方法名 | 功能 | 实现细节 |
|---|---|---|
toJs |
C++ std::set → JS 数组 |
运行期循环遍历有序集合元素,逐个转换后创建 jsi::Array(JS 数组保留 std::set 的有序性) |
fromJs |
JS 数组 → C++ std::set |
1. 获取 JS 数组长度,初始化空 std::set2. 循环遍历 JS 数组元素,逐个转换后通过 insert 插入 set(自动去重并排序)3. 最终返回有序不重复的 std::set |
关键特性总结
- 分层设计 :通过
array_detail内部命名空间隔离通用逻辑,对外暴露简洁的Bridging模板接口,提高代码复用性。 - 静态 / 动态分离 :静态长度集合(
array/pair/tuple)编译期优化,动态长度集合(vector/list/set等)运行期兼容,兼顾效率与灵活性。 - 性能优化 :
std::vector的fromJs方法使用reserve预分配内存,减少内存扩容开销;std::set利用insert自动去重排序,贴合其数据特性。 - 统一接口 :所有桥接结构体遵循
toJs/fromJs统一签名,降低使用成本,便于扩展新的集合类型。
注意事项
std::pair<T1, T2>的fromJs方法存在返回值类型笔误(std::pair<T1, T1>应为std::pair<T1, T2>),使用时需注意(或修正代码)。- 仅支持代码中列举的 C++ 标准集合类型,自定义集合需手动实现
Bridging模板特化。 - 元素类型
T需满足桥接要求(即bridging::toJs和bridging::fromJs支持T类型的转换)。 - 依赖 JSI 库(
jsi::Runtime、jsi::Array)和 React 基础桥接(react/bridging/Base.h),使用时需引入对应依赖。