已合并
feat: Add page level DPI control interface. #2058
haozhihang创建于 1月16日
feat: Add page level DPI control interface. #2058
已合并
共 14 个文件变更+532-384
| @@ -0,0 +1,15 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +import { TurboModuleRegistry } from "react-native"; | ||
| 9 | +import type { TurboModule } from "react-native/Libraries/TurboModule/RCTExport"; | ||
| 10 | + | ||
| 11 | +export interface Spec extends TurboModule { | ||
| 12 | + sendPageName(data: string): Promise<string>; | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +export default TurboModuleRegistry.get<Spec>("RegisterPageName") as Spec | null; | ||
| @@ -215,5 +215,8 @@ module.exports = { | |||
| 215 | return require('react-native/Libraries/Renderer/shims/ReactNative') | 215 | return require('react-native/Libraries/Renderer/shims/ReactNative') |
| 216 | .dispatchCommand; | 216 | .dispatchCommand; |
| 217 | }, | 217 | }, |
| 218 | + get RegisterPageName() { | ||
| 219 | + return require('./Libraries/RegisterPageName/RegisterPageName').default; | ||
| 220 | + }, | ||
| 218 | // END: react-native-harmony specific exports | 221 | // END: react-native-harmony specific exports |
| 219 | }; | 222 | }; |
| @@ -455,6 +455,7 @@ set(RNOH_SOURCE | |||
| 455 | "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/Animated/Drivers/DecayAnimationDriver.cpp" | 455 | "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/Animated/Drivers/DecayAnimationDriver.cpp" |
| 456 | "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/Animated/Drivers/EventAnimationDriver.cpp" | 456 | "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/Animated/Drivers/EventAnimationDriver.cpp" |
| 457 | "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/I18nManagerTurboModule.cpp" | 457 | "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/I18nManagerTurboModule.cpp" |
| 458 | + "${RNOH_CPP_DIR}/RNOHCorePackage/TurboModules/RegisterPageNameTurboModule.cpp" | ||
| 458 | "${RNOH_CPP_DIR}/RNOHCorePackage/EventEmitRequestHandlers/TouchEventEmitRequestHandler.cpp" | 459 | "${RNOH_CPP_DIR}/RNOHCorePackage/EventEmitRequestHandlers/TouchEventEmitRequestHandler.cpp" |
| 459 | "${RNOH_CPP_DIR}/RNOH/arkui/DynamicArkUILoader.cpp" | 460 | "${RNOH_CPP_DIR}/RNOH/arkui/DynamicArkUILoader.cpp" |
| 460 | "${RNOH_CPP_DIR}/RNOH/arkui/NodeApi.cpp" | 461 | "${RNOH_CPP_DIR}/RNOH/arkui/NodeApi.cpp" |
| @@ -522,6 +523,7 @@ endif() | |||
| 522 | target_link_libraries(rnoh PUBLIC | 523 | target_link_libraries(rnoh PUBLIC |
| 523 | libace_napi.z.so | 524 | libace_napi.z.so |
| 524 | libace_ndk.z.so | 525 | libace_ndk.z.so |
| 526 | + libability_runtime.so | ||
| 525 | libdeviceinfo_ndk.z.so | 527 | libdeviceinfo_ndk.z.so |
| 526 | libhilog_ndk.z.so | 528 | libhilog_ndk.z.so |
| 527 | librawfile.z.so | 529 | librawfile.z.so |
| @@ -41,8 +41,8 @@ | |||
| 41 | #include "RNOH/ComponentInstancePreallocationRequestQueue.h" | 41 | #include "RNOH/ComponentInstancePreallocationRequestQueue.h" |
| 42 | #include "RNOH/ComponentInstanceRegistry.h" | 42 | #include "RNOH/ComponentInstanceRegistry.h" |
| 43 | #include "RNOH/CustomComponentArkUINodeHandleFactory.h" | 43 | #include "RNOH/CustomComponentArkUINodeHandleFactory.h" |
| 44 | -#include "RNOH/MountingManagerCAPI.h" | ||
| 45 | #include "RNOH/ImageSourceResolver.h" | 44 | #include "RNOH/ImageSourceResolver.h" |
| 45 | +#include "RNOH/MountingManagerCAPI.h" | ||
| 46 | #include "RNOH/ParallelComponent.h" | 46 | #include "RNOH/ParallelComponent.h" |
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
| @@ -81,12 +81,11 @@ std::shared_ptr<RNInstanceInternal> createRNInstance( | |||
| 81 | std::unordered_set<std::string> arkTsComponentNames, | 81 | std::unordered_set<std::string> arkTsComponentNames, |
| 82 | std::unordered_map<std::string, std::string> fontPathByFontFamily, | 82 | std::unordered_map<std::string, std::string> fontPathByFontFamily, |
| 83 | std::string hspModuleName, | 83 | std::string hspModuleName, |
| 84 | - std::string cacheDir | 84 | + std::string cacheDir) { |
| 85 | - ) { | ||
| 86 | HarmonyReactMarker::logMarker( | 85 | HarmonyReactMarker::logMarker( |
| 87 | HarmonyReactMarker::HarmonyReactMarkerId::REACT_INSTANCE_INIT_START, id); | 86 | HarmonyReactMarker::HarmonyReactMarkerId::REACT_INSTANCE_INIT_START, id); |
| 88 | auto shouldUseCAPIArchitecture = | 87 | auto shouldUseCAPIArchitecture = |
| 89 | - featureFlagRegistry->getFeatureFlagStatus("C_API_ARCH"); | 88 | + featureFlagRegistry->getFeatureFlagStatus("C_API_ARCH"); |
| 90 | auto taskExecutor = std::make_shared<TaskExecutor>( | 89 | auto taskExecutor = std::make_shared<TaskExecutor>( |
| 91 | env, std::move(workerTaskRunner), shouldEnableBackgroundExecutor); | 90 | env, std::move(workerTaskRunner), shouldEnableBackgroundExecutor); |
| 92 | auto arkTSChannel = std::make_shared<ArkTSChannel>( | 91 | auto arkTSChannel = std::make_shared<ArkTSChannel>( |
| @@ -158,7 +157,7 @@ std::shared_ptr<RNInstanceInternal> createRNInstance( | |||
| 158 | }; | 157 | }; |
| 159 | 158 | ||
| 160 | for (auto& componentName : package->getComponentCreateInSubThread()) { | 159 | for (auto& componentName : package->getComponentCreateInSubThread()) { |
| 161 | - ComponentNameManager::getInstance().addComponentName(componentName); | 160 | + ComponentNameManager::getInstance().addComponentName(componentName); |
| 162 | }; | 161 | }; |
| 163 | auto packageGlobalJSIBinders = package->createGlobalJSIBinders(); | 162 | auto packageGlobalJSIBinders = package->createGlobalJSIBinders(); |
| 164 | globalJSIBinders.insert( | 163 | globalJSIBinders.insert( |
| @@ -243,12 +242,13 @@ std::shared_ptr<RNInstanceInternal> createRNInstance( | |||
| 243 | componentInstanceRegistry; | 242 | componentInstanceRegistry; |
| 244 | auto componentInstancePreallocationRequestQueue = | 243 | auto componentInstancePreallocationRequestQueue = |
| 245 | std::make_shared<ComponentInstancePreallocationRequestQueue>(); | 244 | std::make_shared<ComponentInstancePreallocationRequestQueue>(); |
| 246 | - auto componentInstanceProvider = std::make_shared<ComponentInstanceProvider>( | 245 | + auto componentInstanceProvider = |
| 247 | - componentInstancePreallocationRequestQueue, | 246 | + std::make_shared<ComponentInstanceProvider>( |
| 248 | - componentInstanceFactory, | 247 | + componentInstancePreallocationRequestQueue, |
| 249 | - componentInstanceRegistry, | 248 | + componentInstanceFactory, |
| 250 | - uiTicker, | 249 | + componentInstanceRegistry, |
| 251 | - taskExecutor); | 250 | + uiTicker, |
| 251 | + taskExecutor); | ||
| 252 | componentInstanceProvider->initialize(); | 252 | componentInstanceProvider->initialize(); |
| 253 | auto mountingManagerCAPI = std::make_shared<MountingManagerCAPI>( | 253 | auto mountingManagerCAPI = std::make_shared<MountingManagerCAPI>( |
| 254 | componentInstanceRegistry, | 254 | componentInstanceRegistry, |
| @@ -259,11 +259,12 @@ std::shared_ptr<RNInstanceInternal> createRNInstance( | |||
| 259 | featureFlagRegistry, | 259 | featureFlagRegistry, |
| 260 | arkTSChannel); | 260 | arkTSChannel); |
| 261 | SharedNativeResourceManager nativeResourceManager( | 261 | SharedNativeResourceManager nativeResourceManager( |
| 262 | - OH_ResourceManager_InitNativeResourceManager(env, jsResourceManager), | 262 | + OH_ResourceManager_InitNativeResourceManager(env, jsResourceManager), |
| 263 | - OH_ResourceManager_ReleaseNativeResourceManager); | 263 | + OH_ResourceManager_ReleaseNativeResourceManager); |
| 264 | for (auto& [fontFamilyName, fontPathRelativeToRawfileDir] : | 264 | for (auto& [fontFamilyName, fontPathRelativeToRawfileDir] : |
| 265 | - fontPathByFontFamily) { | 265 | + fontPathByFontFamily) { |
| 266 | - textMeasurer->registerFont(nativeResourceManager, fontFamilyName, fontPathRelativeToRawfileDir); | 266 | + textMeasurer->registerFont( |
| 267 | + nativeResourceManager, fontFamilyName, fontPathRelativeToRawfileDir); | ||
| 267 | } | 268 | } |
| 268 | auto rnInstance = std::make_shared<RNInstanceCAPI>( | 269 | auto rnInstance = std::make_shared<RNInstanceCAPI>( |
| 269 | id, | 270 | id, |
| @@ -19,11 +19,11 @@ | |||
| 19 | #include "RNOH/ArkTSBridge.h" | 19 | #include "RNOH/ArkTSBridge.h" |
| 20 | #include "RNOH/Inspector.h" | 20 | #include "RNOH/Inspector.h" |
| 21 | #include "RNOH/LogSink.h" | 21 | #include "RNOH/LogSink.h" |
| 22 | +#include "RNOH/ParallelCheck.h" | ||
| 22 | #include "RNOH/Performance/HarmonyReactMarker.h" | 23 | #include "RNOH/Performance/HarmonyReactMarker.h" |
| 23 | #include "RNOH/Performance/OHReactMarkerListener.h" | 24 | #include "RNOH/Performance/OHReactMarkerListener.h" |
| 24 | #include "RNOH/RNInstance.h" | 25 | #include "RNOH/RNInstance.h" |
| 25 | #include "RNOH/RNInstanceCAPI.h" | 26 | #include "RNOH/RNInstanceCAPI.h" |
| 26 | -#include "RNOH/ParallelCheck.h" | ||
| 27 | #include "RNOH/TaskExecutor/NapiTaskRunner.h" | 27 | #include "RNOH/TaskExecutor/NapiTaskRunner.h" |
| 28 | #include "RNOH/TaskExecutor/ThreadTaskRunner.h" | 28 | #include "RNOH/TaskExecutor/ThreadTaskRunner.h" |
| 29 | #include "RNOH/UITicker.h" | 29 | #include "RNOH/UITicker.h" |
| @@ -65,13 +65,13 @@ auto extractOrDefault(Map& map, K&& key, V&& defaultValue) | |||
| 65 | std::shared_ptr<facebook::react::JSExecutorFactory> getDefaultJSExecutorFactory( | 65 | std::shared_ptr<facebook::react::JSExecutorFactory> getDefaultJSExecutorFactory( |
| 66 | bool shouldEnableDebugger, | 66 | bool shouldEnableDebugger, |
| 67 | folly::dynamic initOptions) { | 67 | folly::dynamic initOptions) { |
| 68 | - #if USE_HERMES | 68 | +#if USE_HERMES |
| 69 | - DLOG(INFO) << "Using HermesExecutorFactory"; | 69 | + DLOG(INFO) << "Using HermesExecutorFactory"; |
| 70 | - return createHermesExecutorFactory(shouldEnableDebugger); | 70 | + return createHermesExecutorFactory(shouldEnableDebugger); |
| 71 | - #else | 71 | +#else |
| 72 | - DLOG(INFO) << "Using JSVMExecutorFactory"; | 72 | + DLOG(INFO) << "Using JSVMExecutorFactory"; |
| 73 | - return createJSVMExecutorFactory(initOptions); | 73 | + return createJSVMExecutorFactory(initOptions); |
| 74 | - #endif | 74 | +#endif |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | std::mutex RN_INSTANCE_BY_ID_MTX; | 77 | std::mutex RN_INSTANCE_BY_ID_MTX; |
| @@ -115,40 +115,40 @@ static napi_value onInit(napi_env env, napi_callback_info info) { | |||
| 115 | #endif | 115 | #endif |
| 116 | LogSink::initializeLogging(); | 116 | LogSink::initializeLogging(); |
| 117 | auto logVerbosityLevel = 0; | 117 | auto logVerbosityLevel = 0; |
| 118 | - | 118 | + |
| 119 | #ifdef LOG_VERBOSITY_LEVEL | 119 | #ifdef LOG_VERBOSITY_LEVEL |
| 120 | - FLAGS_v = LOG_VERBOSITY_LEVEL; | 120 | + FLAGS_v = LOG_VERBOSITY_LEVEL; |
| 121 | - logVerbosityLevel = LOG_VERBOSITY_LEVEL; | 121 | + logVerbosityLevel = LOG_VERBOSITY_LEVEL; |
| 122 | #endif | 122 | #endif |
| 123 | DLOG(INFO) << "onInit (LOG_VERBOSITY_LEVEL=" << logVerbosityLevel << ")"; | 123 | DLOG(INFO) << "onInit (LOG_VERBOSITY_LEVEL=" << logVerbosityLevel << ")"; |
| 124 | ArkJS arkJs(env); | 124 | ArkJS arkJs(env); |
| 125 | auto args = arkJs.getCallbackArgs(info, 1); | 125 | auto args = arkJs.getCallbackArgs(info, 1); |
| 126 | - nextEnvId++; | 126 | + nextEnvId++; |
| 127 | auto shouldClearRNInstances = arkJs.getBoolean(args[0]); | 127 | auto shouldClearRNInstances = arkJs.getBoolean(args[0]); |
| 128 | - if (shouldClearRNInstances) { | 128 | + if (shouldClearRNInstances) { |
| 129 | - /** | 129 | + /** |
| 130 | - * This CPP code can survive closing an app. The app can be closed before | 130 | + * This CPP code can survive closing an app. The app can be closed before |
| 131 | - * removing all RNInstances. As a workaround, all rnInstances are removed | 131 | + * removing all RNInstances. As a workaround, all rnInstances are removed |
| 132 | - * on the start. | 132 | + * on the start. |
| 133 | - */ | 133 | + */ |
| 134 | - CLEANUP_RUNNER->runAsyncTask([] { | 134 | + CLEANUP_RUNNER->runAsyncTask([] { |
| 135 | - decltype(RN_INSTANCE_BY_ID) instances; | 135 | + decltype(RN_INSTANCE_BY_ID) instances; |
| 136 | - { | 136 | + { |
| 137 | - std::lock_guard<std::mutex> lock(RN_INSTANCE_BY_ID_MTX); | 137 | + std::lock_guard<std::mutex> lock(RN_INSTANCE_BY_ID_MTX); |
| 138 | - std::swap(RN_INSTANCE_BY_ID, instances); | 138 | + std::swap(RN_INSTANCE_BY_ID, instances); |
| 139 | - } | 139 | + } |
| 140 | - instances.clear(); | 140 | + instances.clear(); |
| 141 | - }); | 141 | + }); |
| 142 | - ARK_TS_BRIDGE_BY_ENV_ID.clear(); | 142 | + ARK_TS_BRIDGE_BY_ENV_ID.clear(); |
| 143 | - } | 143 | + } |
| 144 | - auto isDebugModeEnabled = false; | 144 | + auto isDebugModeEnabled = false; |
| 145 | #ifdef REACT_NATIVE_DEBUG | 145 | #ifdef REACT_NATIVE_DEBUG |
| 146 | isDebugModeEnabled = true; | 146 | isDebugModeEnabled = true; |
| 147 | #endif | 147 | #endif |
| 148 | - return arkJs.createObjectBuilder() | 148 | + return arkJs.createObjectBuilder() |
| 149 | - .addProperty("isDebugModeEnabled", isDebugModeEnabled) | 149 | + .addProperty("isDebugModeEnabled", isDebugModeEnabled) |
| 150 | - .addProperty("envId", nextEnvId) | 150 | + .addProperty("envId", nextEnvId) |
| 151 | - .build(); | 151 | + .build(); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | napi_value initializeArkTSBridge(napi_env env, napi_callback_info info) { | 154 | napi_value initializeArkTSBridge(napi_env env, napi_callback_info info) { |
| @@ -203,9 +203,7 @@ static napi_value getNextRNInstanceId( | |||
| 203 | } | 203 | } |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | -static napi_value onCreateRNInstance( | 206 | +static napi_value onCreateRNInstance(napi_env env, napi_callback_info info) { |
| 207 | - napi_env env, | ||
| 208 | - napi_callback_info info) { | ||
| 209 | ArkJS arkJs(env); | 207 | ArkJS arkJs(env); |
| 210 | try { | 208 | try { |
| 211 | DLOG(INFO) << "createReactNativeInstance"; | 209 | DLOG(INFO) << "createReactNativeInstance"; |
| @@ -230,12 +228,10 @@ static napi_value onCreateRNInstance( | |||
| 230 | auto arkTsComponentNamesDynamic = arkJs.getDynamic(args[11]); | 228 | auto arkTsComponentNamesDynamic = arkJs.getDynamic(args[11]); |
| 231 | std::unordered_set<std::string> arkTsComponentNames = {}; | 229 | std::unordered_set<std::string> arkTsComponentNames = {}; |
| 232 | for (size_t i = 0; i < arkTsComponentNamesDynamic.size(); ++i) { | 230 | for (size_t i = 0; i < arkTsComponentNamesDynamic.size(); ++i) { |
| 233 | - arkTsComponentNames.emplace(arkTsComponentNamesDynamic[i].asString()); | 231 | + arkTsComponentNames.emplace(arkTsComponentNamesDynamic[i].asString()); |
| 234 | } | 232 | } |
| 235 | - auto fontPathByFontFamilyEntries = | 233 | + auto fontPathByFontFamilyEntries = arkJs.getObjectProperties(args[12]); |
| 236 | - arkJs.getObjectProperties(args[12]); | 234 | + std::unordered_map<std::string, std::string> fontPathByFontFamily; |
| 237 | - std::unordered_map<std::string, std::string> | ||
| 238 | - fontPathByFontFamily; | ||
| 239 | for (auto& [fontFamily, fontPathRelativeToRawfileDir] : | 235 | for (auto& [fontFamily, fontPathRelativeToRawfileDir] : |
| 240 | fontPathByFontFamilyEntries) { | 236 | fontPathByFontFamilyEntries) { |
| 241 | fontPathByFontFamily.emplace( | 237 | fontPathByFontFamily.emplace( |
| @@ -321,8 +317,8 @@ static napi_value onCreateRNInstance( | |||
| 321 | } | 317 | } |
| 322 | auto [it, _inserted] = | 318 | auto [it, _inserted] = |
| 323 | RN_INSTANCE_BY_ID.emplace(instanceId, std::move(rnInstance)); | 319 | RN_INSTANCE_BY_ID.emplace(instanceId, std::move(rnInstance)); |
| 324 | - it->second->setJavaScriptExecutorFactory( | 320 | + it->second->setJavaScriptExecutorFactory(getDefaultJSExecutorFactory( |
| 325 | - getDefaultJSExecutorFactory(shouldEnableDebugger, arkJs.getDynamic(args[14]))); | 321 | + shouldEnableDebugger, arkJs.getDynamic(args[14]))); |
| 326 | it->second->start(); | 322 | it->second->start(); |
| 327 | } catch (...) { | 323 | } catch (...) { |
| 328 | ArkTSBridge::getInstance()->handleError(std::current_exception()); | 324 | ArkTSBridge::getInstance()->handleError(std::current_exception()); |
| @@ -330,9 +326,7 @@ static napi_value onCreateRNInstance( | |||
| 330 | return arkJs.getUndefined(); | 326 | return arkJs.getUndefined(); |
| 331 | } | 327 | } |
| 332 | 328 | ||
| 333 | -static napi_value onDestroyRNInstance( | 329 | +static napi_value onDestroyRNInstance(napi_env env, napi_callback_info info) { |
| 334 | - napi_env env, | ||
| 335 | - napi_callback_info info) { | ||
| 336 | DLOG(INFO) << "destroyReactNativeInstance"; | 330 | DLOG(INFO) << "destroyReactNativeInstance"; |
| 337 | ArkJS arkJs(env); | 331 | ArkJS arkJs(env); |
| 338 | try { | 332 | try { |
| @@ -360,52 +354,51 @@ static napi_value onDestroyRNInstance( | |||
| 360 | } | 354 | } |
| 361 | 355 | ||
| 362 | static napi_value loadScript(napi_env env, napi_callback_info info) { | 356 | static napi_value loadScript(napi_env env, napi_callback_info info) { |
| 363 | - const int sourceUrlParamIdx = 2; | 357 | + const int sourceUrlParamIdx = 2; |
| 364 | - return invoke(env, [&] { | 358 | + return invoke(env, [&] { |
| 365 | - DLOG(INFO) << "loadScript"; | 359 | + DLOG(INFO) << "loadScript"; |
| 366 | - ArkJS arkJS(env); | 360 | + ArkJS arkJS(env); |
| 367 | - auto args = arkJS.getCallbackArgs(info, 4); | 361 | + auto args = arkJS.getCallbackArgs(info, 4); |
| 368 | - size_t instanceId = arkJS.getDouble(args[0]); | 362 | + size_t instanceId = arkJS.getDouble(args[0]); |
| 369 | - auto rnInstance = maybeGetInstanceById(instanceId); | 363 | + auto rnInstance = maybeGetInstanceById(instanceId); |
| 370 | - if (!rnInstance) { | 364 | + if (!rnInstance) { |
| 371 | - return arkJS.getUndefined(); | 365 | + return arkJS.getUndefined(); |
| 372 | - } | 366 | + } |
| 373 | - auto onFinishRef = arkJS.createNapiRef(args[3]); | 367 | + auto onFinishRef = arkJS.createNapiRef(args[3]); |
| 374 | 368 | ||
| 375 | - auto callback = [env, onFinishRef = std::move(onFinishRef), rnInstance]( | 369 | + auto callback = [env, onFinishRef = std::move(onFinishRef), rnInstance]( |
| 376 | - const std::string& errorMsg) mutable { | 370 | + const std::string& errorMsg) mutable { |
| 377 | - auto taskExecutor = rnInstance->getTaskExecutor(); | 371 | + auto taskExecutor = rnInstance->getTaskExecutor(); |
| 378 | - taskExecutor->runTask( | 372 | + taskExecutor->runTask( |
| 379 | - TaskThread::MAIN, | 373 | + TaskThread::MAIN, |
| 380 | - [env, onFinishRef = std::move(onFinishRef), errorMsg]() { | 374 | + [env, onFinishRef = std::move(onFinishRef), errorMsg]() { |
| 381 | - ArkJS arkJS(env); | 375 | + ArkJS arkJS(env); |
| 382 | - auto listener = arkJS.getReferenceValue(onFinishRef); | 376 | + auto listener = arkJS.getReferenceValue(onFinishRef); |
| 383 | - arkJS.call<1>(listener, {arkJS.createString(errorMsg)}); | 377 | + arkJS.call<1>(listener, {arkJS.createString(errorMsg)}); |
| 384 | - }); | 378 | + }); |
| 385 | - }; | 379 | + }; |
| 386 | 380 | ||
| 387 | - if (arkJS.isArrayBuffer(args[1])) { | 381 | + if (arkJS.isArrayBuffer(args[1])) { |
| 388 | - std::vector<uint8_t> bundleContents = arkJS.getArrayBuffer(args[1]); | 382 | + std::vector<uint8_t> bundleContents = arkJS.getArrayBuffer(args[1]); |
| 389 | - rnInstance->loadScriptFromBuffer( | 383 | + rnInstance->loadScriptFromBuffer( |
| 390 | - std::move(bundleContents), | 384 | + std::move(bundleContents), |
| 391 | - arkJS.getString(args[sourceUrlParamIdx]), | 385 | + arkJS.getString(args[sourceUrlParamIdx]), |
| 392 | - callback); | 386 | + callback); |
| 393 | - } else { | 387 | + } else { |
| 394 | - if (arkJS.hasProperty(args[1], "filePath")) { | 388 | + if (arkJS.hasProperty(args[1], "filePath")) { |
| 395 | - auto filePathNapiValue = | 389 | + auto filePathNapiValue = arkJS.getObjectProperty(args[1], "filePath"); |
| 396 | - arkJS.getObjectProperty(args[1], "filePath"); | 390 | + std::string filePath = arkJS.getString(filePathNapiValue); |
| 397 | - std::string filePath = arkJS.getString(filePathNapiValue); | 391 | + rnInstance->loadScriptFromFile(filePath, callback); |
| 398 | - rnInstance->loadScriptFromFile(filePath, callback); | 392 | + } else if (arkJS.hasProperty(args[1], "rawFilePath")) { |
| 399 | - } else if (arkJS.hasProperty(args[1], "rawFilePath")) { | 393 | + auto rawFilePathNapiValue = |
| 400 | - auto rawFilePathNapiValue = | 394 | + arkJS.getObjectProperty(args[1], "rawFilePath"); |
| 401 | - arkJS.getObjectProperty(args[1], "rawFilePath"); | 395 | + std::string rawFilePath = arkJS.getString(rawFilePathNapiValue); |
| 402 | - std::string rawFilePath = arkJS.getString(rawFilePathNapiValue); | 396 | + rnInstance->loadScriptFromRawFile(rawFilePath, callback); |
| 403 | - rnInstance->loadScriptFromRawFile(rawFilePath, callback); | 397 | + } |
| 404 | - } | 398 | + } |
| 405 | - } | ||
| 406 | 399 | ||
| 407 | - return arkJS.getNull(); | 400 | + return arkJS.getNull(); |
| 408 | - }); | 401 | + }); |
| 409 | } | 402 | } |
| 410 | 403 | ||
| 411 | static napi_value updateSurfaceConstraints( | 404 | static napi_value updateSurfaceConstraints( |
| @@ -679,7 +672,7 @@ static napi_value onArkTSMessage(napi_env env, napi_callback_info info) { | |||
| 679 | if (!rnInstance) { | 672 | if (!rnInstance) { |
| 680 | return arkJs.getUndefined(); | 673 | return arkJs.getUndefined(); |
| 681 | } | 674 | } |
| 682 | - std::weak_ptr<RNInstanceInternal> weakRNInstance = rnInstance; | 675 | + std::weak_ptr<RNInstanceInternal> weakRNInstance = rnInstance; |
| 683 | auto taskExecutor = rnInstance->getTaskExecutor(); | 676 | auto taskExecutor = rnInstance->getTaskExecutor(); |
| 684 | if (taskExecutor->isOnTaskThread(TaskThread::MAIN)) { | 677 | if (taskExecutor->isOnTaskThread(TaskThread::MAIN)) { |
| 685 | rnInstance->handleArkTSMessage(messageName, messagePayload); | 678 | rnInstance->handleArkTSMessage(messageName, messagePayload); |
| @@ -771,8 +764,7 @@ static napi_value setUIContext(napi_env env, napi_callback_info info) { | |||
| 771 | }); | 764 | }); |
| 772 | } | 765 | } |
| 773 | 766 | ||
| 774 | -static napi_value setBundlePath(napi_env env, napi_callback_info info) | 767 | +static napi_value setBundlePath(napi_env env, napi_callback_info info) { |
| 775 | -{ | ||
| 776 | DLOG(INFO) << "setBundlePath"; | 768 | DLOG(INFO) << "setBundlePath"; |
| 777 | ArkJS arkJs(env); | 769 | ArkJS arkJs(env); |
| 778 | try { | 770 | try { |
| @@ -833,7 +825,8 @@ static napi_value getNativeNodeIdByTag(napi_env env, napi_callback_info info) { | |||
| 833 | }); | 825 | }); |
| 834 | } | 826 | } |
| 835 | 827 | ||
| 836 | -static napi_value setParallelizationEnabled(napi_env env, | 828 | +static napi_value setParallelizationEnabled( |
| 829 | + napi_env env, | ||
| 837 | napi_callback_info info) { | 830 | napi_callback_info info) { |
| 838 | return invoke(env, [&] { | 831 | return invoke(env, [&] { |
| 839 | ArkJS arkJS(env); | 832 | ArkJS arkJS(env); |
| @@ -1031,7 +1024,7 @@ static napi_value Init(napi_env env, napi_value exports) { | |||
| 1031 | nullptr, | 1024 | nullptr, |
| 1032 | napi_default, | 1025 | napi_default, |
| 1033 | nullptr}, | 1026 | nullptr}, |
| 1034 | - {"getNativeNodeIdByTag", | 1027 | + {"getNativeNodeIdByTag", |
| 1035 | nullptr, | 1028 | nullptr, |
| 1036 | ::getNativeNodeIdByTag, | 1029 | ::getNativeNodeIdByTag, |
| 1037 | nullptr, | 1030 | nullptr, |
| @@ -1039,7 +1032,7 @@ static napi_value Init(napi_env env, napi_value exports) { | |||
| 1039 | nullptr, | 1032 | nullptr, |
| 1040 | napi_default, | 1033 | napi_default, |
| 1041 | nullptr}, | 1034 | nullptr}, |
| 1042 | - {"attachRootView", | 1035 | + {"attachRootView", |
| 1043 | nullptr, | 1036 | nullptr, |
| 1044 | ::attachRootView, | 1037 | ::attachRootView, |
| 1045 | nullptr, | 1038 | nullptr, |
| @@ -83,6 +83,7 @@ | |||
| 83 | #include "RNOHCorePackage/TurboModules/ToastAndroidTurboModule.h" | 83 | #include "RNOHCorePackage/TurboModules/ToastAndroidTurboModule.h" |
| 84 | #include "RNOHCorePackage/TurboModules/VibrationTurboModule.h" | 84 | #include "RNOHCorePackage/TurboModules/VibrationTurboModule.h" |
| 85 | #include "RNOHCorePackage/TurboModules/WebSocketTurboModule.h" | 85 | #include "RNOHCorePackage/TurboModules/WebSocketTurboModule.h" |
| 86 | +#include "RNOHCorePackage/TurboModules/RegisterPageNameTurboModule.h" | ||
| 86 | 87 | ||
| 87 | namespace rnoh { | 88 | namespace rnoh { |
| 88 | 89 | ||
| @@ -148,6 +149,8 @@ class RNOHCoreTurboModuleFactoryDelegate : public TurboModuleFactoryDelegate { | |||
| 148 | return std::make_shared<ToastAndroidTurboModule>(ctx, name); | 149 | return std::make_shared<ToastAndroidTurboModule>(ctx, name); |
| 149 | } else if (name == "ShareModule") { | 150 | } else if (name == "ShareModule") { |
| 150 | return std::make_shared<ShareTurboModule>(ctx, name); | 151 | return std::make_shared<ShareTurboModule>(ctx, name); |
| 152 | + } else if (name == "RegisterPageName") { | ||
| 153 | + return std::make_shared<RegisterPageName>(ctx, name); | ||
| 151 | } | 154 | } |
| 152 | return nullptr; | 155 | return nullptr; |
| 153 | }; | 156 | }; |
| @@ -261,6 +264,11 @@ class RNOHCorePackage : public Package { | |||
| 261 | std::make_shared<ActivityIndicatorComponentNapiBinder>()}}; | 264 | std::make_shared<ActivityIndicatorComponentNapiBinder>()}}; |
| 262 | }; | 265 | }; |
| 263 | 266 | ||
| 267 | + std::vector<ArkTSMessageHandler::Shared> createArkTSMessageHandlers() | ||
| 268 | + override { | ||
| 269 | + return {std::make_shared<RegisterPageNameMessageHandler>()}; | ||
| 270 | + } | ||
| 271 | + | ||
| 264 | EventEmitRequestHandlers createEventEmitRequestHandlers() override { | 272 | EventEmitRequestHandlers createEventEmitRequestHandlers() override { |
| 265 | return { | 273 | return { |
| 266 | std::make_shared<TouchEventEmitRequestHandler>(), | 274 | std::make_shared<TouchEventEmitRequestHandler>(), |
| @@ -0,0 +1,67 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#include "RegisterPageNameTurboModule.h" | ||
| 9 | +#include <dlfcn.h> | ||
| 10 | +#include "AbilityKit/ability_runtime/application_context.h" | ||
| 11 | +#include "RNOH/ApiVersionCheck.h" | ||
| 12 | +#include "RNOH/ArkTSMessageHandler.h" | ||
| 13 | +#include "RNOH/RNInstance.h" | ||
| 14 | +#include "napi/native_api.h" | ||
| 15 | + | ||
| 16 | +namespace rnoh { | ||
| 17 | +using namespace facebook; | ||
| 18 | + | ||
| 19 | +double RegisterPageName::s_windowId = 0; | ||
| 20 | +std::string RegisterPageName::s_bundleCodeDir; | ||
| 21 | + | ||
| 22 | +void RegisterPageNameMessageHandler::handleArkTSMessage( | ||
| 23 | + const ArkTSMessageHandler::Context& ctx) { | ||
| 24 | + if (ctx.messageName == "WINDOW_ID") { | ||
| 25 | + RegisterPageName::s_windowId = ctx.messagePayload.asDouble(); | ||
| 26 | + } | ||
| 27 | + if (ctx.messageName == "BUNDLE_CODE_DIR") { | ||
| 28 | + RegisterPageName::s_bundleCodeDir = ctx.messagePayload.asString(); | ||
【AI-Review】【致命】【基础代码问题】【返回值缺失】 ● 问题: Lambda 函数在多个分支中缺少返回值。当 count <= 0 或 args[0] 不是字符串时,函数直接退出而没有返回 jsi::Value;当 dlsym 返回 nullptr 时,仅打印日志但也未返回值。函数签名明确要求返回 jsi::Value,缺少返回值会导致未定义行为。 ● 影响: 可能导致应用崩溃或不可预期的行为。根据 C++ 标准,非 void 函数退出时未返回值属于未定义行为。 ● 建议: 在所有分支中添加明确的返回值,例如: if (OH_GetSdkApiVersion() < API_LEVEL_23) { return jsi::Value::undefined(); } if (count == 0 || !args[0].isString()) { return jsi::Value::undefined(); } // dlsym 失败时 if (notifyPageChanged != nullptr) { ... } else { LOG(ERROR) << "..."; return jsi::Value::undefined(); } ![]() ![]() | |||
| 29 | + } | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +RegisterPageName::RegisterPageName( | ||
| 33 | + const TurboModule::Context ctx, | ||
| 34 | + const std::string name) | ||
| 35 | + : TurboModule(ctx, name) { | ||
| 36 | + methodMap_["sendPageName"] = MethodMetadata{ | ||
| 37 | + 1, | ||
| 38 | + [](jsi::Runtime& rt, | ||
| 39 | + react::TurboModule& turboModule, | ||
| 40 | + const jsi::Value* args, | ||
| 41 | + size_t count) -> jsi::Value { | ||
| 42 | + constexpr int API_LEVEL_23 = 23; | ||
| 43 | + if (OH_GetSdkApiVersion() < API_LEVEL_23) { | ||
| 44 | + return jsi::Value::undefined(); | ||
| 45 | + } | ||
| 46 | + if (count > 0 && args[0].isString()) { | ||
| 47 | + std::string param = RegisterPageName::s_bundleCodeDir + "/" + | ||
| 48 | + args[0].asString(rt).utf8(rt); | ||
| 49 | + const char* pageName = param.c_str(); | ||
| 50 | + int32_t pageNameLen = param.length(); | ||
| 51 | + int32_t windowId = RegisterPageName::s_windowId; | ||
| 52 | + using NotifyPageChangedFunc = | ||
| 53 | + int32_t (*)(const char*, int32_t, int32_t); | ||
| 54 | + auto notifyPageChanged = (NotifyPageChangedFunc)dlsym( | ||
| 55 | + RTLD_DEFAULT, | ||
| 56 | + "OH_AbilityRuntime_ApplicationContextNotifyPageChanged"); | ||
| 57 | + if (notifyPageChanged != nullptr) { | ||
| 58 | + int32_t result = notifyPageChanged(pageName, pageNameLen, windowId); | ||
| 59 | + return jsi::String::createFromUtf8(rt, std::to_string(result)); | ||
| 60 | + } else { | ||
| 61 | + LOG(ERROR) << "DPI scaling capability is not supported."; | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + }}; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +} // namespace rnoh | ||
| @@ -0,0 +1,27 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * This source code is licensed under the MIT license found in the | ||
| 5 | + * LICENSE-MIT file in the root directory of this source tree. | ||
| 6 | + */ | ||
| 7 | + | ||
| 8 | +#pragma once | ||
| 9 | + | ||
| 10 | +#include "RNOH/TurboModule.h" | ||
| 11 | +#include "RNOH/ArkTSMessageHandler.h" | ||
| 12 | + | ||
| 13 | +namespace rnoh { | ||
| 14 | + | ||
| 15 | +class JSI_EXPORT RegisterPageName : public TurboModule { | ||
| 16 | + public: | ||
| 17 | + RegisterPageName(const TurboModule::Context ctx, const std::string name); | ||
| 18 | + static double s_windowId; | ||
| 19 | + static std::string s_bundleCodeDir; | ||
| 20 | +}; | ||
| 21 | + | ||
| 22 | +class RegisterPageNameMessageHandler : public ArkTSMessageHandler { | ||
| 23 | + public: | ||
| 24 | + void handleArkTSMessage(const Context& ctx) override; | ||
| 25 | +}; | ||
| 26 | + | ||
| 27 | +} | ||
| @@ -138,6 +138,9 @@ export abstract class RNAbility extends UIAbility { | |||
| 138 | try { | 138 | try { |
| 139 | await this.onPrepareRNInstance(AppStorage.get<RNOHCoreContext>('RNOHCoreContext')!) | 139 | await this.onPrepareRNInstance(AppStorage.get<RNOHCoreContext>('RNOHCoreContext')!) |
| 140 | const mainWindow = await windowStage.getMainWindow(); | 140 | const mainWindow = await windowStage.getMainWindow(); |
| 141 | + const windowID = mainWindow.getWindowProperties().id; | ||
| 142 | + this.rnInstancesCoordinator?.postMessageToCpp("WINDOW_ID", windowID); | ||
| 143 | + this.rnInstancesCoordinator?.postMessageToCpp("BUNDLE_CODE_DIR", this.context.bundleCodeDir); | ||
| 141 | this.rnInstancesCoordinator?.setMainWindow(mainWindow); | 144 | this.rnInstancesCoordinator?.setMainWindow(mainWindow); |
| 142 | const onWindowSizeChange = (windowSize: window.Size) => { | 145 | const onWindowSizeChange = (windowSize: window.Size) => { |
| 143 | this.rnInstancesCoordinator?.onWindowSizeChange(windowSize) | 146 | this.rnInstancesCoordinator?.onWindowSizeChange(windowSize) |
| @@ -14,9 +14,9 @@ import type { RNOHLogger } from './RNOHLogger'; | |||
| 14 | import type { DevToolsController } from './DevToolsController'; | 14 | import type { DevToolsController } from './DevToolsController'; |
| 15 | import { HttpClientProvider } from './HttpClientProvider'; | 15 | import { HttpClientProvider } from './HttpClientProvider'; |
| 16 | import { HttpClient } from '../HttpClient/ts'; | 16 | import { HttpClient } from '../HttpClient/ts'; |
| 17 | -import { DisplayMetricsManager } from "./DisplayMetricsManager" | 17 | +import { DisplayMetricsManager } from './DisplayMetricsManager' |
| 18 | import resourceManager from '@ohos.resourceManager'; | 18 | import resourceManager from '@ohos.resourceManager'; |
| 19 | -import { WorkerThread } from "./WorkerThread" | 19 | +import { WorkerThread } from './WorkerThread' |
| 20 | import common from '@ohos.app.ability.common' | 20 | import common from '@ohos.app.ability.common' |
| 21 | import { RNOHCorePackage } from '../RNOHCorePackage/Package' | 21 | import { RNOHCorePackage } from '../RNOHCorePackage/Package' |
| 22 | import { RNOHErrorEventEmitter } from './RNOHError'; | 22 | import { RNOHErrorEventEmitter } from './RNOHError'; |
| @@ -48,6 +48,7 @@ export class RNInstanceRegistry { | |||
| 48 | private workerThreadPromise: Promise<WorkerThread> | undefined | 48 | private workerThreadPromise: Promise<WorkerThread> | undefined |
| 49 | private launchUri?: string | 49 | private launchUri?: string |
| 50 | private cacheDir?: string | 50 | private cacheDir?: string |
| 51 | + private onInstanceCreated?: (rnInstance: RNInstanceImpl) => void | ||
| 51 | 52 | ||
| 52 | constructor( | 53 | constructor( |
| 53 | uiAbilityContext: common.UIAbilityContext, | 54 | uiAbilityContext: common.UIAbilityContext, |
| @@ -63,7 +64,8 @@ export class RNInstanceRegistry { | |||
| 63 | displayMetricsManager: DisplayMetricsManager, | 64 | displayMetricsManager: DisplayMetricsManager, |
| 64 | workerThreadPromise: Promise<WorkerThread> | undefined, | 65 | workerThreadPromise: Promise<WorkerThread> | undefined, |
| 65 | launchUri: string | undefined, | 66 | launchUri: string | undefined, |
| 66 | - cacheDir: string | undefined | 67 | + cacheDir: string | undefined, |
| 68 | + onInstanceCreated?: (rnInstance: RNInstanceImpl) => void, | ||
| 67 | ) { | 69 | ) { |
| 68 | this.uiAbilityContext = uiAbilityContext | 70 | this.uiAbilityContext = uiAbilityContext |
| 69 | this.envId = envId | 71 | this.envId = envId |
| @@ -79,6 +81,7 @@ export class RNInstanceRegistry { | |||
| 79 | this.workerThreadPromise = workerThreadPromise | 81 | this.workerThreadPromise = workerThreadPromise |
| 80 | this.launchUri = launchUri | 82 | this.launchUri = launchUri |
| 81 | this.cacheDir = cacheDir | 83 | this.cacheDir = cacheDir |
| 84 | + this.onInstanceCreated = onInstanceCreated | ||
| 82 | } | 85 | } |
| 83 | 86 | ||
| 84 | public async createInstance(options: RNInstanceOptions): Promise<RNInstance> { | 87 | public async createInstance(options: RNInstanceOptions): Promise<RNInstance> { |
| @@ -139,6 +142,7 @@ export class RNInstanceRegistry { | |||
| 139 | packages.unshift(new RNOHCorePackage({})); | 142 | packages.unshift(new RNOHCorePackage({})); |
| 140 | await rnInstance.initialize(packages); | 143 | await rnInstance.initialize(packages); |
| 141 | this.instanceMap.set(id, rnInstance); | 144 | this.instanceMap.set(id, rnInstance); |
| 145 | + this.onInstanceCreated?.(rnInstance); | ||
| 142 | return rnInstance; | 146 | return rnInstance; |
| 143 | } | 147 | } |
| 144 | 148 | ||
| @@ -102,7 +102,7 @@ function getMetadata(name: string): string { | |||
| 102 | */ | 102 | */ |
| 103 | export class RNInstancesCoordinator { | 103 | export class RNInstancesCoordinator { |
| 104 | private static isInitialized = false | 104 | private static isInitialized = false |
| 105 | - private isBoldTextEnabled:boolean | undefined = undefined; | 105 | + private isBoldTextEnabled: boolean | undefined = undefined; |
| 106 | 106 | ||
| 107 | static create(dependencies: RNInstancesCoordinatorDependencies, | 107 | static create(dependencies: RNInstancesCoordinatorDependencies, |
| 108 | options?: RNInstancesCoordinatorOptions): RNInstancesCoordinator { | 108 | options?: RNInstancesCoordinatorOptions): RNInstancesCoordinator { |
| @@ -118,7 +118,8 @@ export class RNInstancesCoordinator { | |||
| 118 | const devToolsController = new DevToolsController(dependencies.logger); | 118 | const devToolsController = new DevToolsController(dependencies.logger); |
| 119 | const napiBridge = new NapiBridge(dependencies.logger); | 119 | const napiBridge = new NapiBridge(dependencies.logger); |
| 120 | const displayMetricsManager = new DisplayMetricsManager(dependencies.logger); | 120 | const displayMetricsManager = new DisplayMetricsManager(dependencies.logger); |
| 121 | - displayMetricsManager.setFontSizeScale(dependencies.fontSizeScale ?? dependencies.uiAbilityContext.config.fontSizeScale ?? 1) | 121 | + displayMetricsManager.setFontSizeScale(dependencies.fontSizeScale ?? |
| 122 | + dependencies.uiAbilityContext.config.fontSizeScale ?? 1) | ||
| 122 | const globalRNOHErrorEventEmitter: RNOHErrorEventEmitter = new EventEmitter(); | 123 | const globalRNOHErrorEventEmitter: RNOHErrorEventEmitter = new EventEmitter(); |
| 123 | globalRNOHErrorEventEmitter.subscribe("NEW_ERROR", (err) => { | 124 | globalRNOHErrorEventEmitter.subscribe("NEW_ERROR", (err) => { |
| 124 | dependencies.logger.error(err); | 125 | dependencies.logger.error(err); |
| @@ -210,10 +211,12 @@ export class RNInstancesCoordinator { | |||
| 210 | private timerId: number = 0; | 211 | private timerId: number = 0; |
| 211 | private lastChangeTime: number = 0; | 212 | private lastChangeTime: number = 0; |
| 212 | private isWindowRectDrag: boolean = false; | 213 | private isWindowRectDrag: boolean = false; |
| 214 | + private windowId: number | undefined = undefined; | ||
| 215 | + private bundleCodeDir: string | undefined = undefined; | ||
| 213 | /** | 216 | /** |
| 214 | - * Note: You may need to change this delay along with RNSurface's onMeasuredSize delay, | 217 | + * Note: You may need to change this delay along with RNSurface's onMeasuredSize delay, |
| 215 | - * as both have an effect on window changes. | 218 | + * as both have an effect on window changes. |
| 216 | - */ | 219 | + */ |
| 217 | private readonly delayTime: number = 500; | 220 | private readonly delayTime: number = 500; |
| 218 | 221 | ||
| 219 | private constructor(napiBridge: NapiBridge, | 222 | private constructor(napiBridge: NapiBridge, |
| @@ -271,7 +274,15 @@ export class RNInstancesCoordinator { | |||
| 271 | displayMetricsManager, | 274 | displayMetricsManager, |
| 272 | workerThreadPromise, | 275 | workerThreadPromise, |
| 273 | this.options?.launchURI, | 276 | this.options?.launchURI, |
| 274 | - this.uiAbilityContext.cacheDir | 277 | + this.uiAbilityContext.cacheDir, |
| 278 | + (rnInstance) => { | ||
| 279 | + if (this.windowId !== undefined) { | ||
| 280 | + rnInstance.postMessageToCpp("WINDOW_ID", this.windowId); | ||
| 281 | + } | ||
| 282 | + if (this.bundleCodeDir !== undefined) { | ||
| 283 | + rnInstance.postMessageToCpp("BUNDLE_CODE_DIR", this.bundleCodeDir); | ||
| 284 | + } | ||
| 285 | + } | ||
| 275 | ) | 286 | ) |
| 276 | this.rnohCoreContext = new InternalRNOHCoreContext({ | 287 | this.rnohCoreContext = new InternalRNOHCoreContext({ |
| 277 | reactNativeVersion: "0.72.5", | 288 | reactNativeVersion: "0.72.5", |
| @@ -372,7 +383,7 @@ export class RNInstancesCoordinator { | |||
| 372 | if (this.timerId) { | 383 | if (this.timerId) { |
| 373 | clearTimeout(this.timerId) | 384 | clearTimeout(this.timerId) |
| 374 | } | 385 | } |
| 375 | - this.timerId = setTimeout(() =>{ | 386 | + this.timerId = setTimeout(() => { |
| 376 | this.displayMetricsManager.updateWindowSize(windowSize); | 387 | this.displayMetricsManager.updateWindowSize(windowSize); |
| 377 | this.rnInstanceRegistry.forEach((rnInstance) => { | 388 | this.rnInstanceRegistry.forEach((rnInstance) => { |
| 378 | rnInstance.onWindowSizeChange(windowSize) | 389 | rnInstance.onWindowSizeChange(windowSize) |
| @@ -397,7 +408,7 @@ export class RNInstancesCoordinator { | |||
| 397 | 408 | ||
| 398 | public onConfigurationUpdate(systemConfiguration: AbilityConfiguration.Configuration) { | 409 | public onConfigurationUpdate(systemConfiguration: AbilityConfiguration.Configuration) { |
| 399 | this.displayMetricsManager?.setFontSizeScale(systemConfiguration.fontSizeScale); | 410 | this.displayMetricsManager?.setFontSizeScale(systemConfiguration.fontSizeScale); |
| 400 | - | 411 | + |
| 401 | const fontWeightScale = systemConfiguration.fontWeightScale; | 412 | const fontWeightScale = systemConfiguration.fontWeightScale; |
| 402 | let isEmitBoldTextEvent = false; | 413 | let isEmitBoldTextEvent = false; |
| 403 | if (fontWeightScale !== undefined) { | 414 | if (fontWeightScale !== undefined) { |
| @@ -429,4 +440,17 @@ export class RNInstancesCoordinator { | |||
| 429 | rnInstance.onNewWant(want.uri); | 440 | rnInstance.onNewWant(want.uri); |
| 430 | }) | 441 | }) |
| 431 | } | 442 | } |
| 443 | + | ||
| 444 | + public postMessageToCpp(name: string, payload: ESObject) { | ||
| 445 | + if (name === "WINDOW_ID" && typeof payload === "number") { | ||
| 446 | + this.windowId = payload; | ||
| 447 | + } | ||
| 448 | + if (name === "BUNDLE_CODE_DIR" && typeof payload === "string") { | ||
| 449 | + this.bundleCodeDir = payload; | ||
| 450 | + } | ||
| 451 | + | ||
| 452 | + this.rnInstanceRegistry?.forEach((rnInstance) => { | ||
| 453 | + rnInstance.postMessageToCpp(name, payload); | ||
| 454 | + }); | ||
| 455 | + } | ||
| 432 | } | 456 | } |
| @@ -21,26 +21,23 @@ using namespace rnoh; | |||
| 21 | using namespace facebook; | 21 | using namespace facebook; |
| 22 | using namespace react; | 22 | using namespace react; |
| 23 | 23 | ||
| 24 | - | 24 | +bool NativeCxxModuleExampleCxxSpecJSI::getBool(jsi::Runtime& rt, bool arg) { |
| 25 | -bool NativeCxxModuleExampleCxxSpecJSI::getBool( | 25 | + return arg; |
| 26 | - jsi::Runtime &rt, | ||
| 27 | - bool arg) { | ||
| 28 | - return arg; | ||
| 29 | } | 26 | } |
| 30 | 27 | ||
| 31 | int32_t NativeCxxModuleExampleCxxSpecJSI::getEnum( | 28 | int32_t NativeCxxModuleExampleCxxSpecJSI::getEnum( |
| 32 | - jsi::Runtime &rt, | 29 | + jsi::Runtime& rt, |
| 33 | int32_t arg) { | 30 | int32_t arg) { |
| 34 | - return arg; | 31 | + return arg; |
| 35 | } | 32 | } |
| 36 | std::set<float> NativeCxxModuleExampleCxxSpecJSI::getSet( | 33 | std::set<float> NativeCxxModuleExampleCxxSpecJSI::getSet( |
| 37 | - jsi::Runtime &rt, | 34 | + jsi::Runtime& rt, |
| 38 | std::set<float> arg) { | 35 | std::set<float> arg) { |
| 39 | - return arg; | 36 | + return arg; |
| 40 | } | 37 | } |
| 41 | 38 | ||
| 42 | double NativeCxxModuleExampleCxxSpecJSI::getNumber( | 39 | double NativeCxxModuleExampleCxxSpecJSI::getNumber( |
| 43 | - jsi::Runtime& rt, | 40 | + jsi::Runtime& rt, |
| 44 | double arg) { | 41 | double arg) { |
| 45 | return arg; | 42 | return arg; |
| 46 | } | 43 | } |
| @@ -10,8 +10,8 @@ | |||
| 10 | 10 | ||
| 11 | #include <ReactCommon/TurboModule.h> | 11 | #include <ReactCommon/TurboModule.h> |
| 12 | #include <react/bridging/Bridging.h> | 12 | #include <react/bridging/Bridging.h> |
| 13 | -#include "RNOH/ArkTSTurboModule.h" | ||
| 14 | #include <map> | 13 | #include <map> |
| 14 | +#include "RNOH/ArkTSTurboModule.h" | ||
| 15 | 15 | ||
| 16 | using namespace rnoh; | 16 | using namespace rnoh; |
| 17 | using namespace facebook; | 17 | using namespace facebook; |
| @@ -28,17 +28,17 @@ struct ConstantsStruct { | |||
| 28 | 28 | ||
| 29 | struct ObjectStruct { | 29 | struct ObjectStruct { |
| 30 | std::string a; | 30 | std::string a; |
| 31 | - std::string b; | 31 | + std::string b; |
| 32 | std::string c; | 32 | std::string c; |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | struct objectStruct { | 35 | struct objectStruct { |
| 36 | int32_t a; | 36 | int32_t a; |
| 37 | - std::string b; | 37 | + std::string b; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | -struct ValueStruct { | 40 | +struct ValueStruct { |
| 41 | - double x; | 41 | + double x; |
| 42 | std::string y; | 42 | std::string y; |
| 43 | objectStruct z; | 43 | objectStruct z; |
| 44 | }; | 44 | }; |
| @@ -57,29 +57,26 @@ class JSI_EXPORT NativeCxxModuleExampleCxxSpecJSI : public TurboModule { | |||
| 57 | 57 | ||
| 58 | std::string getString(jsi::Runtime& rt, std::string arg); | 58 | std::string getString(jsi::Runtime& rt, std::string arg); |
| 59 | 59 | ||
| 60 | - jsi::String getValueWithCallback( | 60 | + jsi::String getValueWithCallback(jsi::Runtime& rt); |
| 61 | - jsi::Runtime& rt); | ||
| 62 | 61 | ||
| 63 | ConstantsStruct getConstants(jsi::Runtime& rt); | 62 | ConstantsStruct getConstants(jsi::Runtime& rt); |
| 64 | 63 | ||
| 65 | std::vector<std::optional<ObjectStruct>> getArray( | 64 | std::vector<std::optional<ObjectStruct>> getArray( |
| 66 | - jsi::Runtime& rt, | 65 | + jsi::Runtime& rt, |
| 67 | - std::vector<std::optional<ObjectStruct>> arg); | 66 | + std::vector<std::optional<ObjectStruct>> arg); |
| 68 | 67 | ||
| 69 | - std::map<std::string,std::optional<int32_t>> getMap( | 68 | + std::map<std::string, std::optional<int32_t>> getMap( |
| 70 | - jsi::Runtime& rt, | 69 | + jsi::Runtime& rt, |
| 71 | - std::map<std::string, | 70 | + std::map<std::string, std::optional<int32_t>> arg); |
| 72 | - std::optional<int32_t>> arg); | ||
| 73 | 71 | ||
| 74 | objectStruct getObject(jsi::Runtime& rt, objectStruct arg); | 72 | objectStruct getObject(jsi::Runtime& rt, objectStruct arg); |
| 75 | 73 | ||
| 76 | - std::set<float> getSet(jsi::Runtime &rt, std::set<float> arg); | 74 | + std::set<float> getSet(jsi::Runtime& rt, std::set<float> arg); |
| 77 | 75 | ||
| 78 | - ValueStruct getValue(jsi::Runtime& rt, | 76 | + ValueStruct |
| 79 | - double x, std::string y, objectStruct z); | 77 | + getValue(jsi::Runtime& rt, double x, std::string y, objectStruct z); |
| 80 | 78 | ||
| 81 | - std::string getUnion(jsi::Runtime& rt,float x, | 79 | + std::string getUnion(jsi::Runtime& rt, float x, std::string y, jsi::Object z); |
| 82 | - std::string y,jsi::Object z); | ||
| 83 | 80 | ||
| 84 | void voidFunc(jsi::Runtime& rt); | 81 | void voidFunc(jsi::Runtime& rt); |
| 85 | }; | 82 | }; |
| @@ -45,27 +45,27 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI( | |||
| 45 | const ArkTSTurboModule::Context ctx, | 45 | const ArkTSTurboModule::Context ctx, |
| 46 | const std::string name) | 46 | const std::string name) |
| 47 | : ArkTSTurboModule(ctx, name) { | 47 | : ArkTSTurboModule(ctx, name) { |
| 48 | - methodMap_ = { | 48 | + methodMap_ = { |
| 49 | - ARK_METHOD_METADATA(voidFunc, 0), | 49 | + ARK_METHOD_METADATA(voidFunc, 0), |
| 50 | - ARK_METHOD_METADATA(getBool, 1), | 50 | + ARK_METHOD_METADATA(getBool, 1), |
| 51 | - ARK_METHOD_METADATA(getString, 1), | 51 | + ARK_METHOD_METADATA(getString, 1), |
| 52 | - ARK_METHOD_METADATA(getObject, 1), | 52 | + ARK_METHOD_METADATA(getObject, 1), |
| 53 | - ARK_METHOD_METADATA(registerFunction, 1), | 53 | + ARK_METHOD_METADATA(registerFunction, 1), |
| 54 | - ARK_ASYNC_METHOD_METADATA(doAsyncJob, 1), | 54 | + ARK_ASYNC_METHOD_METADATA(doAsyncJob, 1), |
| 55 | - ARK_ASYNC_METHOD_METADATA(getPromisedArray, 0), | 55 | + ARK_ASYNC_METHOD_METADATA(getPromisedArray, 0), |
| 56 | - ARK_METHOD_METADATA(getUnionValue, 1), | 56 | + ARK_METHOD_METADATA(getUnionValue, 1), |
| 57 | - ARK_METHOD_METADATA(getEnum, 3), | 57 | + ARK_METHOD_METADATA(getEnum, 3), |
| 58 | - ARK_METHOD_METADATA(getUnknown, 1), | 58 | + ARK_METHOD_METADATA(getUnknown, 1), |
| 59 | - ARK_METHOD_METADATA(getRootTag, 1), | 59 | + ARK_METHOD_METADATA(getRootTag, 1), |
| 60 | - ARK_METHOD_METADATA(getNumber, 1), | 60 | + ARK_METHOD_METADATA(getNumber, 1), |
| 61 | - ARK_METHOD_METADATA(getValue, 3), | 61 | + ARK_METHOD_METADATA(getValue, 3), |
| 62 | - ARK_METHOD_METADATA(getValueWithCallback, 1), | 62 | + ARK_METHOD_METADATA(getValueWithCallback, 1), |
| 63 | - ARK_ASYNC_METHOD_METADATA(getValueWithPromise, 1), | 63 | + ARK_ASYNC_METHOD_METADATA(getValueWithPromise, 1), |
| 64 | - ARK_METHOD_METADATA(getUnsafeObject, 1), | 64 | + ARK_METHOD_METADATA(getUnsafeObject, 1), |
| 65 | - ARK_METHOD_METADATA(getConstants, 0), | 65 | + ARK_METHOD_METADATA(getConstants, 0), |
| 66 | - ARK_METHOD_METADATA(getNull, 1), | 66 | + ARK_METHOD_METADATA(getNull, 1), |
| 67 | - ARK_METHOD_METADATA(getArray, 1), | 67 | + ARK_METHOD_METADATA(getArray, 1), |
| 68 | - }; | 68 | + }; |
| 69 | 69 | ||
| 70 | methodMap_["displayRNOHError"] = MethodMetadata{ | 70 | methodMap_["displayRNOHError"] = MethodMetadata{ |
| 71 | 1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_displayRNOHError}; | 71 | 1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_displayRNOHError}; |


【AI-Review】【严重】【基础代码问题】【多线程问题】 ● 问题: 静态成员变量 s_windowId 和 s_bundleCodeDir 缺少线程安全保护。RegisterPageNameMessageHandler::handleArkTSMessage 可能在 ArkTS 线程中写入这些变量,而 RegisterPageName::sendPageName lambda 可能在 JS 线程中读取它们。两个线程并发访问同一静态变量,没有任何同步机制(如 mutex、atomic 或锁),存在数据竞争风险。 ● 影响: 数据竞争会导致读取到不一致的值,可能传递错误的 windowId 或 bundleCodeDir 给系统 API,甚至导致应用崩溃。 ● 建议: 使用以下方案之一: