From caa8a857a3d2e9e402c93f9e82e12847a74c05f8 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 20 Mar 2025 10:37:24 -0700 Subject: [PATCH] Add warning when RCT_EXPORT_MODULE is used in New Arch (#49897) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49897 This change introduces the first warning for the New Architecture warning. When modules are registered through the RCT_EXPORT_MODULE (or its variants) a warning is emitted. Note: currently it is only emitted on the Xcode console. I'm looking into ways to emit it also in the RN DevTools console. ## Changelog: [iOS][Added] - Show warnings in the New Architecture when modules are loaded using RCT_EXPORT_MODULE Differential Revision: D70789672 --- packages/react-native/React/Base/RCTBridge.h | 5 + packages/react-native/React/Base/RCTBridge.mm | 94 +++++++++++++++++++ .../platform/ios/ReactCommon/RCTInstance.mm | 17 ++++ 3 files changed, 116 insertions(+) diff --git a/packages/react-native/React/Base/RCTBridge.h b/packages/react-native/React/Base/RCTBridge.h index 788730bba133..cdfd10f6f6d5 100644 --- a/packages/react-native/React/Base/RCTBridge.h +++ b/packages/react-native/React/Base/RCTBridge.h @@ -38,6 +38,11 @@ RCT_EXTERN_C_BEGIN */ NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); +/** + * This function returns the list of modules that have been registered using the Old Architecture mechanism. + */ +NSMutableArray *getModulesLoadedWithOldArch(void); + /** * Experimental. * Check/set if JSI-bound NativeModule is enabled. By default it's off. diff --git a/packages/react-native/React/Base/RCTBridge.mm b/packages/react-native/React/Base/RCTBridge.mm index 32000177fcb5..d163cd49ccbd 100644 --- a/packages/react-native/React/Base/RCTBridge.mm +++ b/packages/react-native/React/Base/RCTBridge.mm @@ -42,6 +42,97 @@ return result; } +NSSet *getCoreModuleClasses(void); +NSSet *getCoreModuleClasses(void) +{ + static NSSet *coreModuleClasses = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + coreModuleClasses = [NSSet setWithArray:@[ + @"RCTViewManager", + @"RCTActivityIndicatorViewManager", + @"RCTDebuggingOverlayManager", + @"RCTModalHostViewManager", + @"RCTModalManager", + @"RCTRefreshControlManager", + @"RCTSafeAreaViewManager", + @"RCTScrollContentViewManager", + @"RCTScrollViewManager", + @"RCTSwitchManager", + @"RCTUIManager", + @"RCTAccessibilityManager", + @"RCTActionSheetManager", + @"RCTAlertManager", + @"RCTAppearance", + @"RCTAppState", + @"RCTClipboard", + @"RCTDeviceInfo", + @"RCTDevLoadingView", + @"RCTDevMenu", + @"RCTDevSettings", + @"RCTDevToolsRuntimeSettingsModule", + @"RCTEventDispatcher", + @"RCTExceptionsManager", + @"RCTI18nManager", + @"RCTKeyboardObserver", + @"RCTLogBox", + @"RCTPerfMonitor", + @"RCTPlatform", + @"RCTRedBox", + @"RCTSourceCode", + @"RCTStatusBarManager", + @"RCTTiming", + @"RCTWebSocketModule", + @"RCTNativeAnimatedModule", + @"RCTNativeAnimatedTurboModule", + @"RCTBlobManager", + @"RCTFileReaderModule", + @"RCTBundleAssetImageLoader", + @"RCTGIFImageDecoder", + @"RCTImageEditingManager", + @"RCTImageLoader", + @"RCTImageStoreManager", + @"RCTImageViewManager", + @"RCTLocalAssetImageLoader", + @"RCTLinkingManager", + @"RCTDataRequestHandler", + @"RCTFileRequestHandler", + @"RCTHTTPRequestHandler", + @"RCTNetworking", + @"RCTPushNotificationManager", + @"RCTSettingsManager", + @"RCTBaseTextViewManager", + @"RCTBaseTextInputViewManager", + @"RCTInputAccessoryViewManager", + @"RCTMultilineTextInputViewManager", + @"RCTRawTextViewManager", + @"RCTSinglelineTextInputViewManager", + @"RCTTextViewManager", + @"RCTVirtualTextViewManager", + @"RCTVibration", + ]]; + }); + + return coreModuleClasses; +} + +static NSMutableArray *modulesLoadedWithOldArch; +void addModuleLoadedWithOldArch(NSString *); +void addModuleLoadedWithOldArch(NSString *moduleName) +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + modulesLoadedWithOldArch = [NSMutableArray new]; + }); + + [modulesLoadedWithOldArch addObject:moduleName]; +} + +NSMutableArray *getModulesLoadedWithOldArch(void) +{ + return modulesLoadedWithOldArch; +} + /** * Register the given class as a bridge module. All modules must be registered * prior to the first bridge initialization. @@ -50,6 +141,9 @@ void RCTRegisterModule(Class); void RCTRegisterModule(Class moduleClass) { + if (RCTIsNewArchEnabled() && ![getCoreModuleClasses() containsObject:[moduleClass description]]) { + addModuleLoadedWithOldArch([moduleClass description]); + } static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ RCTModuleClasses = [NSMutableArray new]; diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index e06167df9640..4778ec2a2689 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -512,9 +512,26 @@ - (void)_loadJSBundle:(NSURL *)sourceURL // Set up hot module reloading in Dev only. [strongSelf->_performanceLogger markStopForTag:RCTPLScriptDownload]; [devSettings setupHMRClientWithBundleURL:sourceURL]; + + [strongSelf _logOldArchitectureWarnings]; }]; } +- (void)_logOldArchitectureWarnings +{ + NSMutableArray *modulesInOldArchMode = getModulesLoadedWithOldArch(); + if (modulesInOldArchMode.count > 0) { + NSMutableString *moduleList = [NSMutableString new]; + for (NSString *moduleName in modulesInOldArchMode) { + [moduleList appendFormat:@"- %@\n", moduleName]; + } + RCTLogWarn( + @"The following modules have been registered using a RCT_EXPORT_MODULE. That's a Legacy Architecture API. Please migrate to the new approach as described in the https://reactnative.dev/docs/next/turbo-native-modules-introduction#register-the-native-module-in-your-app website or open a PR in the library repository:\n%@", + moduleList); + [modulesInOldArchMode removeAllObjects]; + } +} + - (void)_loadScriptFromSource:(RCTSource *)source { std::lock_guard lock(_invalidationMutex);