From dbec1fbd4e6a7cdc1f25a2026da1b9eb7cbb88bd Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 13:29:10 +0800 Subject: [PATCH 01/11] docs: add detailed implementation plan for Phase 2 cross-platform support - Introduced a new document outlining the goals, tasks, and timelines for achieving complete cross-platform support for macOS, iOS, and Android. - Included specific tasks for iOS and Android platform integration, as well as a unified testing process. - Simplified the roadmap by focusing on core functionalities and removing complex tasks related to engine optimization. --- docs/PHASE2_PLAN.md | 307 ++++++++++++++++++++++++++++++++++++++++++++ docs/roadmap.md | 55 ++++---- 2 files changed, 339 insertions(+), 23 deletions(-) create mode 100644 docs/PHASE2_PLAN.md diff --git a/docs/PHASE2_PLAN.md b/docs/PHASE2_PLAN.md new file mode 100644 index 0000000..08178f0 --- /dev/null +++ b/docs/PHASE2_PLAN.md @@ -0,0 +1,307 @@ +# 阶段2:跨平台支持 - 详细实施计划 + +## 🎯 阶段目标 + +实现完整的跨平台支持(macOS + iOS + Android),建立统一的构建和测试流程,这是 Mini React Native 走向完整性的关键步骤。 + +**成功标准:** + +- ✅ iOS 平台完整支持,与 macOS 共享 JavaScriptCore.framework +- ✅ Android 平台完整支持,通过 JNI 集成 JavaScriptCore +- ✅ 三平台统一的构建、测试和验证流程 +- ✅ DeviceInfo 模块在所有平台正常工作 +- ✅ 性能保持在可接受水平(< 10ms 调用延迟) + +## 📋 详细任务分解 + +### 任务1: iOS 平台支持完成 + +**目标:** 完成 iOS 平台的完整适配,利用与 macOS 共享的 JavaScriptCore.framework + +**架构约束:** + +- 复用现有的 JSCExecutor 实现,最小化平台差异 +- 利用 iOS 和 macOS 共享的 JavaScriptCore.framework +- 保持与 macOS 版本的 API 一致性 + +#### 子任务 1.1: iOS 构建系统配置 (0.25天) + +- [ ] **Xcode 项目配置** + - 创建 iOS target 配置 + - 配置 JavaScriptCore.framework 链接 + - 设置最低 iOS 版本支持(iOS 12.0+) + +- [ ] **CMake 构建适配** + - 添加 iOS 平台检测逻辑 + - 配置 iOS 特定的编译选项 + - 确保与 macOS 构建的一致性 + +#### 子任务 1.2: iOS 平台验证 (0.25天) + +- [ ] **基础功能验证** + - JSCExecutor 在 iOS 上的初始化验证 + - Bridge 通信功能测试 + - DeviceInfo 模块在 iOS 上的运行验证 + +- [ ] **iOS 特定 API 实现** + - iOS 版本的设备信息获取 + - 确保 DeviceInfo 返回正确的 iOS 设备数据 + +### 任务2: Android 平台集成 + +**目标:** 实现 Android 平台的完整支持,通过 JNI 集成 JavaScriptCore + +**架构约束:** + +- 使用 JSC 的移植版本(如 facebook/android-jsc) +- 通过 JNI 桥接 C++ 和 Java/Kotlin 代码 +- 保持与 iOS/macOS 的 API 一致性 + +#### 子任务 2.1: Android 构建系统搭建 (1.5天) + +- [ ] **Gradle 项目结构** + - 创建 Android 项目基础结构 + - 配置 CMake 与 Gradle 的集成 + - 设置 NDK 构建配置 + +- [ ] **JavaScriptCore 移植版本集成** + - 集成 facebook/android-jsc 或类似的 JSC 移植版本 + - 配置 JSC 库的链接和依赖 + - 验证 JSC API 在 Android 上的可用性 + +- [ ] **JNI 桥接层设计** + ```cpp + // JNI 接口设计 + extern "C" { + JNIEXPORT void JNICALL Java_com_minirn_JSCExecutor_initializeContext(JNIEnv* env, jobject obj); + JNIEXPORT void JNICALL Java_com_minirn_JSCExecutor_loadScript(JNIEnv* env, jobject obj, jstring script); + JNIEXPORT void JNICALL Java_com_minirn_JSCExecutor_destroyContext(JNIEnv* env, jobject obj); + } + ``` + +#### 子任务 2.2: Android Native 层实现 (1天) + +- [ ] **JSCExecutor Android 适配** + - 适配现有的 JSCExecutor 到 Android 环境 + - 处理 Android 特定的内存管理 + - 确保线程安全(Android 主线程 vs Native 线程) + +- [ ] **Android DeviceInfo 模块** + - 实现 Android 版本的设备信息获取 + - 通过 JNI 调用 Android API + - 返回正确的 Android 设备数据 + +#### 子任务 2.3: Android Java 层实现 (0.5天) + +- [ ] **Java/Kotlin 封装层** + - 创建 JSCExecutor 的 Java 封装类 + - 实现 DeviceInfo 的 Android API 调用 + - 建立 Java 到 Native 的调用桥梁 + +- [ ] **Android 应用示例** + - 创建简单的 Android 应用示例 + - 集成 Mini React Native 库 + - 验证基础功能正常工作 + +### 任务3: 跨平台测试与验证 + +**目标:** 建立统一的跨平台测试流程,确保三平台的一致性 + +#### 子任务 3.1: 统一测试套件 (0.5天) + +- [ ] **跨平台测试脚本** + - 创建统一的测试脚本,支持三平台 + - 自动化构建和测试流程 + - 集成到 Makefile 中 + +- [ ] **一致性验证** + - 确保 DeviceInfo 在三平台返回正确格式的数据 + - 验证 Bridge 通信的性能一致性 + - 测试错误处理的平台一致性 + +#### 子任务 3.2: 文档和示例完善 (0.5天) + +- [ ] **跨平台构建文档** + - 详细的三平台构建指南 + - 依赖安装和环境配置说明 + - 常见问题和解决方案 + +- [ ] **平台差异说明** + - 记录三平台的技术差异 + - API 调用的平台特定实现 + - 性能特征对比 + +## 🔧 技术要点和难点 + +### Android 平台的主要挑战 + +1. **JNI 集成复杂性** + - C++ 和 Java 之间的数据类型转换 + - 内存管理和生命周期控制 + - 异常处理的跨语言传递 + +2. **JavaScriptCore 移植版本** + - 不同 JSC 移植版本的 API 差异 + - 性能和稳定性的权衡 + - 版本兼容性管理 + +3. **Android 构建系统** + - CMake 和 Gradle 的集成配置 + - NDK 版本兼容性 + - 多架构支持(arm64-v8a, armeabi-v7a) + +### iOS 平台的技术要点 + +1. **框架共享优势** + - 与 macOS 共享 JavaScriptCore.framework + - 代码复用率高,适配工作量小 + - API 一致性好 + +2. **平台特定优化** + - iOS 内存限制的考虑 + - 后台执行的限制 + - App Store 审核要求 + +### 跨平台一致性保证 + +1. **API 抽象层设计** + - 统一的 NativeModule 接口 + - 平台特定实现的封装 + - 错误处理的标准化 + +2. **测试策略** + - 自动化的跨平台测试 + - 性能基准的平台对比 + - 功能一致性验证 + +## 📝 验收标准 + +### 功能验收 + +- [ ] **iOS 平台验收** + - JSCExecutor 在 iOS 上正常初始化和运行 + - DeviceInfo 模块返回正确的 iOS 设备信息 + - Bridge 通信性能 < 10ms + +- [ ] **Android 平台验收** + - 通过 JNI 成功集成 JavaScriptCore + - DeviceInfo 模块返回正确的 Android 设备信息 + - 构建系统支持多架构(arm64-v8a, armeabi-v7a) + +- [ ] **跨平台一致性验收** + - 同一份 JavaScript 代码在三平台运行结果一致 + - DeviceInfo API 在三平台返回相同格式的数据 + - 错误处理行为在三平台保持一致 + +### 性能验收 + +- [ ] **基础性能指标** + - 单次调用延迟 < 10ms(所有平台) + - 内存使用稳定,无明显泄漏 + - 应用启动时间在可接受范围内 + +- [ ] **跨平台性能对比** + - 记录三平台的性能基准数据 + - 分析平台间的性能差异 + - 确保没有明显的性能退化 + +### 质量验收 + +- [ ] **代码质量** + - 通过静态分析检查(所有平台) + - 代码覆盖率达到基本要求 + - 文档完整且准确 + +- [ ] **构建系统** + - 三平台的自动化构建成功 + - 统一的测试脚本正常运行 + - CI/CD 流程可以正常执行 + +## 🎯 输出成果 + +### 1. 代码成果 + +- **完整的三平台支持** + - macOS(已完成)+ iOS + Android 的完整实现 + - 统一的 API 接口和一致的行为 + - 跨平台的构建和测试系统 + +- **平台特定实现** + - iOS 的 JavaScriptCore.framework 集成 + - Android 的 JNI + JSC 移植版本集成 + - 各平台的 DeviceInfo 模块实现 + +### 2. 文档成果 + +- **跨平台构建指南** + - 详细的环境配置说明 + - 三平台的构建步骤 + - 常见问题和解决方案 + +- **技术架构文档** + - 跨平台架构设计说明 + - 平台差异和处理策略 + - 性能对比和分析报告 + +### 3. 博客文章 + +- **《从零实现 React Native (2): 跨平台架构实现》** + - 跨平台技术挑战和解决方案 + - iOS 和 Android 平台的适配经验 + - JavaScriptCore 在不同平台的集成方式 + - 构建系统的统一设计思路 + +## ⏱️ 时间规划 + +| 任务 | 预估时间 | 主要工作内容 | 依赖关系 | +|------|---------|-------------|----------| +| 任务1: iOS 平台支持 | **0.5天** | Xcode 配置 + 功能验证 | 无 | +| 任务2: Android 平台集成 | **3天** | JNI + JSC 移植 + 构建系统 | 无 | +| 任务3: 跨平台测试验证 | **1天** | 统一测试 + 文档完善 | 依赖任务1,2 | + +**总计: 4.5天** (相比原 ROADMAP 的 3-4周,大幅简化和聚焦) + +### 📋 执行建议 + +**Day 1: iOS 快速适配** +- 上午:iOS 构建系统配置 +- 下午:功能验证和测试 + +**Day 2-4: Android 深度集成** +- Day 2:构建系统和 JSC 集成 +- Day 3:JNI 桥接和 Native 层实现 +- Day 4:Java 层封装和应用示例 + +**Day 5: 跨平台验证** +- 上午:统一测试套件运行 +- 下午:文档完善和成果整理 + +## 🚀 下一步计划 + +完成阶段2后,将进入阶段3(视图渲染系统),重点关注: + +- Shadow Tree 虚拟 DOM 机制 +- Yoga 布局引擎集成 +- 基础组件实现(View, Text, Image) +- 事件系统的完善 + +这将标志着从基础通信向完整 UI 系统的重要跃进。 + +## 📱 跨平台支持总结 + +### ✅ macOS 支持 (Phase 1 已完成) +- 完整实现并测试通过 +- 使用系统 JavaScriptCore.framework +- 作为主要开发和验证平台 + +### 🍎 iOS 支持 (本阶段) +- **实施时间**: 0.5天 +- **技术复杂度**: 低 +- **主要优势**: 与 macOS 共享 JavaScriptCore.framework + +### 🤖 Android 支持 (本阶段) +- **实施时间**: 3天 +- **技术复杂度**: 中高 +- **主要挑战**: JNI 集成 + JSC 移植版本适配 + +这将为后续的视图渲染系统提供坚实的跨平台基础。 \ No newline at end of file diff --git a/docs/roadmap.md b/docs/roadmap.md index 16413e6..78b1f53 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -104,36 +104,45 @@ --- -### 阶段 2: JavaScript 引擎深度集成 + 跨平台支持 +### 阶段 2: 跨平台支持 (简化版) -**目标:** 深入理解 JS 引擎在 RN 中的作用和优化,完善跨平台支持 +**目标:** 实现完整的跨平台支持,专注于核心功能而非性能优化 **重要性:** ⭐⭐⭐⭐⭐ #### 核心任务 -1. **引擎选择和集成** - - JavaScriptCore vs Hermes 性能对比 - - 引擎启动和内存管理优化 - - 多线程环境下的 JS 执行 - - 引擎配置和调优 +1. **iOS 平台支持完成** + - 利用与 macOS 共享的 JavaScriptCore.framework + - iOS 构建系统配置和验证 + - DeviceInfo 模块的 iOS 适配 -2. **跨平台支持完善** - - Android 平台适配 (JNI 集成、JSC 移植版本) - - iOS 和 Android 的构建系统统一 - - 平台特定优化和性能调优 - - 跨平台兼容性测试 +2. **Android 平台集成** + - JNI 集成和 JSC 移植版本适配 + - Android 构建系统 (CMake + Gradle) + - DeviceInfo 模块的 Android 实现 -3. **高级特性实现** - - JS 异常处理和错误边界 - - 调试接口集成 (Chrome DevTools) - - 热重载机制的基础支持 - - 内存泄漏检测 +3. **跨平台统一** + - 三平台统一的构建和测试流程 + - API 一致性验证 + - 性能基准对比 + +#### 简化说明 + +**移除的复杂任务:** +- ❌ JavaScriptCore vs Hermes 性能对比(继续使用 JSC) +- ❌ 引擎深度优化(当前性能已满足需求) +- ❌ 高级特性(调试接口、热重载等作为后续可选项) + +**专注核心价值:** +- ✅ 跨平台架构的理解和实现 +- ✅ 不同平台的技术差异处理 +- ✅ 统一构建系统的设计 #### 输出成果 -- 性能优化的 JS 引擎集成 - 完整的三平台支持 (macOS + iOS + Android) -- 技术博客:《从零实现 React Native (2): JavaScript 引擎集成与跨平台架构》 +- 跨平台构建和测试文档 +- 技术博客:《从零实现 React Native (2): 跨平台架构实现》 --- @@ -274,20 +283,20 @@ | 阶段 | 预估时间 | 关键里程碑 | |------|---------|-----------| | 阶段 1: Bridge 通信 | 2-3 周 | 完成双向通信 Demo ✅ | -| 阶段 2: JS 引擎集成 + 跨平台 | 3-4 周 | 三平台支持 + JS 优化 | +| 阶段 2: 跨平台支持 (简化版) | **4.5天** | 三平台支持完成 | | 阶段 3: 视图渲染 | 4-5 周 | 基础组件渲染 | | 阶段 4: 新架构迁移 | 3-4 周 | JSI 架构对比 | | 阶段 5: 工具链完善 | 2-3 周 | 生产级项目 | -**总计: 14-19 周** (约 3.5-4.5 个月) +**总计: 12-17 周** (约 3-4 个月,比原计划缩短 2周) ## 📱 跨平台支持时间线 | 平台 | 支持时间 | 技术复杂度 | 主要工作内容 | |------|---------|-----------|-------------| | ✅ **macOS** | 已完成 | 低 | 系统 JavaScriptCore.framework | -| 🍎 **iOS** | 任务4期间 (0.5天) | 低 | 构建配置 + 兼容性验证 | -| 🤖 **Android** | 阶段2期间 (2-3天) | 中高 | JNI 集成 + JSC 移植版本 | +| 🍎 **iOS** | 阶段2期间 (0.5天) | 低 | 构建配置 + 兼容性验证 | +| 🤖 **Android** | 阶段2期间 (3天) | 中高 | JNI 集成 + JSC 移植版本 | --- From c2b7ce70a96b47b5ccb66acad7490959754616e0 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 14:26:41 +0800 Subject: [PATCH 02/11] feat: add iOS platform support with cross-platform build system - Add iOS platform detection and conditional compilation in CMakeLists.txt - Implement iOS-specific DeviceInfo module using Foundation APIs - Add iOS device and simulator build targets to Makefile - Support platform-specific framework linking (IOKit for macOS, UIKit for iOS) - Set appropriate deployment targets (macOS 10.15+, iOS 12.0+) - Create separate build directories for iOS device (build_ios) and simulator (build_ios_sim) - Maintain backward compatibility with existing macOS build system --- .gitignore | 2 + CMakeLists.txt | 54 +++++++---- Makefile | 50 +++++++++- .../modules/deviceinfo/DeviceInfoModule.mm | 97 +++++++++++++++++++ 4 files changed, 183 insertions(+), 20 deletions(-) create mode 100644 src/ios/modules/deviceinfo/DeviceInfoModule.mm diff --git a/.gitignore b/.gitignore index c3ff7ba..e104be5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ build/ dist/ out/ +build_ios/ +build_ios_sim/ # IDE and editor files .vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 11a6b73..72a4d7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,9 +31,17 @@ set(COMMON_SOURCES # 平台特定源文件 if(APPLE) - set(PLATFORM_SOURCES - src/macos/modules/deviceinfo/DeviceInfoModule.mm - ) + # 根据具体平台选择源文件 + if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") + set(PLATFORM_SOURCES + src/ios/modules/deviceinfo/DeviceInfoModule.mm + ) + else() + # macOS + set(PLATFORM_SOURCES + src/macos/modules/deviceinfo/DeviceInfoModule.mm + ) + endif() # 设置 Objective-C++ 编译标志 set_source_files_properties(${PLATFORM_SOURCES} PROPERTIES COMPILE_FLAGS "-fobjc-arc") @@ -63,37 +71,45 @@ if(APPLE) message(FATAL_ERROR "JavaScriptCore framework not found") endif() - # 查找并链接 IOKit 框架 (DeviceInfo 模块需要) - find_library(IOKIT_FRAMEWORK IOKit) - if(NOT IOKIT_FRAMEWORK) - message(FATAL_ERROR "IOKit framework not found") - endif() - - # 查找并链接 Foundation 框架 + # 查找并链接 Foundation 框架 (所有 Apple 平台共用) find_library(FOUNDATION_FRAMEWORK Foundation) if(NOT FOUNDATION_FRAMEWORK) message(FATAL_ERROR "Foundation framework not found") endif() + # 平台特定框架 + if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") + # iOS 特定框架 + find_library(UIKIT_FRAMEWORK UIKit) + if(NOT UIKIT_FRAMEWORK) + message(FATAL_ERROR "UIKit framework not found") + endif() + set(PLATFORM_FRAMEWORKS ${UIKIT_FRAMEWORK}) + else() + # macOS 特定框架 + find_library(IOKIT_FRAMEWORK IOKit) + if(NOT IOKIT_FRAMEWORK) + message(FATAL_ERROR "IOKit framework not found") + endif() + set(PLATFORM_FRAMEWORKS ${IOKIT_FRAMEWORK}) + endif() + # 链接所需框架 target_link_libraries(mini_react_native ${JAVASCRIPTCORE_FRAMEWORK} - ${IOKIT_FRAMEWORK} ${FOUNDATION_FRAMEWORK} + ${PLATFORM_FRAMEWORKS} ) - # macOS 特定设置 - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # 平台特定部署目标设置 + if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") + set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0") + message(STATUS "Building for iOS with deployment target: ${CMAKE_OSX_DEPLOYMENT_TARGET}") + elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15") message(STATUS "Building for macOS with deployment target: ${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() - # iOS 特定设置 (暂时注释,专注 macOS) - # if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") - # set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") - # message(STATUS "Building for iOS with deployment target: ${CMAKE_OSX_DEPLOYMENT_TARGET}") - # endif() - elseif(ANDROID) # Android 配置 (未来实现) message(STATUS "Android build configuration - TODO") diff --git a/Makefile b/Makefile index dd1d6dd..00793c9 100644 --- a/Makefile +++ b/Makefile @@ -53,6 +53,48 @@ build: js-build configure @cd $(BUILD_DIR) && make -j$(CORES) @echo "✅ Build complete" +# iOS 构建配置 +.PHONY: ios-configure +ios-configure: + @echo "🔧 Configuring iOS build system..." + @mkdir -p $(BUILD_DIR)_ios + @cd $(BUILD_DIR)_ios && DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer cmake \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES=arm64 \ + -DCMAKE_OSX_SYSROOT=$$(DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcrun --sdk iphoneos --show-sdk-path) \ + -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + .. + @echo "✅ iOS configuration complete" + +# iOS 模拟器构建配置 +.PHONY: ios-sim-configure +ios-sim-configure: + @echo "🔧 Configuring iOS Simulator build system..." + @mkdir -p $(BUILD_DIR)_ios_sim + @cd $(BUILD_DIR)_ios_sim && DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer cmake \ + -DCMAKE_SYSTEM_NAME=iOS \ + -DCMAKE_OSX_ARCHITECTURES=x86_64 \ + -DCMAKE_OSX_SYSROOT=$$(DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcrun --sdk iphonesimulator --show-sdk-path) \ + -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + .. + @echo "✅ iOS Simulator configuration complete" + +# 构建 iOS 版本 +.PHONY: ios-build +ios-build: js-build ios-configure + @echo "🔨 Building Mini React Native for iOS..." + @cd $(BUILD_DIR)_ios && make -j$(CORES) + @echo "✅ iOS build complete" + +# 构建 iOS 模拟器版本 +.PHONY: ios-sim-build +ios-sim-build: js-build ios-sim-configure + @echo "🔨 Building Mini React Native for iOS Simulator..." + @cd $(BUILD_DIR)_ios_sim && make -j$(CORES) + @echo "✅ iOS Simulator build complete" + # 运行测试 # 执行顺序:configure → build → test .PHONY: test @@ -91,7 +133,7 @@ test-integration: build .PHONY: clean clean: js-clean @echo "🧹 Cleaning build files..." - @rm -rf $(BUILD_DIR) + @rm -rf $(BUILD_DIR) $(BUILD_DIR)_ios $(BUILD_DIR)_ios_sim @echo "✅ Clean complete" # 完全重建 @@ -160,6 +202,12 @@ help: @echo " make rebuild - 完全重新构建" @echo " make configure - 仅配置 CMake" @echo "" + @echo "iOS 构建命令:" + @echo " make ios-build - 构建 iOS 设备版本" + @echo " make ios-sim-build - 构建 iOS 模拟器版本" + @echo " make ios-configure - 仅配置 iOS 构建" + @echo " make ios-sim-configure - 仅配置 iOS 模拟器构建" + @echo "" @echo "测试命令:" @echo " make test - 运行所有测试" @echo " make test-basic - 仅运行基础功能测试" diff --git a/src/ios/modules/deviceinfo/DeviceInfoModule.mm b/src/ios/modules/deviceinfo/DeviceInfoModule.mm new file mode 100644 index 0000000..6b0fa47 --- /dev/null +++ b/src/ios/modules/deviceinfo/DeviceInfoModule.mm @@ -0,0 +1,97 @@ +#include "common/modules/DeviceInfoModule.h" +#import +#include +#include +#include "common/utils/JSONParser.h" + +// 使用最小依赖,避免 UIKit 冲突 +#ifdef __OBJC__ +#import +#endif + +namespace mini_rn { +namespace modules { + +// 构造函数 +DeviceInfoModule::DeviceInfoModule() {} + +// NativeModule 接口实现 +std::string DeviceInfoModule::getName() const { return "DeviceInfo"; } + +std::vector DeviceInfoModule::getMethods() const { + return { + "getUniqueId", // methodId = 0 + "getSystemVersion", // methodId = 1 + "getDeviceId" // methodId = 2 + }; +} + +void DeviceInfoModule::invoke(const std::string& methodName, const std::string& args, int callId) { + try { + if (methodName == "getUniqueId") { + std::string uniqueId = getUniqueIdImpl(); + sendSuccessCallback(callId, uniqueId); + } else { + sendErrorCallback(callId, "Unknown method: " + methodName); + } + } catch (const std::exception& e) { + sendErrorCallback(callId, "Method invocation failed: " + std::string(e.what())); + } +} + +// iOS 平台特定实现 +std::string DeviceInfoModule::getUniqueIdImpl() const { + @autoreleasepool { + // iOS 简化实现:使用 NSUUID 生成唯一标识 + // 注意:这个实现每次启动都会生成新的ID,适用于MVP测试 + NSUUID* uuid = [NSUUID UUID]; + NSString* uuidString = [uuid UUIDString]; + return [uuidString UTF8String]; + } +} + +std::string DeviceInfoModule::getSystemVersionImpl() const { + @autoreleasepool { + // iOS 简化实现:使用 NSProcessInfo 获取系统版本(避免 UIDevice 依赖) + NSProcessInfo* processInfo = [NSProcessInfo processInfo]; + NSOperatingSystemVersion version = [processInfo operatingSystemVersion]; + + std::ostringstream oss; + oss << version.majorVersion << "." << version.minorVersion << "." << version.patchVersion; + + return oss.str(); + } +} + +std::string DeviceInfoModule::getDeviceIdImpl() const { + @autoreleasepool { + // iOS 简化实现:直接使用 sysctl 获取设备型号(避免 UIDevice 依赖) + size_t size = 0; + sysctlbyname("hw.machine", nullptr, &size, nullptr, 0); + + if (size > 0) { + std::vector buffer(size); + if (sysctlbyname("hw.machine", buffer.data(), &size, nullptr, 0) == 0) { + return std::string(buffer.data()); + } + } + + // 备选方案:iOS 模拟器标识 + return "iOS-Simulator"; + } +} + +// 工具方法实现 - sendSuccessCallback 和 sendErrorCallback 现在由基类提供 + +std::string DeviceInfoModule::createSuccessResponse(const std::string& data) const { + // React Native 回调约定:直接返回数据,不需要包装对象 + return data; +} + +std::string DeviceInfoModule::createErrorResponse(const std::string& error) const { + // React Native 回调约定:直接返回错误消息 + return error; +} + +} // namespace modules +} // namespace mini_rn \ No newline at end of file From f9437ae7453df96b52e10c3d38cb3dae7d867e13 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 15:18:08 +0800 Subject: [PATCH 03/11] feat: add iOS DeviceInfo test and testing script - Introduced a new executable for testing the DeviceInfo module on iOS. - Added a comprehensive iOS testing script (`test_ios.sh`) to facilitate running various tests on the iOS simulator. - Created documentation (`iOS_TESTING.md`) detailing the testing process and available test types. - Implemented a sample test for the DeviceInfo module to verify functionality and performance metrics. --- CMakeLists.txt | 5 + docs/iOS_TESTING.md | 219 ++++++++++++++++++++++++++++ examples/test_ios_deviceinfo.cpp | 82 +++++++++++ test_ios.sh | 243 +++++++++++++++++++++++++++++++ 4 files changed, 549 insertions(+) create mode 100644 docs/iOS_TESTING.md create mode 100644 examples/test_ios_deviceinfo.cpp create mode 100755 test_ios.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 72a4d7c..f255069 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,11 @@ add_executable(test_integration examples/test_integration.cpp) target_include_directories(test_integration PRIVATE src) target_link_libraries(test_integration mini_react_native) +# iOS DeviceInfo 测试可执行文件 +add_executable(test_ios_deviceinfo examples/test_ios_deviceinfo.cpp) +target_include_directories(test_ios_deviceinfo PRIVATE src) +target_link_libraries(test_ios_deviceinfo mini_react_native) + # 安装配置(make install 时才会执行) # 安装静态库到 /usr/local/lib 下 install(TARGETS mini_react_native diff --git a/docs/iOS_TESTING.md b/docs/iOS_TESTING.md new file mode 100644 index 0000000..14a32de --- /dev/null +++ b/docs/iOS_TESTING.md @@ -0,0 +1,219 @@ +# iOS 测试指南 + +本文档描述如何在 iOS 模拟器上测试 Mini React Native 的功能。 + +## 🍎 iOS 测试脚本 + +项目提供了一个便捷的 iOS 测试脚本 `test_ios.sh`,可以在 iOS 模拟器中运行各种测试。 + +### 快速开始 + +```bash +# 运行所有 iOS 测试 +./test_ios.sh all + +# 运行特定测试 +./test_ios.sh deviceinfo + +# 查看帮助 +./test_ios.sh help +``` + +### 使用 Makefile + +```bash +# 仅构建 iOS 版本 +make ios-sim-build +``` + +## 📋 可用测试 + +| 测试类型 | 命令 | 描述 | +|---------|------|------| +| **基础功能** | `./test_ios.sh basic` | 验证 JSCExecutor 基础功能 | +| **DeviceInfo** | `./test_ios.sh deviceinfo` | 测试 iOS 设备信息获取和性能 | +| **模块框架** | `./test_ios.sh module` | 验证模块注册和调用机制 | +| **集成测试** | `./test_ios.sh integration` | 完整 JavaScript ↔ Native 通信 | +| **全部测试** | `./test_ios.sh all` | 运行所有测试 | + +## 🔧 环境要求 + +### 必需软件 +- **Xcode** (完整版本,包含 iOS SDK) +- **iOS 模拟器** (通过 Xcode 安装) +- **CMake** 3.15+ +- **Node.js** (用于 JavaScript 构建) + +### 验证环境 +```bash +# 检查 Xcode 和 iOS SDK +xcodebuild -showsdks | grep iOS + +# 列出可用的 iOS 模拟器 +xcrun simctl list devices available | grep iPhone +``` + +## 📱 模拟器管理 + +### 使用默认模拟器 +脚本默认使用 `iPhone 16 Pro` 模拟器。 + +### 使用自定义模拟器 +```bash +# 列出可用模拟器 +./test_ios.sh list + +# 在指定模拟器上运行测试 +./test_ios.sh deviceinfo "iPhone 15 Pro" +``` + +### 手动管理模拟器 +```bash +# 启动模拟器 +xcrun simctl boot "iPhone 16 Pro" + +# 关闭模拟器 +xcrun simctl shutdown "iPhone 16 Pro" + +# 查看模拟器状态 +xcrun simctl list devices +``` + +## 📊 测试结果解读 + +### DeviceInfo 测试示例 +``` +=== iOS DeviceInfo Module Test === + +2. Testing DeviceInfo methods directly... + UniqueId: F67EDB44-DA12-45E3-800D-800BBB7F1FC6 + SystemVersion: 18.5.0 + DeviceId: x86_64 + +5. Performance Results: + Bridge call duration: 17.776 ms + ⚠️ Performance slower than expected (>= 10ms) +``` + +### 结果说明 +- **UniqueId**: iOS 模拟器的唯一标识符 (每次重新生成) +- **SystemVersion**: iOS 系统版本 (模拟器版本) +- **DeviceId**: 设备架构 (`x86_64` 为模拟器, `arm64` 为真机) +- **Performance**: Bridge 调用性能 (模拟器通常较慢) + +## 🔍 性能基准 + +| 平台 | Bridge 调用耗时 | 状态 | +|------|---------------|------| +| **macOS** | ~2ms | ✅ 优秀 | +| **iOS 模拟器** | ~18ms | ⚠️ 可接受 | +| **iOS 真机** | ~5ms | ✅ 良好 (预期) | + +> **注意**: iOS 模拟器性能较慢是正常的,真机性能会明显更好。 + +## 🐛 常见问题 + +### 1. 模拟器启动失败 +```bash +# 检查可用模拟器 +./test_ios.sh list + +# 手动启动模拟器 +xcrun simctl boot "iPhone 16 Pro" +``` + +### 2. iOS SDK 不可用 +```bash +# 检查 Xcode 安装 +xcode-select -p + +# 安装 iOS SDK (通过 Xcode) +open /Applications/Xcode.app +``` + +### 3. 构建失败 +```bash +# 清理并重新构建 +make clean +make ios-sim-build +``` + +### 4. JavaScript bundle 错误 +```bash +# 重新构建 JavaScript +make js-build + +# 或完整重建 +make ios-test +``` + +## 🚀 高级用法 + +### 自定义测试脚本 +```bash +# 创建自定义测试 +cat > my_ios_test.sh << 'EOF' +#!/bin/bash +export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer + +# 启动模拟器 +xcrun simctl boot "iPhone 16 Pro" + +# 运行自定义测试 +xcrun simctl spawn "iPhone 16 Pro" ./build_ios_sim/my_test.app/my_test + +# 关闭模拟器 +xcrun simctl shutdown "iPhone 16 Pro" +EOF + +chmod +x my_ios_test.sh +``` + +### 性能分析 +```bash +# 使用 Instruments 进行性能分析 +xcrun instruments -t "Time Profiler" -D trace.trace ./build_ios_sim/test_ios_deviceinfo.app/test_ios_deviceinfo +``` + +### 批量测试 +```bash +# 在多个模拟器上运行测试 +for sim in "iPhone 15" "iPhone 16" "iPhone 16 Pro"; do + echo "Testing on $sim..." + ./test_ios.sh deviceinfo "$sim" +done +``` + +## 📝 测试报告 + +### 生成测试报告 +```bash +# 运行测试并保存输出 +./test_ios.sh all > ios_test_report.txt 2>&1 + +# 查看报告 +cat ios_test_report.txt +``` + +### 自动化 CI/CD +```yaml +# GitHub Actions 示例 +- name: Run iOS Tests + run: | + make ios-sim-build + ./test_ios.sh all +``` + +## 🎯 下一步 + +- 在真实 iOS 设备上测试 +- 添加更多设备信息测试 +- 实现 iOS 特定功能测试 +- 集成性能监控 + +--- + +**相关文档:** +- [构建指南](../README.md) +- [Phase 2 计划](PHASE2_PLAN.md) +- [技术路线图](ROADMAP.md) \ No newline at end of file diff --git a/examples/test_ios_deviceinfo.cpp b/examples/test_ios_deviceinfo.cpp new file mode 100644 index 0000000..0ab0291 --- /dev/null +++ b/examples/test_ios_deviceinfo.cpp @@ -0,0 +1,82 @@ +#include +#include +#include "common/bridge/JSCExecutor.h" +#include "common/modules/DeviceInfoModule.h" + +using namespace mini_rn::bridge; +using namespace mini_rn::modules; + +int main() { + std::cout << "Mini React Native - iOS DeviceInfo Test" << std::endl; + std::cout << "This test verifies DeviceInfo module on iOS platform" << std::endl; + std::cout << std::endl; + + std::cout << "=== iOS DeviceInfo Module Test ===" << std::endl; + + try { + // 1. 创建 JSCExecutor + std::cout << "\n1. Creating JSCExecutor..." << std::endl; + auto executor = std::make_unique(); + + // 2. 创建 DeviceInfo 模块并直接测试 + std::cout << "2. Testing DeviceInfo methods directly..." << std::endl; + auto deviceInfo = std::make_unique(); + + std::cout << " UniqueId: " << deviceInfo->getUniqueIdImpl() << std::endl; + std::cout << " SystemVersion: " << deviceInfo->getSystemVersionImpl() << std::endl; + std::cout << " DeviceId: " << deviceInfo->getDeviceIdImpl() << std::endl; + + // 3. 注册模块到 JSCExecutor + std::cout << "\n3. Registering DeviceInfo module..." << std::endl; + std::vector> modules; + modules.push_back(std::move(deviceInfo)); + executor->registerModules(std::move(modules)); + + // 4. 测试同步调用性能 + std::cout << "\n4. Testing Bridge communication performance..." << std::endl; + + auto start = std::chrono::high_resolution_clock::now(); + + std::string testScript = R"( + // 测试 iOS DeviceInfo 方法 + console.log('🍎 iOS DeviceInfo Bridge 测试开始...'); + + try { + // getSystemVersion (methodId = 1) + var systemVersion = global.nativeCallSyncHook(0, 1, []); + console.log('✅ iOS SystemVersion:', systemVersion); + + // getDeviceId (methodId = 2) + var deviceId = global.nativeCallSyncHook(0, 2, []); + console.log('✅ iOS DeviceId:', deviceId); + + console.log('🎉 iOS DeviceInfo 测试成功!'); + } catch (e) { + console.log('❌ 测试失败:', e.toString()); + } + )"; + + executor->loadApplicationScript(testScript, "ios_deviceinfo_test.js"); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + std::cout << "\n5. Performance Results:" << std::endl; + std::cout << " Bridge call duration: " << duration.count() / 1000.0 << " ms" << std::endl; + + if (duration.count() / 1000.0 < 10.0) { + std::cout << " ✅ Performance requirement met (< 10ms)" << std::endl; + } else { + std::cout << " ⚠️ Performance slower than expected (>= 10ms)" << std::endl; + } + + std::cout << "\n6. iOS DeviceInfo test completed successfully!" << std::endl; + + } catch (const std::exception& e) { + std::cout << "❌ Test failed: " << e.what() << std::endl; + return 1; + } + + std::cout << "\n===========================================" << std::endl; + return 0; +} \ No newline at end of file diff --git a/test_ios.sh b/test_ios.sh new file mode 100755 index 0000000..5dcc559 --- /dev/null +++ b/test_ios.sh @@ -0,0 +1,243 @@ +#!/bin/bash + +# iOS 测试脚本 +# 用于在 iOS 模拟器上运行各种测试 + +set -e # 遇到错误时退出 + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +# 设置 Xcode 开发者目录 +export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer + +# 默认模拟器 +DEFAULT_SIMULATOR="iPhone 16 Pro" +SIMULATOR="${2:-$DEFAULT_SIMULATOR}" + +# 打印带颜色的消息 +print_header() { + echo -e "${BLUE}===============================================${NC}" + echo -e "${BLUE}🍎 Mini React Native - iOS 测试脚本${NC}" + echo -e "${BLUE}===============================================${NC}" +} + +print_info() { + echo -e "${CYAN}ℹ️ $1${NC}" +} + +print_success() { + echo -e "${GREEN}✅ $1${NC}" +} + +print_warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +print_error() { + echo -e "${RED}❌ $1${NC}" +} + +# 检查 iOS 构建是否存在 +check_ios_build() { + if [ ! -d "build_ios_sim" ]; then + print_error "iOS 模拟器构建不存在!" + print_info "请先运行: make ios-sim-build" + exit 1 + fi +} + +# 检查模拟器是否可用 +check_simulator() { + print_info "检查模拟器: $SIMULATOR" + + if ! xcrun simctl list devices available | grep -q "$SIMULATOR"; then + print_error "模拟器 '$SIMULATOR' 不可用!" + print_info "可用的模拟器:" + xcrun simctl list devices available | grep iPhone | head -5 + exit 1 + fi + + print_success "模拟器 '$SIMULATOR' 可用" +} + +# 启动模拟器 +boot_simulator() { + print_info "启动模拟器: $SIMULATOR" + + # 检查模拟器是否已经启动 + if xcrun simctl list devices | grep "$SIMULATOR" | grep -q "Booted"; then + print_success "模拟器已经启动" + else + print_info "正在启动模拟器..." + xcrun simctl boot "$SIMULATOR" + print_success "模拟器启动成功" + + # 等待模拟器完全启动 + print_info "等待模拟器完全启动..." + sleep 3 + fi +} + +# 运行测试 +run_test() { + local test_name=$1 + local test_path=$2 + local description=$3 + + echo + print_info "🧪 运行测试: $test_name" + print_info "📝 描述: $description" + echo -e "${PURPLE}----------------------------------------${NC}" + + if [ ! -f "$test_path" ]; then + print_error "测试文件不存在: $test_path" + return 1 + fi + + # 运行测试 + if xcrun simctl spawn "$SIMULATOR" "$test_path"; then + echo -e "${PURPLE}----------------------------------------${NC}" + print_success "$test_name 测试完成" + else + echo -e "${PURPLE}----------------------------------------${NC}" + print_error "$test_name 测试失败" + return 1 + fi +} + +# 显示帮助信息 +show_help() { + print_header + echo + echo -e "${YELLOW}用法:${NC}" + echo " $0 [simulator_name]" + echo + echo -e "${YELLOW}测试类型:${NC}" + echo " basic - 基础功能测试 (JSCExecutor)" + echo " deviceinfo - DeviceInfo 模块测试" + echo " module - 模块框架测试" + echo " integration - 完整集成测试" + echo " all - 运行所有测试" + echo " list - 列出可用的模拟器" + echo + echo -e "${YELLOW}示例:${NC}" + echo " $0 deviceinfo # 在默认模拟器上运行 DeviceInfo 测试" + echo " $0 all \"iPhone 15 Pro\" # 在指定模拟器上运行所有测试" + echo " $0 list # 列出可用模拟器" + echo + echo -e "${YELLOW}默认模拟器:${NC} $DEFAULT_SIMULATOR" + echo +} + +# 列出可用模拟器 +list_simulators() { + print_header + print_info "可用的 iOS 模拟器:" + echo + xcrun simctl list devices available | grep -E "(iPhone|iPad)" | head -10 + echo +} + +# 运行所有测试 +run_all_tests() { + print_header + print_info "在模拟器 '$SIMULATOR' 上运行所有测试" + echo + + check_ios_build + check_simulator + boot_simulator + + local failed_tests=0 + + # 基础测试 + if ! run_test "基础功能" "./build_ios_sim/mini_rn_test.app/mini_rn_test" "验证 JSCExecutor 基础功能"; then + ((failed_tests++)) + fi + + # DeviceInfo 测试 + if ! run_test "DeviceInfo" "./build_ios_sim/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能"; then + ((failed_tests++)) + fi + + # 模块框架测试 + if ! run_test "模块框架" "./build_ios_sim/test_module_framework.app/test_module_framework" "验证模块注册和调用机制"; then + ((failed_tests++)) + fi + + # 集成测试 + if ! run_test "集成测试" "./build_ios_sim/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试"; then + ((failed_tests++)) + fi + + # 测试总结 + echo + echo -e "${BLUE}===============================================${NC}" + if [ $failed_tests -eq 0 ]; then + print_success "🎉 所有测试通过!iOS 平台功能正常" + else + print_warning "⚠️ $failed_tests 个测试失败" + fi + echo -e "${BLUE}===============================================${NC}" + + return $failed_tests +} + +# 主函数 +main() { + case "${1:-help}" in + "basic") + print_header + check_ios_build + check_simulator + boot_simulator + run_test "基础功能" "./build_ios_sim/mini_rn_test.app/mini_rn_test" "验证 JSCExecutor 基础功能" + ;; + "deviceinfo") + print_header + check_ios_build + check_simulator + boot_simulator + run_test "DeviceInfo" "./build_ios_sim/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能" + ;; + "module") + print_header + check_ios_build + check_simulator + boot_simulator + run_test "模块框架" "./build_ios_sim/test_module_framework.app/test_module_framework" "验证模块注册和调用机制" + ;; + "integration") + print_header + check_ios_build + check_simulator + boot_simulator + run_test "集成测试" "./build_ios_sim/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试" + ;; + "all") + run_all_tests + ;; + "list") + list_simulators + ;; + "help"|"--help"|"-h"|"") + show_help + ;; + *) + print_error "未知的测试类型: $1" + echo + show_help + exit 1 + ;; + esac +} + +# 运行主函数 +main "$@" \ No newline at end of file From 8756637c4ee05c5f5b1fbcc2b8b729fce9c93282 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 16:53:50 +0800 Subject: [PATCH 04/11] refactor: streamline iOS build and testing process - Consolidated iOS build configurations by removing separate simulator build targets in the Makefile. - Updated the iOS testing script to reference the unified build directory for iOS. - Enhanced documentation in the Makefile to reflect changes in build and test commands for iOS. - Introduced new test targets for running comprehensive iOS tests directly from the Makefile. --- Makefile | 49 +++++++++++++++++++++---------------------------- test_ios.sh | 22 +++++++++++----------- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 00793c9..3f9c18e 100644 --- a/Makefile +++ b/Makefile @@ -53,47 +53,38 @@ build: js-build configure @cd $(BUILD_DIR) && make -j$(CORES) @echo "✅ Build complete" -# iOS 构建配置 +# iOS 构建配置(模拟器) .PHONY: ios-configure ios-configure: @echo "🔧 Configuring iOS build system..." @mkdir -p $(BUILD_DIR)_ios @cd $(BUILD_DIR)_ios && DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer cmake \ -DCMAKE_SYSTEM_NAME=iOS \ - -DCMAKE_OSX_ARCHITECTURES=arm64 \ - -DCMAKE_OSX_SYSROOT=$$(DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcrun --sdk iphoneos --show-sdk-path) \ - -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - .. - @echo "✅ iOS configuration complete" - -# iOS 模拟器构建配置 -.PHONY: ios-sim-configure -ios-sim-configure: - @echo "🔧 Configuring iOS Simulator build system..." - @mkdir -p $(BUILD_DIR)_ios_sim - @cd $(BUILD_DIR)_ios_sim && DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer cmake \ - -DCMAKE_SYSTEM_NAME=iOS \ - -DCMAKE_OSX_ARCHITECTURES=x86_64 \ + -DCMAKE_OSX_ARCHITECTURES=$$(uname -m) \ -DCMAKE_OSX_SYSROOT=$$(DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcrun --sdk iphonesimulator --show-sdk-path) \ -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ .. - @echo "✅ iOS Simulator configuration complete" + @echo "✅ iOS configuration complete" -# 构建 iOS 版本 +# 构建 iOS 版本(模拟器) .PHONY: ios-build ios-build: js-build ios-configure @echo "🔨 Building Mini React Native for iOS..." @cd $(BUILD_DIR)_ios && make -j$(CORES) @echo "✅ iOS build complete" -# 构建 iOS 模拟器版本 -.PHONY: ios-sim-build -ios-sim-build: js-build ios-sim-configure - @echo "🔨 Building Mini React Native for iOS Simulator..." - @cd $(BUILD_DIR)_ios_sim && make -j$(CORES) - @echo "✅ iOS Simulator build complete" +# iOS 测试目标 +.PHONY: ios-test +ios-test: ios-build + @echo "🍎 Running iOS tests..." + @./test_ios.sh all + +# iOS DeviceInfo 测试 +.PHONY: ios-test-deviceinfo +ios-test-deviceinfo: ios-build + @echo "🍎 Running iOS DeviceInfo test..." + @./test_ios.sh deviceinfo # 运行测试 # 执行顺序:configure → build → test @@ -133,7 +124,7 @@ test-integration: build .PHONY: clean clean: js-clean @echo "🧹 Cleaning build files..." - @rm -rf $(BUILD_DIR) $(BUILD_DIR)_ios $(BUILD_DIR)_ios_sim + @rm -rf $(BUILD_DIR) $(BUILD_DIR)_ios @echo "✅ Clean complete" # 完全重建 @@ -203,10 +194,12 @@ help: @echo " make configure - 仅配置 CMake" @echo "" @echo "iOS 构建命令:" - @echo " make ios-build - 构建 iOS 设备版本" - @echo " make ios-sim-build - 构建 iOS 模拟器版本" + @echo " make ios-build - 构建 iOS 版本(模拟器)" @echo " make ios-configure - 仅配置 iOS 构建" - @echo " make ios-sim-configure - 仅配置 iOS 模拟器构建" + @echo "" + @echo "iOS 测试命令:" + @echo " make ios-test - 运行所有 iOS 测试" + @echo " make ios-test-deviceinfo - 运行 iOS DeviceInfo 测试" @echo "" @echo "测试命令:" @echo " make test - 运行所有测试" diff --git a/test_ios.sh b/test_ios.sh index 5dcc559..77c99b8 100755 --- a/test_ios.sh +++ b/test_ios.sh @@ -46,9 +46,9 @@ print_error() { # 检查 iOS 构建是否存在 check_ios_build() { - if [ ! -d "build_ios_sim" ]; then - print_error "iOS 模拟器构建不存在!" - print_info "请先运行: make ios-sim-build" + if [ ! -d "build_ios" ]; then + print_error "iOS 构建不存在!" + print_info "请先运行: make ios-build" exit 1 fi } @@ -158,22 +158,22 @@ run_all_tests() { local failed_tests=0 # 基础测试 - if ! run_test "基础功能" "./build_ios_sim/mini_rn_test.app/mini_rn_test" "验证 JSCExecutor 基础功能"; then + if ! run_test "基础功能" "./build_ios/mini_rn_test.app/mini_rn_test" "验证 JSCExecutor 基础功能"; then ((failed_tests++)) fi # DeviceInfo 测试 - if ! run_test "DeviceInfo" "./build_ios_sim/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能"; then + if ! run_test "DeviceInfo" "./build_ios/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能"; then ((failed_tests++)) fi # 模块框架测试 - if ! run_test "模块框架" "./build_ios_sim/test_module_framework.app/test_module_framework" "验证模块注册和调用机制"; then + if ! run_test "模块框架" "./build_ios/test_module_framework.app/test_module_framework" "验证模块注册和调用机制"; then ((failed_tests++)) fi # 集成测试 - if ! run_test "集成测试" "./build_ios_sim/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试"; then + if ! run_test "集成测试" "./build_ios/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试"; then ((failed_tests++)) fi @@ -198,28 +198,28 @@ main() { check_ios_build check_simulator boot_simulator - run_test "基础功能" "./build_ios_sim/mini_rn_test.app/mini_rn_test" "验证 JSCExecutor 基础功能" + run_test "基础功能" "./build_ios/mini_rn_test.app/mini_rn_test" "验证 JSCExecutor 基础功能" ;; "deviceinfo") print_header check_ios_build check_simulator boot_simulator - run_test "DeviceInfo" "./build_ios_sim/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能" + run_test "DeviceInfo" "./build_ios/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能" ;; "module") print_header check_ios_build check_simulator boot_simulator - run_test "模块框架" "./build_ios_sim/test_module_framework.app/test_module_framework" "验证模块注册和调用机制" + run_test "模块框架" "./build_ios/test_module_framework.app/test_module_framework" "验证模块注册和调用机制" ;; "integration") print_header check_ios_build check_simulator boot_simulator - run_test "集成测试" "./build_ios_sim/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试" + run_test "集成测试" "./build_ios/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试" ;; "all") run_all_tests From 526d78d2004cb9b6f155138f76d0d83dc549dfc9 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 17:05:14 +0800 Subject: [PATCH 05/11] refactor: remove iOS DeviceInfo test and integrate performance testing into existing integration test - Deleted the standalone iOS DeviceInfo test executable. - Updated the integration test to include performance testing for DeviceInfo methods. - Modified the testing script to reflect changes in test execution and reporting. - Enhanced the integration test output to provide detailed performance metrics. --- .gitignore | 1 - CMakeLists.txt | 4 -- examples/test_integration.cpp | 104 ++++++++++++++++++++++++++++--- examples/test_ios_deviceinfo.cpp | 82 ------------------------ test_ios.sh | 11 +--- 5 files changed, 97 insertions(+), 105 deletions(-) delete mode 100644 examples/test_ios_deviceinfo.cpp diff --git a/.gitignore b/.gitignore index e104be5..25de38b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ build/ dist/ out/ build_ios/ -build_ios_sim/ # IDE and editor files .vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt index f255069..d9a5015 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,10 +137,6 @@ add_executable(test_integration examples/test_integration.cpp) target_include_directories(test_integration PRIVATE src) target_link_libraries(test_integration mini_react_native) -# iOS DeviceInfo 测试可执行文件 -add_executable(test_ios_deviceinfo examples/test_ios_deviceinfo.cpp) -target_include_directories(test_ios_deviceinfo PRIVATE src) -target_link_libraries(test_ios_deviceinfo mini_react_native) # 安装配置(make install 时才会执行) # 安装静态库到 /usr/local/lib 下 diff --git a/examples/test_integration.cpp b/examples/test_integration.cpp index 9621ff6..ffc298b 100644 --- a/examples/test_integration.cpp +++ b/examples/test_integration.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "common/bridge/JSCExecutor.h" #include "common/modules/DeviceInfoModule.h" @@ -58,6 +59,47 @@ std::string readFile(const std::string& filePath) { } } +/** + * 性能测试函数 - 测试 Bridge 通信性能 + * @param executor JSCExecutor 实例 + */ +void performanceTest(JSCExecutor& executor) { + std::cout << "\n3.5. Testing Bridge communication performance..." << std::endl; + + auto start = std::chrono::high_resolution_clock::now(); + + // 执行性能测试脚本 + std::string performanceScript = R"( + // 性能测试:调用 DeviceInfo 方法 + try { + // getSystemVersion (methodId = 1) + var systemVersion = global.nativeCallSyncHook(0, 1, []); + + // getDeviceId (methodId = 2) + var deviceId = global.nativeCallSyncHook(0, 2, []); + + console.log('✅ Performance test completed - SystemVersion:', systemVersion, 'DeviceId:', deviceId); + } catch (e) { + console.log('❌ Performance test failed:', e.toString()); + } + )"; + + executor.loadApplicationScript(performanceScript, "performance_test.js"); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + // 性能报告 + double ms = duration.count() / 1000.0; + std::cout << " Bridge call duration: " << ms << " ms" << std::endl; + + if (ms < 10.0) { + std::cout << " ✅ Performance requirement met (< 10ms)" << std::endl; + } else { + std::cout << " ⚠️ Performance slower than expected (>= 10ms)" << std::endl; + } +} + void testIntegration() { std::cout << "\n=== Mini React Native Integration Test ===" << std::endl; @@ -70,18 +112,41 @@ void testIntegration() { std::cout << "[JS Exception] " << error << std::endl; }); + // 直接测试 DeviceInfo 原生方法 + std::cout << "\n1. Testing DeviceInfo methods directly..." << std::endl; + auto deviceInfoForTesting = std::make_unique(); + std::cout << " UniqueId: " << deviceInfoForTesting->getUniqueIdImpl() << std::endl; + std::cout << " SystemVersion: " << deviceInfoForTesting->getSystemVersionImpl() << std::endl; + std::cout << " DeviceId: " << deviceInfoForTesting->getDeviceIdImpl() << std::endl; + // 注册 DeviceInfo 模块(自动注入配置) - std::cout << "\n1. Registering DeviceInfo module and injecting configuration..." + std::cout << "\n2. Registering DeviceInfo module and injecting configuration..." << std::endl; std::vector> modules; modules.push_back(std::make_unique()); executor.registerModules(std::move(modules)); // 加载打包后的 JavaScript bundle - std::cout << "\n2. Loading JavaScript bundle..." << std::endl; - - std::string bundlePath = "dist/bundle.js"; - std::string bundleScript = readFile(bundlePath); + std::cout << "\n3. Loading JavaScript bundle..." << std::endl; + + // 尝试多个可能的路径(支持不同的工作目录) + std::vector possiblePaths = { + "dist/bundle.js", // 项目根目录 + "../dist/bundle.js", // 从 build 目录 + "../../dist/bundle.js", // 从深层目录 + "/Users/yujiayu02/Dev/Repo/github/mini-react-native/dist/bundle.js" // 绝对路径 + }; + + std::string bundlePath; + std::string bundleScript; + + for (const auto& path : possiblePaths) { + bundleScript = readFile(path); + if (!bundleScript.empty()) { + bundlePath = path; + break; + } + } if (bundleScript.empty()) { std::cout << "[Error] Failed to load JavaScript bundle: " << bundlePath @@ -98,11 +163,30 @@ void testIntegration() { executor.loadApplicationScript(bundleScript, bundlePath); std::cout << " ✓ Bundle executed successfully" << std::endl; - // 加载测试文件 - std::cout << "\n3. Loading DeviceInfo integration test..." << std::endl; + // 性能测试 + performanceTest(executor); - std::string testPath = "examples/scripts/test_deviceinfo.js"; - std::string testScript = readFile(testPath); + // 加载测试文件 + std::cout << "\n4. Loading DeviceInfo integration test..." << std::endl; + + // 尝试多个可能的测试脚本路径 + std::vector possibleTestPaths = { + "examples/scripts/test_deviceinfo.js", // 项目根目录 + "../examples/scripts/test_deviceinfo.js", // 从 build 目录 + "../../examples/scripts/test_deviceinfo.js", // 从深层目录 + "/Users/yujiayu02/Dev/Repo/github/mini-react-native/examples/scripts/test_deviceinfo.js" // 绝对路径 + }; + + std::string testPath; + std::string testScript; + + for (const auto& path : possibleTestPaths) { + testScript = readFile(path); + if (!testScript.empty()) { + testPath = path; + break; + } + } if (testScript.empty()) { std::cout << "[Error] Failed to load test file: " << testPath @@ -117,7 +201,7 @@ void testIntegration() { executor.loadApplicationScript(testScript, testPath); - std::cout << "\n4. Bundle-based JavaScript Test Completed!" << std::endl; + std::cout << "\n5. Integration Test Completed!" << std::endl; std::cout << " Check the JavaScript output above for detailed test results." << std::endl; diff --git a/examples/test_ios_deviceinfo.cpp b/examples/test_ios_deviceinfo.cpp deleted file mode 100644 index 0ab0291..0000000 --- a/examples/test_ios_deviceinfo.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include "common/bridge/JSCExecutor.h" -#include "common/modules/DeviceInfoModule.h" - -using namespace mini_rn::bridge; -using namespace mini_rn::modules; - -int main() { - std::cout << "Mini React Native - iOS DeviceInfo Test" << std::endl; - std::cout << "This test verifies DeviceInfo module on iOS platform" << std::endl; - std::cout << std::endl; - - std::cout << "=== iOS DeviceInfo Module Test ===" << std::endl; - - try { - // 1. 创建 JSCExecutor - std::cout << "\n1. Creating JSCExecutor..." << std::endl; - auto executor = std::make_unique(); - - // 2. 创建 DeviceInfo 模块并直接测试 - std::cout << "2. Testing DeviceInfo methods directly..." << std::endl; - auto deviceInfo = std::make_unique(); - - std::cout << " UniqueId: " << deviceInfo->getUniqueIdImpl() << std::endl; - std::cout << " SystemVersion: " << deviceInfo->getSystemVersionImpl() << std::endl; - std::cout << " DeviceId: " << deviceInfo->getDeviceIdImpl() << std::endl; - - // 3. 注册模块到 JSCExecutor - std::cout << "\n3. Registering DeviceInfo module..." << std::endl; - std::vector> modules; - modules.push_back(std::move(deviceInfo)); - executor->registerModules(std::move(modules)); - - // 4. 测试同步调用性能 - std::cout << "\n4. Testing Bridge communication performance..." << std::endl; - - auto start = std::chrono::high_resolution_clock::now(); - - std::string testScript = R"( - // 测试 iOS DeviceInfo 方法 - console.log('🍎 iOS DeviceInfo Bridge 测试开始...'); - - try { - // getSystemVersion (methodId = 1) - var systemVersion = global.nativeCallSyncHook(0, 1, []); - console.log('✅ iOS SystemVersion:', systemVersion); - - // getDeviceId (methodId = 2) - var deviceId = global.nativeCallSyncHook(0, 2, []); - console.log('✅ iOS DeviceId:', deviceId); - - console.log('🎉 iOS DeviceInfo 测试成功!'); - } catch (e) { - console.log('❌ 测试失败:', e.toString()); - } - )"; - - executor->loadApplicationScript(testScript, "ios_deviceinfo_test.js"); - - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(end - start); - - std::cout << "\n5. Performance Results:" << std::endl; - std::cout << " Bridge call duration: " << duration.count() / 1000.0 << " ms" << std::endl; - - if (duration.count() / 1000.0 < 10.0) { - std::cout << " ✅ Performance requirement met (< 10ms)" << std::endl; - } else { - std::cout << " ⚠️ Performance slower than expected (>= 10ms)" << std::endl; - } - - std::cout << "\n6. iOS DeviceInfo test completed successfully!" << std::endl; - - } catch (const std::exception& e) { - std::cout << "❌ Test failed: " << e.what() << std::endl; - return 1; - } - - std::cout << "\n===========================================" << std::endl; - return 0; -} \ No newline at end of file diff --git a/test_ios.sh b/test_ios.sh index 77c99b8..61827f5 100755 --- a/test_ios.sh +++ b/test_ios.sh @@ -162,18 +162,13 @@ run_all_tests() { ((failed_tests++)) fi - # DeviceInfo 测试 - if ! run_test "DeviceInfo" "./build_ios/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能"; then - ((failed_tests++)) - fi - # 模块框架测试 if ! run_test "模块框架" "./build_ios/test_module_framework.app/test_module_framework" "验证模块注册和调用机制"; then ((failed_tests++)) fi - # 集成测试 - if ! run_test "集成测试" "./build_ios/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试"; then + # 集成测试(包含 DeviceInfo 性能测试) + if ! run_test "集成测试 (含DeviceInfo)" "./build_ios/test_integration.app/test_integration" "完整 JavaScript ↔ Native 通信测试,包含性能基准"; then ((failed_tests++)) fi @@ -205,7 +200,7 @@ main() { check_ios_build check_simulator boot_simulator - run_test "DeviceInfo" "./build_ios/test_ios_deviceinfo.app/test_ios_deviceinfo" "测试 iOS 设备信息获取和性能" + run_test "DeviceInfo (Integration)" "./build_ios/test_integration.app/test_integration" "测试 iOS 设备信息获取和性能(集成测试)" ;; "module") print_header From 31534d443b1a55271b49efd8d9ba0fdbf4253ec8 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 17:23:35 +0800 Subject: [PATCH 06/11] refactor: spreate lightweight performance testing executable and update Makefile - Introduced a new executable for lightweight performance testing (`test_performance`) to assess Bridge communication efficiency. - Updated the Makefile to include a target for running the performance test and added relevant documentation for the new test command. - Removed the performance testing function from the integration test to streamline the testing process. --- CMakeLists.txt | 5 ++ Makefile | 10 +++ examples/test_integration.cpp | 100 +++++++++------------------- examples/test_performance.cpp | 120 ++++++++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 69 deletions(-) create mode 100644 examples/test_performance.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d9a5015..1810eb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,11 @@ add_executable(test_integration examples/test_integration.cpp) target_include_directories(test_integration PRIVATE src) target_link_libraries(test_integration mini_react_native) +# 性能测试可执行文件(轻量级性能检查) +add_executable(test_performance examples/test_performance.cpp) +target_include_directories(test_performance PRIVATE src) +target_link_libraries(test_performance mini_react_native) + # 安装配置(make install 时才会执行) # 安装静态库到 /usr/local/lib 下 diff --git a/Makefile b/Makefile index 3f9c18e..2a31d78 100644 --- a/Makefile +++ b/Makefile @@ -97,6 +97,8 @@ test: build @./$(BUILD_DIR)/test_module_framework @echo "\n📝 Test 3: Integration test" @./$(BUILD_DIR)/test_integration + @echo "\n📝 Test 4: Performance test" + @./$(BUILD_DIR)/test_performance @echo "\n✅ All tests complete" # 运行基础测试 @@ -120,6 +122,13 @@ test-integration: build @./$(BUILD_DIR)/test_integration @echo "✅ Integration test complete" +# 运行性能测试 +.PHONY: test-performance +test-performance: build + @echo "🧪 Running performance test..." + @./$(BUILD_DIR)/test_performance + @echo "✅ Performance test complete" + # 清理构建文件 .PHONY: clean clean: js-clean @@ -206,6 +215,7 @@ help: @echo " make test-basic - 仅运行基础功能测试" @echo " make test-module - 仅运行模块框架测试" @echo " make test-integration - 仅运行集成测试" + @echo " make test-performance - 仅运行性能测试" @echo "" @echo "开发工具:" @echo " make install-deps - 安装开发依赖" diff --git a/examples/test_integration.cpp b/examples/test_integration.cpp index ffc298b..778ee6f 100644 --- a/examples/test_integration.cpp +++ b/examples/test_integration.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "common/bridge/JSCExecutor.h" #include "common/modules/DeviceInfoModule.h" @@ -59,47 +58,6 @@ std::string readFile(const std::string& filePath) { } } -/** - * 性能测试函数 - 测试 Bridge 通信性能 - * @param executor JSCExecutor 实例 - */ -void performanceTest(JSCExecutor& executor) { - std::cout << "\n3.5. Testing Bridge communication performance..." << std::endl; - - auto start = std::chrono::high_resolution_clock::now(); - - // 执行性能测试脚本 - std::string performanceScript = R"( - // 性能测试:调用 DeviceInfo 方法 - try { - // getSystemVersion (methodId = 1) - var systemVersion = global.nativeCallSyncHook(0, 1, []); - - // getDeviceId (methodId = 2) - var deviceId = global.nativeCallSyncHook(0, 2, []); - - console.log('✅ Performance test completed - SystemVersion:', systemVersion, 'DeviceId:', deviceId); - } catch (e) { - console.log('❌ Performance test failed:', e.toString()); - } - )"; - - executor.loadApplicationScript(performanceScript, "performance_test.js"); - - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast(end - start); - - // 性能报告 - double ms = duration.count() / 1000.0; - std::cout << " Bridge call duration: " << ms << " ms" << std::endl; - - if (ms < 10.0) { - std::cout << " ✅ Performance requirement met (< 10ms)" << std::endl; - } else { - std::cout << " ⚠️ Performance slower than expected (>= 10ms)" << std::endl; - } -} - void testIntegration() { std::cout << "\n=== Mini React Native Integration Test ===" << std::endl; @@ -115,13 +73,17 @@ void testIntegration() { // 直接测试 DeviceInfo 原生方法 std::cout << "\n1. Testing DeviceInfo methods directly..." << std::endl; auto deviceInfoForTesting = std::make_unique(); - std::cout << " UniqueId: " << deviceInfoForTesting->getUniqueIdImpl() << std::endl; - std::cout << " SystemVersion: " << deviceInfoForTesting->getSystemVersionImpl() << std::endl; - std::cout << " DeviceId: " << deviceInfoForTesting->getDeviceIdImpl() << std::endl; + std::cout << " UniqueId: " << deviceInfoForTesting->getUniqueIdImpl() + << std::endl; + std::cout << " SystemVersion: " + << deviceInfoForTesting->getSystemVersionImpl() << std::endl; + std::cout << " DeviceId: " << deviceInfoForTesting->getDeviceIdImpl() + << std::endl; // 注册 DeviceInfo 模块(自动注入配置) - std::cout << "\n2. Registering DeviceInfo module and injecting configuration..." - << std::endl; + std::cout + << "\n2. Registering DeviceInfo module and injecting configuration..." + << std::endl; std::vector> modules; modules.push_back(std::make_unique()); executor.registerModules(std::move(modules)); @@ -131,21 +93,22 @@ void testIntegration() { // 尝试多个可能的路径(支持不同的工作目录) std::vector possiblePaths = { - "dist/bundle.js", // 项目根目录 - "../dist/bundle.js", // 从 build 目录 - "../../dist/bundle.js", // 从深层目录 - "/Users/yujiayu02/Dev/Repo/github/mini-react-native/dist/bundle.js" // 绝对路径 + "dist/bundle.js", // 项目根目录 + "./dist/bundle.js", // 从 build 目录 + "../dist/bundle.js", // 从 build 目录 + "../../dist/bundle.js", // 从深层目录 + }; std::string bundlePath; std::string bundleScript; for (const auto& path : possiblePaths) { - bundleScript = readFile(path); - if (!bundleScript.empty()) { - bundlePath = path; - break; - } + bundleScript = readFile(path); + if (!bundleScript.empty()) { + bundlePath = path; + break; + } } if (bundleScript.empty()) { @@ -163,29 +126,26 @@ void testIntegration() { executor.loadApplicationScript(bundleScript, bundlePath); std::cout << " ✓ Bundle executed successfully" << std::endl; - // 性能测试 - performanceTest(executor); - // 加载测试文件 std::cout << "\n4. Loading DeviceInfo integration test..." << std::endl; // 尝试多个可能的测试脚本路径 std::vector possibleTestPaths = { - "examples/scripts/test_deviceinfo.js", // 项目根目录 - "../examples/scripts/test_deviceinfo.js", // 从 build 目录 - "../../examples/scripts/test_deviceinfo.js", // 从深层目录 - "/Users/yujiayu02/Dev/Repo/github/mini-react-native/examples/scripts/test_deviceinfo.js" // 绝对路径 + "examples/scripts/test_deviceinfo.js", // 项目根目录 + "./examples/scripts/test_deviceinfo.js", // 从 build 目录 + "../examples/scripts/test_deviceinfo.js", // 从 build 目录 + "../../examples/scripts/test_deviceinfo.js", // 从深层目录 }; std::string testPath; std::string testScript; for (const auto& path : possibleTestPaths) { - testScript = readFile(path); - if (!testScript.empty()) { - testPath = path; - break; - } + testScript = readFile(path); + if (!testScript.empty()) { + testPath = path; + break; + } } if (testScript.empty()) { @@ -214,7 +174,9 @@ void testIntegration() { int main() { std::cout << "Mini React Native - Integration Test" << std::endl; - std::cout << "This test verifies the complete JavaScript ↔ Native communication using bundled JavaScript" << std::endl; + std::cout << "This test verifies the complete JavaScript ↔ Native " + "communication using bundled JavaScript" + << std::endl; // 运行集成测试 testIntegration(); diff --git a/examples/test_performance.cpp b/examples/test_performance.cpp new file mode 100644 index 0000000..f2a5534 --- /dev/null +++ b/examples/test_performance.cpp @@ -0,0 +1,120 @@ +#include +#include +#include + +#include "common/bridge/JSCExecutor.h" +#include "common/modules/DeviceInfoModule.h" + +using namespace mini_rn::bridge; +using namespace mini_rn::modules; + +/** + * Mini React Native - 轻量级性能测试 + * + * 专注于检测严重性能问题,不做复杂的性能分析 + * 主要验证 Bridge 通信没有明显的性能瓶颈 + */ + +/** + * 快速性能检查 - 验证 Bridge 通信性能 + */ +void quickPerformanceCheck() { + std::cout << "\n🧪 Quick Performance Check" << std::endl; + + try { + // 1. 创建 JSCExecutor + auto executor = std::make_unique(); + + // 2. 注册 DeviceInfo 模块 + std::vector> modules; + modules.push_back(std::make_unique()); + executor->registerModules(std::move(modules)); + + // 3. 测试 Bridge 调用延迟 + auto start = std::chrono::high_resolution_clock::now(); + + // 执行几次关键的 Bridge 调用 + std::string testScript = R"( + // 快速性能测试:调用几个关键方法 + try { + var result1 = global.nativeCallSyncHook(0, 1, []); // getSystemVersion + var result2 = global.nativeCallSyncHook(0, 2, []); // getDeviceId + console.log('Performance test calls completed'); + } catch (e) { + console.log('Performance test failed:', e.toString()); + } + )"; + + executor->loadApplicationScript(testScript, "performance_test.js"); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + // 4. 简单的性能阈值检查 + double ms = duration.count(); + std::cout << " Bridge call latency: " << ms << "ms"; + + if (ms < 10.0) { + std::cout << " (< 10ms threshold)" << std::endl; + std::cout << "✅ Bridge performance OK" << std::endl; + } else if (ms < 50.0) { + std::cout << " (< 50ms threshold)" << std::endl; + std::cout << "⚠️ Bridge performance acceptable but slow" << std::endl; + } else { + std::cout << " (>= 50ms threshold)" << std::endl; + std::cout << "❌ Bridge performance issue detected" << std::endl; + } + + } catch (const std::exception& e) { + std::cout << "❌ Performance test failed: " << e.what() << std::endl; + } +} + +/** + * 模块注册性能检查 + */ +void moduleRegistrationCheck() { + std::cout << "\n🔧 Module Registration Performance Check" << std::endl; + + try { + auto start = std::chrono::high_resolution_clock::now(); + + // 测试模块注册性能 + auto executor = std::make_unique(); + std::vector> modules; + modules.push_back(std::make_unique()); + executor->registerModules(std::move(modules)); + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + double ms = duration.count() / 1000.0; + std::cout << " Module registration: " << ms << "ms" << std::endl; + + if (ms < 5.0) { + std::cout << "✅ Module registration performance OK" << std::endl; + } else { + std::cout << "⚠️ Module registration slower than expected" << std::endl; + } + + } catch (const std::exception& e) { + std::cout << "❌ Module registration test failed: " << e.what() << std::endl; + } +} + +int main() { + std::cout << "Mini React Native - Performance Test" << std::endl; + std::cout << "Lightweight performance check for critical performance issues" << std::endl; + std::cout << std::endl; + + std::cout << "=== Performance Test ===" << std::endl; + + // 执行轻量级性能检查 + moduleRegistrationCheck(); + quickPerformanceCheck(); + + std::cout << "\n🏁 Performance test completed" << std::endl; + std::cout << " No severe performance issues detected if all checks passed" << std::endl; + + return 0; +} \ No newline at end of file From 56d0264b43f1371f6457581d1677eacc73734a53 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 23 Nov 2025 19:29:40 +0800 Subject: [PATCH 07/11] fix: enhance iOS integration testing with path resolve - Added iOS-specific configurations in CMakeLists.txt to include an Objective-C helper file for integration tests. - Implemented custom commands to copy the JavaScript bundle and test scripts into the iOS app package post-build. - Updated the test_integration.cpp file to utilize the new Objective-C functions for retrieving bundle and resource paths on iOS. - Ensured that the integration test can now dynamically load resources based on the platform, improving cross-platform compatibility. --- CMakeLists.txt | 27 +++++++++- examples/ios_bundle_helper.m | 41 +++++++++++++++ examples/test_integration.cpp | 96 +++++++++++++++++++++++++++++++---- 3 files changed, 152 insertions(+), 12 deletions(-) create mode 100644 examples/ios_bundle_helper.m diff --git a/CMakeLists.txt b/CMakeLists.txt index 1810eb0..93fa529 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,7 +133,13 @@ target_include_directories(test_module_framework PRIVATE src) target_link_libraries(test_module_framework mini_react_native) # 集成测试可执行文件(使用打包后的 JavaScript bundle) -add_executable(test_integration examples/test_integration.cpp) +if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") + # iOS版本需要包含Objective-C helper文件 + add_executable(test_integration examples/test_integration.cpp examples/ios_bundle_helper.m) +else() + # 其他平台只需要C++文件 + add_executable(test_integration examples/test_integration.cpp) +endif() target_include_directories(test_integration PRIVATE src) target_link_libraries(test_integration mini_react_native) @@ -142,6 +148,25 @@ add_executable(test_performance examples/test_performance.cpp) target_include_directories(test_performance PRIVATE src) target_link_libraries(test_performance mini_react_native) +# iOS 特定配置:复制 JavaScript bundle 到应用包 +if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") + # 为 test_integration 添加 bundle.js 资源复制 + add_custom_command(TARGET test_integration POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/dist/bundle.js" + "$/bundle.js" + COMMENT "Copying JavaScript bundle to iOS app package" + ) + + # 为 test_integration 添加测试脚本复制 + add_custom_command(TARGET test_integration POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_SOURCE_DIR}/examples/scripts/test_deviceinfo.js" + "$/test_deviceinfo.js" + COMMENT "Copying test script to iOS app package" + ) +endif() + # 安装配置(make install 时才会执行) # 安装静态库到 /usr/local/lib 下 diff --git a/examples/ios_bundle_helper.m b/examples/ios_bundle_helper.m new file mode 100644 index 0000000..1c64abc --- /dev/null +++ b/examples/ios_bundle_helper.m @@ -0,0 +1,41 @@ +#import + +// C函数接口,供C++代码调用 +const char* getBundlePath() { + @autoreleasepool { + NSBundle* mainBundle = [NSBundle mainBundle]; + if (mainBundle) { + NSString* bundlePath = [mainBundle bundlePath]; + if (bundlePath) { + // 返回静态字符串,避免内存管理问题 + static char pathBuffer[1024]; + strncpy(pathBuffer, [bundlePath UTF8String], sizeof(pathBuffer) - 1); + pathBuffer[sizeof(pathBuffer) - 1] = '\0'; + return pathBuffer; + } + } + return NULL; + } +} + +const char* getResourcePath(const char* resourceName) { + @autoreleasepool { + if (!resourceName) { + return NULL; + } + + NSBundle* mainBundle = [NSBundle mainBundle]; + if (mainBundle) { + NSString* fileName = [NSString stringWithUTF8String:resourceName]; + NSString* resourcePath = [mainBundle pathForResource:fileName ofType:nil]; + if (resourcePath) { + // 返回静态字符串,避免内存管理问题 + static char pathBuffer[1024]; + strncpy(pathBuffer, [resourcePath UTF8String], sizeof(pathBuffer) - 1); + pathBuffer[sizeof(pathBuffer) - 1] = '\0'; + return pathBuffer; + } + } + return NULL; + } +} \ No newline at end of file diff --git a/examples/test_integration.cpp b/examples/test_integration.cpp index 778ee6f..bf0059b 100644 --- a/examples/test_integration.cpp +++ b/examples/test_integration.cpp @@ -4,6 +4,17 @@ #include #include +#ifdef __APPLE__ +#include +#if TARGET_OS_IPHONE +// iOS特定声明,实现在单独的文件中 +extern "C" { + const char* getBundlePath(); + const char* getResourcePath(const char* resourceName); +} +#endif +#endif + #include "common/bridge/JSCExecutor.h" #include "common/modules/DeviceInfoModule.h" #include "common/modules/ModuleRegistry.h" @@ -11,6 +22,29 @@ using namespace mini_rn::bridge; using namespace mini_rn::modules; +#ifdef __APPLE__ +#if TARGET_OS_IPHONE +/** + * 获取iOS应用包路径 + * @return iOS应用包的完整路径 + */ +std::string getMainBundlePath() { + const char* path = getBundlePath(); + return path ? std::string(path) : ""; +} + +/** + * 获取iOS应用包内资源路径 + * @param resourceName 资源文件名 + * @return 资源文件的完整路径 + */ +std::string getBundleResourcePath(const std::string& resourceName) { + const char* path = getResourcePath(resourceName.c_str()); + return path ? std::string(path) : ""; +} +#endif +#endif + /** * Mini React Native - 端到端集成测试 * @@ -91,28 +125,49 @@ void testIntegration() { // 加载打包后的 JavaScript bundle std::cout << "\n3. Loading JavaScript bundle..." << std::endl; - // 尝试多个可能的路径(支持不同的工作目录) - std::vector possiblePaths = { + // 构建路径列表,iOS优先使用bundle路径 + std::vector possiblePaths; + +#ifdef __APPLE__ +#if TARGET_OS_IPHONE + // iOS: 优先尝试应用包内的bundle.js + std::string bundleResourcePath = getBundleResourcePath("bundle.js"); + if (!bundleResourcePath.empty()) { + possiblePaths.push_back(bundleResourcePath); + std::cout << " [iOS] Found bundle resource path: " << bundleResourcePath << std::endl; + } + + // iOS: 也尝试应用包根目录 + std::string appBundlePath = getMainBundlePath(); + if (!appBundlePath.empty()) { + possiblePaths.push_back(appBundlePath + "/bundle.js"); + std::cout << " [iOS] Bundle path: " << appBundlePath << std::endl; + } +#endif +#endif + + // 通用路径(适用于macOS和iOS fallback) + possiblePaths.insert(possiblePaths.end(), { + "bundle.js", // 当前目录 "dist/bundle.js", // 项目根目录 "./dist/bundle.js", // 从 build 目录 "../dist/bundle.js", // 从 build 目录 "../../dist/bundle.js", // 从深层目录 + }); - }; - - std::string bundlePath; + std::string foundBundlePath; std::string bundleScript; for (const auto& path : possiblePaths) { bundleScript = readFile(path); if (!bundleScript.empty()) { - bundlePath = path; + foundBundlePath = path; break; } } if (bundleScript.empty()) { - std::cout << "[Error] Failed to load JavaScript bundle: " << bundlePath + std::cout << "[Error] Failed to load JavaScript bundle: " << foundBundlePath << std::endl; std::cout << " Make sure you have run 'make js-build' first." << std::endl; @@ -123,19 +178,38 @@ void testIntegration() { << " bytes)" << std::endl; // 执行打包后的 JavaScript bundle - executor.loadApplicationScript(bundleScript, bundlePath); + executor.loadApplicationScript(bundleScript, foundBundlePath); std::cout << " ✓ Bundle executed successfully" << std::endl; // 加载测试文件 std::cout << "\n4. Loading DeviceInfo integration test..." << std::endl; - // 尝试多个可能的测试脚本路径 - std::vector possibleTestPaths = { + // 构建测试脚本路径列表,iOS优先使用bundle路径 + std::vector possibleTestPaths; + +#ifdef __APPLE__ +#if TARGET_OS_IPHONE + // iOS: 优先尝试应用包内的测试脚本 + std::string testResourcePath = getBundleResourcePath("test_deviceinfo.js"); + if (!testResourcePath.empty()) { + possibleTestPaths.push_back(testResourcePath); + std::cout << " [iOS] Found test resource path: " << testResourcePath << std::endl; + } + + // iOS: 也尝试应用包根目录 + if (!appBundlePath.empty()) { + possibleTestPaths.push_back(appBundlePath + "/test_deviceinfo.js"); + } +#endif +#endif + + // 通用路径(适用于macOS和iOS fallback) + possibleTestPaths.insert(possibleTestPaths.end(), { "examples/scripts/test_deviceinfo.js", // 项目根目录 "./examples/scripts/test_deviceinfo.js", // 从 build 目录 "../examples/scripts/test_deviceinfo.js", // 从 build 目录 "../../examples/scripts/test_deviceinfo.js", // 从深层目录 - }; + }); std::string testPath; std::string testScript; From 9b6dfab7c5d6d55bfeda59baaeb148b1c1ae1300 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sun, 7 Dec 2025 17:23:49 +0800 Subject: [PATCH 08/11] docs: update Phase 2 implementation plan for iOS platform support --- docs/PHASE2_PLAN.md | 198 ++++++++++++++------------------------------ 1 file changed, 62 insertions(+), 136 deletions(-) diff --git a/docs/PHASE2_PLAN.md b/docs/PHASE2_PLAN.md index 08178f0..7da639d 100644 --- a/docs/PHASE2_PLAN.md +++ b/docs/PHASE2_PLAN.md @@ -1,20 +1,19 @@ -# 阶段2:跨平台支持 - 详细实施计划 +# 阶段2:iOS 平台支持 - 详细实施计划 ## 🎯 阶段目标 -实现完整的跨平台支持(macOS + iOS + Android),建立统一的构建和测试流程,这是 Mini React Native 走向完整性的关键步骤。 +实现 iOS 平台的完整支持,建立统一的构建和测试流程,为 Mini React Native 提供移动端支持。 **成功标准:** - ✅ iOS 平台完整支持,与 macOS 共享 JavaScriptCore.framework -- ✅ Android 平台完整支持,通过 JNI 集成 JavaScriptCore -- ✅ 三平台统一的构建、测试和验证流程 +- ✅ macOS + iOS 双平台统一的构建、测试和验证流程 - ✅ DeviceInfo 模块在所有平台正常工作 - ✅ 性能保持在可接受水平(< 10ms 调用延迟) ## 📋 详细任务分解 -### 任务1: iOS 平台支持完成 +### 任务1: iOS 平台支持完成 ✅ **目标:** 完成 iOS 平台的完整适配,利用与 macOS 共享的 JavaScriptCore.framework @@ -24,132 +23,59 @@ - 利用 iOS 和 macOS 共享的 JavaScriptCore.framework - 保持与 macOS 版本的 API 一致性 -#### 子任务 1.1: iOS 构建系统配置 (0.25天) +#### 子任务 1.1: iOS 构建系统配置 ✅ -- [ ] **Xcode 项目配置** +- [x] **Xcode 项目配置** - 创建 iOS target 配置 - 配置 JavaScriptCore.framework 链接 - 设置最低 iOS 版本支持(iOS 12.0+) -- [ ] **CMake 构建适配** +- [x] **CMake 构建适配** - 添加 iOS 平台检测逻辑 - 配置 iOS 特定的编译选项 - 确保与 macOS 构建的一致性 -#### 子任务 1.2: iOS 平台验证 (0.25天) +#### 子任务 1.2: iOS 平台验证 ✅ -- [ ] **基础功能验证** +- [x] **基础功能验证** - JSCExecutor 在 iOS 上的初始化验证 - Bridge 通信功能测试 - DeviceInfo 模块在 iOS 上的运行验证 -- [ ] **iOS 特定 API 实现** +- [x] **iOS 特定 API 实现** - iOS 版本的设备信息获取 - 确保 DeviceInfo 返回正确的 iOS 设备数据 -### 任务2: Android 平台集成 +### 任务2: iOS 与 macOS 统一测试与验证 -**目标:** 实现 Android 平台的完整支持,通过 JNI 集成 JavaScriptCore +**目标:** 建立统一的测试流程,确保双平台的一致性 -**架构约束:** - -- 使用 JSC 的移植版本(如 facebook/android-jsc) -- 通过 JNI 桥接 C++ 和 Java/Kotlin 代码 -- 保持与 iOS/macOS 的 API 一致性 - -#### 子任务 2.1: Android 构建系统搭建 (1.5天) - -- [ ] **Gradle 项目结构** - - 创建 Android 项目基础结构 - - 配置 CMake 与 Gradle 的集成 - - 设置 NDK 构建配置 - -- [ ] **JavaScriptCore 移植版本集成** - - 集成 facebook/android-jsc 或类似的 JSC 移植版本 - - 配置 JSC 库的链接和依赖 - - 验证 JSC API 在 Android 上的可用性 - -- [ ] **JNI 桥接层设计** - ```cpp - // JNI 接口设计 - extern "C" { - JNIEXPORT void JNICALL Java_com_minirn_JSCExecutor_initializeContext(JNIEnv* env, jobject obj); - JNIEXPORT void JNICALL Java_com_minirn_JSCExecutor_loadScript(JNIEnv* env, jobject obj, jstring script); - JNIEXPORT void JNICALL Java_com_minirn_JSCExecutor_destroyContext(JNIEnv* env, jobject obj); - } - ``` - -#### 子任务 2.2: Android Native 层实现 (1天) - -- [ ] **JSCExecutor Android 适配** - - 适配现有的 JSCExecutor 到 Android 环境 - - 处理 Android 特定的内存管理 - - 确保线程安全(Android 主线程 vs Native 线程) - -- [ ] **Android DeviceInfo 模块** - - 实现 Android 版本的设备信息获取 - - 通过 JNI 调用 Android API - - 返回正确的 Android 设备数据 - -#### 子任务 2.3: Android Java 层实现 (0.5天) - -- [ ] **Java/Kotlin 封装层** - - 创建 JSCExecutor 的 Java 封装类 - - 实现 DeviceInfo 的 Android API 调用 - - 建立 Java 到 Native 的调用桥梁 - -- [ ] **Android 应用示例** - - 创建简单的 Android 应用示例 - - 集成 Mini React Native 库 - - 验证基础功能正常工作 +#### 子任务 2.1: 统一测试套件 (0.5天) -### 任务3: 跨平台测试与验证 - -**目标:** 建立统一的跨平台测试流程,确保三平台的一致性 - -#### 子任务 3.1: 统一测试套件 (0.5天) - -- [ ] **跨平台测试脚本** - - 创建统一的测试脚本,支持三平台 +- [ ] **双平台测试脚本** + - 创建统一的测试脚本,支持 macOS + iOS - 自动化构建和测试流程 - 集成到 Makefile 中 - [ ] **一致性验证** - - 确保 DeviceInfo 在三平台返回正确格式的数据 + - 确保 DeviceInfo 在双平台返回正确格式的数据 - 验证 Bridge 通信的性能一致性 - 测试错误处理的平台一致性 -#### 子任务 3.2: 文档和示例完善 (0.5天) +#### 子任务 2.2: 文档和示例完善 (0.5天) -- [ ] **跨平台构建文档** - - 详细的三平台构建指南 +- [ ] **双平台构建文档** + - 详细的 macOS + iOS 构建指南 - 依赖安装和环境配置说明 - 常见问题和解决方案 - [ ] **平台差异说明** - - 记录三平台的技术差异 + - 记录 macOS 和 iOS 的技术差异 - API 调用的平台特定实现 - 性能特征对比 ## 🔧 技术要点和难点 -### Android 平台的主要挑战 - -1. **JNI 集成复杂性** - - C++ 和 Java 之间的数据类型转换 - - 内存管理和生命周期控制 - - 异常处理的跨语言传递 - -2. **JavaScriptCore 移植版本** - - 不同 JSC 移植版本的 API 差异 - - 性能和稳定性的权衡 - - 版本兼容性管理 - -3. **Android 构建系统** - - CMake 和 Gradle 的集成配置 - - NDK 版本兼容性 - - 多架构支持(arm64-v8a, armeabi-v7a) - ### iOS 平台的技术要点 1. **框架共享优势** @@ -162,7 +88,12 @@ - 后台执行的限制 - App Store 审核要求 -### 跨平台一致性保证 +3. **iOS 构建系统** + - CMake 与 Xcode 的集成配置 + - iOS Simulator 和真机的差异处理 + - 多架构支持(arm64, x86_64) + +### 双平台一致性保证 1. **API 抽象层设计** - 统一的 NativeModule 接口 @@ -170,50 +101,50 @@ - 错误处理的标准化 2. **测试策略** - - 自动化的跨平台测试 + - 自动化的双平台测试 - 性能基准的平台对比 - 功能一致性验证 +3. **构建系统统一** + - CMake 的跨平台配置 + - Makefile 的双平台支持 + - 依赖管理的统一化 + ## 📝 验收标准 ### 功能验收 -- [ ] **iOS 平台验收** +- [x] **iOS 平台验收** - JSCExecutor 在 iOS 上正常初始化和运行 - DeviceInfo 模块返回正确的 iOS 设备信息 - Bridge 通信性能 < 10ms -- [ ] **Android 平台验收** - - 通过 JNI 成功集成 JavaScriptCore - - DeviceInfo 模块返回正确的 Android 设备信息 - - 构建系统支持多架构(arm64-v8a, armeabi-v7a) - -- [ ] **跨平台一致性验收** - - 同一份 JavaScript 代码在三平台运行结果一致 - - DeviceInfo API 在三平台返回相同格式的数据 - - 错误处理行为在三平台保持一致 +- [ ] **双平台一致性验收** + - 同一份 JavaScript 代码在 macOS 和 iOS 运行结果一致 + - DeviceInfo API 在双平台返回相同格式的数据 + - 错误处理行为在双平台保持一致 ### 性能验收 - [ ] **基础性能指标** - - 单次调用延迟 < 10ms(所有平台) + - 单次调用延迟 < 10ms(双平台) - 内存使用稳定,无明显泄漏 - 应用启动时间在可接受范围内 -- [ ] **跨平台性能对比** - - 记录三平台的性能基准数据 +- [ ] **双平台性能对比** + - 记录 macOS 和 iOS 的性能基准数据 - 分析平台间的性能差异 - 确保没有明显的性能退化 ### 质量验收 - [ ] **代码质量** - - 通过静态分析检查(所有平台) + - 通过静态分析检查(双平台) - 代码覆盖率达到基本要求 - 文档完整且准确 - [ ] **构建系统** - - 三平台的自动化构建成功 + - 双平台的自动化构建成功 - 统一的测试脚本正常运行 - CI/CD 流程可以正常执行 @@ -221,21 +152,20 @@ ### 1. 代码成果 -- **完整的三平台支持** - - macOS(已完成)+ iOS + Android 的完整实现 +- **完整的双平台支持** + - macOS(已完成)+ iOS 的完整实现 - 统一的 API 接口和一致的行为 - 跨平台的构建和测试系统 - **平台特定实现** - iOS 的 JavaScriptCore.framework 集成 - - Android 的 JNI + JSC 移植版本集成 - 各平台的 DeviceInfo 模块实现 ### 2. 文档成果 -- **跨平台构建指南** +- **双平台构建指南** - 详细的环境配置说明 - - 三平台的构建步骤 + - macOS 和 iOS 的构建步骤 - 常见问题和解决方案 - **技术架构文档** @@ -245,34 +175,28 @@ ### 3. 博客文章 -- **《从零实现 React Native (2): 跨平台架构实现》** - - 跨平台技术挑战和解决方案 - - iOS 和 Android 平台的适配经验 - - JavaScriptCore 在不同平台的集成方式 +- **《从零实现 React Native (2): iOS 平台架构实现》** + - iOS 平台技术挑战和解决方案 + - iOS 和 macOS 的代码复用经验 + - JavaScriptCore 在 iOS 平台的集成方式 - 构建系统的统一设计思路 ## ⏱️ 时间规划 | 任务 | 预估时间 | 主要工作内容 | 依赖关系 | |------|---------|-------------|----------| -| 任务1: iOS 平台支持 | **0.5天** | Xcode 配置 + 功能验证 | 无 | -| 任务2: Android 平台集成 | **3天** | JNI + JSC 移植 + 构建系统 | 无 | -| 任务3: 跨平台测试验证 | **1天** | 统一测试 + 文档完善 | 依赖任务1,2 | +| 任务1: iOS 平台支持 | **0.5天** | Xcode 配置 + 功能验证 | ✅ 已完成 | +| 任务2: 双平台测试验证 | **1天** | 统一测试 + 文档完善 | 依赖任务1 | -**总计: 4.5天** (相比原 ROADMAP 的 3-4周,大幅简化和聚焦) +**总计: 1.5天** (相比原计划的 4.5天,大幅简化) ### 📋 执行建议 -**Day 1: iOS 快速适配** +**Day 1: iOS 快速适配** ✅ 已完成 - 上午:iOS 构建系统配置 - 下午:功能验证和测试 -**Day 2-4: Android 深度集成** -- Day 2:构建系统和 JSC 集成 -- Day 3:JNI 桥接和 Native 层实现 -- Day 4:Java 层封装和应用示例 - -**Day 5: 跨平台验证** +**Day 2: 双平台验证** - 上午:统一测试套件运行 - 下午:文档完善和成果整理 @@ -287,21 +211,23 @@ 这将标志着从基础通信向完整 UI 系统的重要跃进。 -## 📱 跨平台支持总结 +## 📱 平台支持总结 ### ✅ macOS 支持 (Phase 1 已完成) - 完整实现并测试通过 - 使用系统 JavaScriptCore.framework - 作为主要开发和验证平台 -### 🍎 iOS 支持 (本阶段) +### ✅ iOS 支持 (本阶段已完成) - **实施时间**: 0.5天 - **技术复杂度**: 低 - **主要优势**: 与 macOS 共享 JavaScriptCore.framework +- **状态**: 已完成 iOS 平台的完整适配和测试 -### 🤖 Android 支持 (本阶段) -- **实施时间**: 3天 +### 📝 Android 支持 (未来计划) +- **实施时间**: 预计 3天 - **技术复杂度**: 中高 - **主要挑战**: JNI 集成 + JSC 移植版本适配 +- **状态**: 暂缓,优先完成视图渲染系统 -这将为后续的视图渲染系统提供坚实的跨平台基础。 \ No newline at end of file +macOS + iOS 双平台支持已为后续的视图渲染系统提供了坚实的移动端基础。 \ No newline at end of file From 2736932eef4faaa3b71a1e5d195d87c192c7bf3c Mon Sep 17 00:00:00 2001 From: zerosrat Date: Sat, 13 Dec 2025 11:53:05 +0800 Subject: [PATCH 09/11] refactor: replace Objective-C helper file with Objective-C++ for iOS integration tests - Renamed the Objective-C helper file from `.m` to `.mm` to support C++ interoperability. - Updated CMakeLists.txt to reflect the change in file extension for the iOS integration test executable. - Removed the old Objective-C helper file and implemented the necessary functions in the new Objective-C++ file. --- CMakeLists.txt | 2 +- examples/ios_bundle_helper.m | 41 ------------------------------- examples/ios_bundle_helper.mm | 46 +++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 42 deletions(-) delete mode 100644 examples/ios_bundle_helper.m create mode 100644 examples/ios_bundle_helper.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index 93fa529..b711ac2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,7 +135,7 @@ target_link_libraries(test_module_framework mini_react_native) # 集成测试可执行文件(使用打包后的 JavaScript bundle) if(${CMAKE_SYSTEM_NAME} MATCHES "iOS") # iOS版本需要包含Objective-C helper文件 - add_executable(test_integration examples/test_integration.cpp examples/ios_bundle_helper.m) + add_executable(test_integration examples/test_integration.cpp examples/ios_bundle_helper.mm) else() # 其他平台只需要C++文件 add_executable(test_integration examples/test_integration.cpp) diff --git a/examples/ios_bundle_helper.m b/examples/ios_bundle_helper.m deleted file mode 100644 index 1c64abc..0000000 --- a/examples/ios_bundle_helper.m +++ /dev/null @@ -1,41 +0,0 @@ -#import - -// C函数接口,供C++代码调用 -const char* getBundlePath() { - @autoreleasepool { - NSBundle* mainBundle = [NSBundle mainBundle]; - if (mainBundle) { - NSString* bundlePath = [mainBundle bundlePath]; - if (bundlePath) { - // 返回静态字符串,避免内存管理问题 - static char pathBuffer[1024]; - strncpy(pathBuffer, [bundlePath UTF8String], sizeof(pathBuffer) - 1); - pathBuffer[sizeof(pathBuffer) - 1] = '\0'; - return pathBuffer; - } - } - return NULL; - } -} - -const char* getResourcePath(const char* resourceName) { - @autoreleasepool { - if (!resourceName) { - return NULL; - } - - NSBundle* mainBundle = [NSBundle mainBundle]; - if (mainBundle) { - NSString* fileName = [NSString stringWithUTF8String:resourceName]; - NSString* resourcePath = [mainBundle pathForResource:fileName ofType:nil]; - if (resourcePath) { - // 返回静态字符串,避免内存管理问题 - static char pathBuffer[1024]; - strncpy(pathBuffer, [resourcePath UTF8String], sizeof(pathBuffer) - 1); - pathBuffer[sizeof(pathBuffer) - 1] = '\0'; - return pathBuffer; - } - } - return NULL; - } -} \ No newline at end of file diff --git a/examples/ios_bundle_helper.mm b/examples/ios_bundle_helper.mm new file mode 100644 index 0000000..523cef5 --- /dev/null +++ b/examples/ios_bundle_helper.mm @@ -0,0 +1,46 @@ +#import + +// C函数接口,供C++代码调用 +// 使用 extern "C" 确保 C 链接,避免 C++ 名称修饰 +extern "C" { + +const char* getBundlePath() { + @autoreleasepool { + NSBundle* mainBundle = [NSBundle mainBundle]; + if (mainBundle) { + NSString* bundlePath = [mainBundle bundlePath]; + if (bundlePath) { + // 返回静态字符串,避免内存管理问题 + static char pathBuffer[1024]; + strncpy(pathBuffer, [bundlePath UTF8String], sizeof(pathBuffer) - 1); + pathBuffer[sizeof(pathBuffer) - 1] = '\0'; + return pathBuffer; + } + } + return NULL; + } +} + +const char* getResourcePath(const char* resourceName) { + @autoreleasepool { + if (!resourceName) { + return NULL; + } + + NSBundle* mainBundle = [NSBundle mainBundle]; + if (mainBundle) { + NSString* fileName = [NSString stringWithUTF8String:resourceName]; + NSString* resourcePath = [mainBundle pathForResource:fileName ofType:nil]; + if (resourcePath) { + // 返回静态字符串,避免内存管理问题 + static char pathBuffer[1024]; + strncpy(pathBuffer, [resourcePath UTF8String], sizeof(pathBuffer) - 1); + pathBuffer[sizeof(pathBuffer) - 1] = '\0'; + return pathBuffer; + } + } + return NULL; + } +} + +} // extern "C" \ No newline at end of file From 14a01327a7c40baef10ec4cf7674f9d732974356 Mon Sep 17 00:00:00 2001 From: zerosrat Date: Mon, 22 Dec 2025 15:29:08 +0800 Subject: [PATCH 10/11] feat: add submodule for vibe-writing-workflow and update documentation - Introduced a new submodule for the vibe-writing-workflow repository to streamline project management. - Updated claude.md to enhance the development strategy section, including key project paths and build commands. - Added detailed build and testing commands for various platforms in the documentation to improve usability. --- .gitmodules | 3 ++ claude.md | 116 +++++++++++++++++++++--------------------- docs/PHASE1_PLAN.md | 27 ++++++++++ vibe-writing-workflow | 1 + 4 files changed, 88 insertions(+), 59 deletions(-) create mode 100644 .gitmodules create mode 160000 vibe-writing-workflow diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3aaf133 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "vibe-writing-workflow"] + path = vibe-writing-workflow + url = https://github.com/zerosrat/vibe-writing-workflow.git diff --git a/claude.md b/claude.md index 7aa9b37..54a54cb 100644 --- a/claude.md +++ b/claude.md @@ -23,11 +23,6 @@ - 尽快建立反馈循环,验证设计思路 - 允许后续重构和改进 -4. **AI 协助开发** > 纯手工编码 - - 利用 AI 生成大部分基础代码和样板代码 - - 人工专注于架构设计和核心逻辑 - - 显著提升开发效率,缩短实现周期 - ## 🔧 开发策略 ### 质量标准 @@ -57,81 +52,84 @@ 具体的,桥架构版本参考 RN [v0.57.8](https://github.com/facebook/react-native/blob/0.57-stable/Libraries/BatchedBridge/MessageQueue.js),这个版本只包含 Bridge 代码不包含 JSI 代码,便于学习和参考。 -**核心约束:** +## 关键项目路径 -1. **架构思路与 RN 保持一致** - - 遵循官方 RN Bridge 的设计模式和数据流向 - - JavaScript ↔ Native 通信必须基于异步消息队列 - - 模块注册和方法导出方式与 RN 保持一致 +### 核心源码 -2. **具体实现可以简化** - - 在保持架构思路一致的前提下,实现细节可以更简单 - - 减少复杂的优化和边缘情况处理 - - 专注核心流程,忽略生产级的健壮性要求 +- `src/common/` - 跨平台核心代码(JSCExecutor、模块系统) +- `src/js/` - JavaScript 实现(MessageQueue、NativeModule 等) +- `src/macos/` - macOS 平台代码 +- `src/ios/` - iOS 平台代码 +- `src/android/` - Android 平台代码 -### 关键组件对应关系 +### 构建输出 -| 组件 | React Native 原版 | Mini 实现 | 一致性要求 | -|------|------------------|-----------|------------| -| **JSCExecutor** | JSCExecutor.cpp | 简化版 JSCExecutor | JavaScript 上下文管理方式一致 | -| **MessageQueue** | MessageQueue.js | 简化版 MessageQueue | 消息格式和队列机制一致 | -| **NativeModule** | NativeModule.java/.mm | 简化版 NativeModule | 模块注册和方法调用方式一致 | -| **EventEmitter** | RCTEventEmitter | 简化版事件系统 | 事件分发机制一致 | +- `build/` - macOS 构建目录 +- `build_ios/` - iOS 构建目录 +- `dist/bundle.js` - JavaScript 打包文件 -### 兼容性目标 +### 测试和示例 +- `examples/` - 测试用例和示例代码 -- **消息格式兼容**: 能够处理标准 RN 的消息队列格式 -- **模块接口兼容**: Native 模块的导出方式与 RN 保持一致 -- **JavaScript 接口兼容**: 能够运行基础的 RN-style JavaScript 代码 -- **事件系统兼容**: 事件的注册、监听、分发与 RN 行为一致 +### 关键配置 -## 📅 时间管理 +- `CMakeLists.txt` - CMake 构建配置 +- `Makefile` - 构建自动化脚本 +- `package.json` - Node.js 依赖 +- `rollup.config.js` - JavaScript 打包配置 -### 总体目标 +## 命令 -- **阶段1 (Bridge通信)**: 7-10天 (而非原计划的 19-27天) -- **快速原型**: 2-3天内建立基础通信 -- **功能完善**: 4-5天完善核心功能 -- **验证测试**: 1-2天集成测试 +### 构建命令 -### 里程碑设定 +```bash +make build # 编译项目(默认包含 JS 构建) +make js-build # 仅构建 JavaScript bundle +make js-watch # 监听 JS 文件并自动重建 +make clean # 清理所有构建文件 +make js-clean # 仅清理 JavaScript 构建文件 +make rebuild # 完全清理重建 +make configure # 仅配置 CMake +``` -每个里程碑都应该有可演示的成果: -- **M1**: JavaScript 能调用一个 Native 函数并获得返回值 -- **M2**: Native 能向 JavaScript 发送事件 -- **M3**: 完整的 DeviceInfo 模块演示 -- **M4**: 性能基准和文档总结 +### iOS 构建命令 -## 🚀 成功标准 +```bash +make ios-build # 为 iOS 模拟器构建 +make ios-configure # 仅配置 iOS 构建 +``` -### 最小成功标准 (Must Have) +### macos 测试命令 -- [x] JavaScript ↔ Native 双向通信正常工作 -- [x] 至少一个完整的 Native 模块实现 (DeviceInfo) -- [x] 基础的错误处理机制 -- [x] 可运行的端到端演示 +```bash +make test # 运行所有测试(基础、模块、集成、性能) +make test-basic # 仅基础功能测试 +make test-module # 仅模块框架测试 +make test-integration # 仅集成测试 +make test-performance # 仅性能测试 +make ios-test # 运行所有 iOS 测试 +make ios-test-deviceinfo # 仅运行 iOS DeviceInfo 测试 +``` -### 期望标准 (Should Have) +### iOS 测试 -- [x] 性能达到可接受水平 (< 10ms 调用延迟) -- [x] 事件系统正常工作 -- [x] 基础的调试和日志功能 -- [x] 与 React Native 行为对比分析 +`docs/iOS_TESTING.md` -### 理想标准 (Could Have) +### 构建系统详情 -- [x] 多平台支持 (macOS + iOS) -- [x] 性能优化和内存管理 -- [x] 完整的文档和教程 -- [x] 开源社区反馈 +- 构建类型:基于 CMake(3.15+) +- 编译器:Clang++(C++17 标准) +- 构建目录:`build/`(macOS)、`build_ios/`(iOS) +- 并行构建:自动使用系统 CPU 核心数 +- 部署目标:macOS 10.15+、iOS 12.0+ -## 📝 文档输出 +## 关键文档索引 -### 必需文档 +- 路线图:`docs/ROADMAP.md` +- 阶段一规划:`docs/PHASE1_PLAN.md` +- 阶段二规划:`docs/PHASE2_PLAN.md` -1. **实现文档**: 记录关键技术决策和实现细节 -2. **使用指南**: 如何构建、运行和测试项目 -3. **对比分析**: 与官方 React Native 的差异分析 +## 📝 文档输出 ### 期望文档 diff --git a/docs/PHASE1_PLAN.md b/docs/PHASE1_PLAN.md index 2a5bdec..084b57b 100644 --- a/docs/PHASE1_PLAN.md +++ b/docs/PHASE1_PLAN.md @@ -12,6 +12,33 @@ - ✅ 通信性能达到可接受水平 - ✅ 建立真实的 JavaScriptCore 执行环境和通信机制 +**核心约束:** + +1. **架构思路与 RN 保持一致** + - 遵循官方 RN Bridge 的设计模式和数据流向 + - JavaScript ↔ Native 通信必须基于异步消息队列 + - 模块注册和方法导出方式与 RN 保持一致 + +2. **具体实现可以简化** + - 在保持架构思路一致的前提下,实现细节可以更简单 + - 减少复杂的优化和边缘情况处理 + - 专注核心流程,忽略生产级的健壮性要求 + +### 关键组件对应关系 + +| 组件 | React Native 原版 | Mini 实现 | 一致性要求 | +|------|------------------|-----------|------------| +| **JSCExecutor** | JSCExecutor.cpp | 简化版 JSCExecutor | JavaScript 上下文管理方式一致 | +| **MessageQueue** | MessageQueue.js | 简化版 MessageQueue | 消息格式和队列机制一致 | +| **NativeModule** | NativeModule.java/.mm | 简化版 NativeModule | 模块注册和方法调用方式一致 | + +### 兼容性目标 + +- **消息格式兼容**: 能够处理标准 RN 的消息队列格式 +- **模块接口兼容**: Native 模块的导出方式与 RN 保持一致 +- **JavaScript 接口兼容**: 能够运行基础的 RN-style JavaScript 代码 +- **事件系统兼容**: 事件的注册、监听、分发与 RN 行为一致 + ## 📋 详细任务分解 ### 任务1: 构建 RN 风格的 JSCExecutor diff --git a/vibe-writing-workflow b/vibe-writing-workflow new file mode 160000 index 0000000..24847ff --- /dev/null +++ b/vibe-writing-workflow @@ -0,0 +1 @@ +Subproject commit 24847ff733eee9fbec89fa3be031a9fb59513fde From aa4a6b6bed8d0b710043adc1a7783807b6a8dffe Mon Sep 17 00:00:00 2001 From: zerosrat Date: Fri, 2 Jan 2026 19:07:53 +0800 Subject: [PATCH 11/11] =?UTF-8?q?chore:=20=E6=9B=B4=E6=96=B0vibe-writing-w?= =?UTF-8?q?orkflow=E5=AD=90=E6=A8=A1=E5=9D=97=E6=8C=87=E5=90=91=E6=9C=80?= =?UTF-8?q?=E6=96=B0=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vibe-writing-workflow | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vibe-writing-workflow b/vibe-writing-workflow index 24847ff..f1c25a9 160000 --- a/vibe-writing-workflow +++ b/vibe-writing-workflow @@ -1 +1 @@ -Subproject commit 24847ff733eee9fbec89fa3be031a9fb59513fde +Subproject commit f1c25a97e828daf97f50d49219d589d990366e3f