From bb1c93d077f950c8b47658f3717523f24a3e2da3 Mon Sep 17 00:00:00 2001 From: Christoph Purrer Date: Mon, 16 Jun 2025 14:23:26 -0700 Subject: [PATCH] Update outdated ReactNativeCPP.api Summary: changelog: [internal] Update outdated ReactNativeCPP.api Differential Revision: D76763455 --- private/cxx-public-api/ReactNativeCPP.api | 16192 ++++++++++++++------ 1 file changed, 11782 insertions(+), 4410 deletions(-) diff --git a/private/cxx-public-api/ReactNativeCPP.api b/private/cxx-public-api/ReactNativeCPP.api index 5f824f6c3c63..7696dbd6da69 100644 --- a/private/cxx-public-api/ReactNativeCPP.api +++ b/private/cxx-public-api/ReactNativeCPP.api @@ -2,7 +2,7 @@ * This file is generated, do not edit. * @generated * - * @file_count 1059 + * @file_count 1199 * @generate-command: node tools/api/public-api.js */ @@ -10,15 +10,79 @@ /// @src {packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h}: /// @dep {packages/react-native/Libraries/AppDelegate/RCTArchConfiguratorProtocol.h} /// @dep {packages/react-native/Libraries/AppDelegate/RCTDependencyProvider.h} -/// @dep {packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h} +/// @dep {packages/react-native/Libraries/AppDelegate/RCTJSRuntimeConfiguratorProtocol.h} +NS_ASSUME_NONNULL_BEGIN +typedef UIView *_Nonnull ( + ^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps); +typedef RCTBridge *_Nonnull ( + ^RCTCreateBridgeWithDelegateBlock)(id delegate, NSDictionary *launchOptions); +typedef void (^RCTCustomizeRootViewBlock)(UIView *rootView); +typedef NSURL *_Nullable (^RCTSourceURLForBridgeBlock)(RCTBridge *bridge); +typedef NSURL *_Nullable (^RCTBundleURLBlock)(void); +typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); +typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); +typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); +typedef void (^RCTLoadSourceForBridgeWithProgressBlock)( + RCTBridge *bridge, + RCTSourceLoadProgressBlock onProgress, + RCTSourceLoadBlock loadCallback); +typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBlock loadCallback); +@interface RCTRootViewFactoryConfiguration : NSObject +@property (nonatomic, assign, readonly) BOOL fabricEnabled; +@property (nonatomic, assign, readonly) BOOL bridgelessEnabled; +@property (nonatomic, assign, readonly) BOOL turboModuleEnabled; +@property (nonatomic, nonnull) RCTBundleURLBlock bundleURLBlock; +- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled NS_DESIGNATED_INITIALIZER __deprecated; +- (instancetype)initWithBundleURL:(NSURL *)bundleURL + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled __deprecated; +- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock newArchEnabled:(BOOL)newArchEnabled; +- (instancetype)initWithBundleURL:(NSURL *)bundleURL newArchEnabled:(BOOL)newArchEnabled; +@property (nonatomic, nullable) RCTCreateRootViewWithBridgeBlock createRootViewWithBridge; +@property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate; +@property (nonatomic, nullable) RCTCustomizeRootViewBlock customizeRootView; +@property (nonatomic, weak, nullable) id jsRuntimeConfiguratorDelegate; +@property (nonatomic, nullable) RCTSourceURLForBridgeBlock sourceURLForBridge; +@property (nonatomic, nullable) RCTExtraModulesForBridgeBlock extraModulesForBridge; +@property (nonatomic, nullable) RCTExtraLazyModuleClassesForBridge extraLazyModuleClassesForBridge; +@property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; +@property (nonatomic, nullable) RCTLoadSourceForBridgeWithProgressBlock loadSourceForBridgeWithProgress; +@property (nonatomic, nullable) RCTLoadSourceForBridgeBlock loadSourceForBridge; +@end +@interface RCTRootViewFactory : NSObject +@property (nonatomic, strong, nullable) RCTBridge *bridge; +@property (nonatomic, strong, nullable) RCTHost *reactHost; +@property (nonatomic, strong, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration + andTurboModuleManagerDelegate:(id _Nullable)turboModuleManagerDelegate; +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration; +- (instancetype)initWithTurboModuleDelegate:(id)turboModuleManagerDelegate + hostDelegate:(id)hostdelegate + configuration:(RCTRootViewFactoryConfiguration *)configuration; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties + launchOptions:(NSDictionary *__nullable)launchOptions; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName; +- (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions; +- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions; +@end +NS_ASSUME_NONNULL_END /// @dep {packages/react-native/Libraries/AppDelegate/RCTUIConfiguratorProtocol.h} NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable }; @protocol RCTReactNativeFactoryDelegate < RCTBridgeDelegate, RCTUIConfiguratorProtocol, RCTHostDelegate, RCTTurboModuleManagerDelegate, RCTComponentViewFactoryComponentProvider, + RCTJSRuntimeConfiguratorProtocol, RCTArchConfiguratorProtocol> - (NSURL *__nullable)bundleURL; @property (nonatomic, strong) id dependencyProvider; @@ -31,9 +95,16 @@ NS_ASSUME_NONNULL_BEGIN @end @interface RCTReactNativeFactory : NSObject - (instancetype)initWithDelegate:(id)delegate; +- (instancetype)initWithDelegate:(id)delegate releaseLevel:(RCTReleaseLevel)releaseLevel; +- (void)startReactNativeWithModuleName:(NSString *)moduleName inWindow:(UIWindow *_Nullable)window; +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + launchOptions:(NSDictionary *_Nullable)launchOptions; +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + initialProperties:(NSDictionary *_Nullable)initialProperties + launchOptions:(NSDictionary *_Nullable)launchOptions; @property (nonatomic, nullable) RCTBridge *bridge; -@property (nonatomic, strong, nullable) NSString *moduleName; -@property (nonatomic, strong, nullable) NSDictionary *initialProps; @property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory; @property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; @property (nonatomic, weak) id delegate; @@ -45,7 +116,9 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_BEGIN -@interface RCTAppDelegate : RCTDefaultReactNativeFactoryDelegate +__attribute__((deprecated( + "RCTAppDelegate is deprecated and will be removed in a future version of React Native. Use `RCTReactNativeFactory` instead."))) +@interface RCTAppDelegate : RCTDefaultReactNativeFactoryDelegate @property (nonatomic, strong, nonnull) UIWindow *window; @property (nonatomic, nullable) RCTBridge *bridge; @property (nonatomic, strong, nullable) NSString *moduleName; @@ -61,6 +134,8 @@ NS_ASSUME_NONNULL_END namespace facebook::react { } +RCT_EXTERN NSArray *RCTAppSetupUnstableModulesRequiringMainQueueSetup( + id dependencyProvider); RCT_EXTERN id RCTAppSetupDefaultModuleFromClass( Class moduleClass, id dependencyProvider); @@ -81,25 +156,91 @@ UIView *RCTAppSetupDefaultRootView( RCT_EXTERN_C_END /// @src {packages/react-native/Libraries/AppDelegate/RCTArchConfiguratorProtocol.h}: +NS_ASSUME_NONNULL_BEGIN @protocol RCTArchConfiguratorProtocol -- (BOOL)turboModuleEnabled __attribute__((deprecated("Use newArchEnabled instead"))); -- (BOOL)fabricEnabled __attribute__((deprecated("Use newArchEnabled instead"))); -- (BOOL)bridgelessEnabled __attribute__((deprecated("Use newArchEnabled instead"))); -- (BOOL)newArchEnabled; +- (BOOL)turboModuleEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead"))); +- (BOOL)fabricEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead"))); +- (BOOL)bridgelessEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead"))); +- (BOOL)newArchEnabled __attribute__((deprecated("Use RCTIsNewArchEnabled instead"))); @end +NS_ASSUME_NONNULL_END /// @src {packages/react-native/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.h}: /// @dep {packages/react-native/Libraries/AppDelegate/RCTArchConfiguratorProtocol.h} /// @dep {packages/react-native/Libraries/AppDelegate/RCTDependencyProvider.h} -/// @dep {packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h} +/// @dep {packages/react-native/Libraries/AppDelegate/RCTJSRuntimeConfiguratorProtocol.h} +NS_ASSUME_NONNULL_BEGIN +typedef UIView *_Nonnull ( + ^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps); +typedef RCTBridge *_Nonnull ( + ^RCTCreateBridgeWithDelegateBlock)(id delegate, NSDictionary *launchOptions); +typedef void (^RCTCustomizeRootViewBlock)(UIView *rootView); +typedef NSURL *_Nullable (^RCTSourceURLForBridgeBlock)(RCTBridge *bridge); +typedef NSURL *_Nullable (^RCTBundleURLBlock)(void); +typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); +typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); +typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); +typedef void (^RCTLoadSourceForBridgeWithProgressBlock)( + RCTBridge *bridge, + RCTSourceLoadProgressBlock onProgress, + RCTSourceLoadBlock loadCallback); +typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBlock loadCallback); +@interface RCTRootViewFactoryConfiguration : NSObject +@property (nonatomic, assign, readonly) BOOL fabricEnabled; +@property (nonatomic, assign, readonly) BOOL bridgelessEnabled; +@property (nonatomic, assign, readonly) BOOL turboModuleEnabled; +@property (nonatomic, nonnull) RCTBundleURLBlock bundleURLBlock; +- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled NS_DESIGNATED_INITIALIZER __deprecated; +- (instancetype)initWithBundleURL:(NSURL *)bundleURL + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled __deprecated; +- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock newArchEnabled:(BOOL)newArchEnabled; +- (instancetype)initWithBundleURL:(NSURL *)bundleURL newArchEnabled:(BOOL)newArchEnabled; +@property (nonatomic, nullable) RCTCreateRootViewWithBridgeBlock createRootViewWithBridge; +@property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate; +@property (nonatomic, nullable) RCTCustomizeRootViewBlock customizeRootView; +@property (nonatomic, weak, nullable) id jsRuntimeConfiguratorDelegate; +@property (nonatomic, nullable) RCTSourceURLForBridgeBlock sourceURLForBridge; +@property (nonatomic, nullable) RCTExtraModulesForBridgeBlock extraModulesForBridge; +@property (nonatomic, nullable) RCTExtraLazyModuleClassesForBridge extraLazyModuleClassesForBridge; +@property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; +@property (nonatomic, nullable) RCTLoadSourceForBridgeWithProgressBlock loadSourceForBridgeWithProgress; +@property (nonatomic, nullable) RCTLoadSourceForBridgeBlock loadSourceForBridge; +@end +@interface RCTRootViewFactory : NSObject +@property (nonatomic, strong, nullable) RCTBridge *bridge; +@property (nonatomic, strong, nullable) RCTHost *reactHost; +@property (nonatomic, strong, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration + andTurboModuleManagerDelegate:(id _Nullable)turboModuleManagerDelegate; +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration; +- (instancetype)initWithTurboModuleDelegate:(id)turboModuleManagerDelegate + hostDelegate:(id)hostdelegate + configuration:(RCTRootViewFactoryConfiguration *)configuration; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties + launchOptions:(NSDictionary *__nullable)launchOptions; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName; +- (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions; +- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions; +@end +NS_ASSUME_NONNULL_END /// @dep {packages/react-native/Libraries/AppDelegate/RCTUIConfiguratorProtocol.h} NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable }; @protocol RCTReactNativeFactoryDelegate < RCTBridgeDelegate, RCTUIConfiguratorProtocol, RCTHostDelegate, RCTTurboModuleManagerDelegate, RCTComponentViewFactoryComponentProvider, + RCTJSRuntimeConfiguratorProtocol, RCTArchConfiguratorProtocol> - (NSURL *__nullable)bundleURL; @property (nonatomic, strong) id dependencyProvider; @@ -112,9 +253,16 @@ NS_ASSUME_NONNULL_BEGIN @end @interface RCTReactNativeFactory : NSObject - (instancetype)initWithDelegate:(id)delegate; +- (instancetype)initWithDelegate:(id)delegate releaseLevel:(RCTReleaseLevel)releaseLevel; +- (void)startReactNativeWithModuleName:(NSString *)moduleName inWindow:(UIWindow *_Nullable)window; +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + launchOptions:(NSDictionary *_Nullable)launchOptions; +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + initialProperties:(NSDictionary *_Nullable)initialProperties + launchOptions:(NSDictionary *_Nullable)launchOptions; @property (nonatomic, nullable) RCTBridge *bridge; -@property (nonatomic, strong, nullable) NSString *moduleName; -@property (nonatomic, strong, nullable) NSDictionary *initialProps; @property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory; @property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; @property (nonatomic, weak) id delegate; @@ -133,22 +281,96 @@ NS_ASSUME_NONNULL_BEGIN - (NSArray *)imageURLLoaderClassNames; - (NSArray *)imageDataDecoderClassNames; - (NSArray *)URLRequestHandlerClassNames; +- (NSArray *)unstableModulesRequiringMainQueueSetup; - (NSDictionary> *)thirdPartyFabricComponents; +- (nonnull NSDictionary> *)moduleProviders; +@end +NS_ASSUME_NONNULL_END + +/// @src {packages/react-native/Libraries/AppDelegate/RCTJSRuntimeConfiguratorProtocol.h}: +NS_ASSUME_NONNULL_BEGIN +typedef void *JSRuntimeFactoryRef; +@protocol RCTJSRuntimeConfiguratorProtocol +- (JSRuntimeFactoryRef)createJSRuntimeFactory; @end NS_ASSUME_NONNULL_END /// @src {packages/react-native/Libraries/AppDelegate/RCTReactNativeFactory.h}: /// @dep {packages/react-native/Libraries/AppDelegate/RCTArchConfiguratorProtocol.h} /// @dep {packages/react-native/Libraries/AppDelegate/RCTDependencyProvider.h} -/// @dep {packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h} +/// @dep {packages/react-native/Libraries/AppDelegate/RCTJSRuntimeConfiguratorProtocol.h} +NS_ASSUME_NONNULL_BEGIN +typedef UIView *_Nonnull ( + ^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps); +typedef RCTBridge *_Nonnull ( + ^RCTCreateBridgeWithDelegateBlock)(id delegate, NSDictionary *launchOptions); +typedef void (^RCTCustomizeRootViewBlock)(UIView *rootView); +typedef NSURL *_Nullable (^RCTSourceURLForBridgeBlock)(RCTBridge *bridge); +typedef NSURL *_Nullable (^RCTBundleURLBlock)(void); +typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); +typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); +typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); +typedef void (^RCTLoadSourceForBridgeWithProgressBlock)( + RCTBridge *bridge, + RCTSourceLoadProgressBlock onProgress, + RCTSourceLoadBlock loadCallback); +typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBlock loadCallback); +@interface RCTRootViewFactoryConfiguration : NSObject +@property (nonatomic, assign, readonly) BOOL fabricEnabled; +@property (nonatomic, assign, readonly) BOOL bridgelessEnabled; +@property (nonatomic, assign, readonly) BOOL turboModuleEnabled; +@property (nonatomic, nonnull) RCTBundleURLBlock bundleURLBlock; +- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled NS_DESIGNATED_INITIALIZER __deprecated; +- (instancetype)initWithBundleURL:(NSURL *)bundleURL + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled __deprecated; +- (instancetype)initWithBundleURLBlock:(RCTBundleURLBlock)bundleURLBlock newArchEnabled:(BOOL)newArchEnabled; +- (instancetype)initWithBundleURL:(NSURL *)bundleURL newArchEnabled:(BOOL)newArchEnabled; +@property (nonatomic, nullable) RCTCreateRootViewWithBridgeBlock createRootViewWithBridge; +@property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate; +@property (nonatomic, nullable) RCTCustomizeRootViewBlock customizeRootView; +@property (nonatomic, weak, nullable) id jsRuntimeConfiguratorDelegate; +@property (nonatomic, nullable) RCTSourceURLForBridgeBlock sourceURLForBridge; +@property (nonatomic, nullable) RCTExtraModulesForBridgeBlock extraModulesForBridge; +@property (nonatomic, nullable) RCTExtraLazyModuleClassesForBridge extraLazyModuleClassesForBridge; +@property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; +@property (nonatomic, nullable) RCTLoadSourceForBridgeWithProgressBlock loadSourceForBridgeWithProgress; +@property (nonatomic, nullable) RCTLoadSourceForBridgeBlock loadSourceForBridge; +@end +@interface RCTRootViewFactory : NSObject +@property (nonatomic, strong, nullable) RCTBridge *bridge; +@property (nonatomic, strong, nullable) RCTHost *reactHost; +@property (nonatomic, strong, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration + andTurboModuleManagerDelegate:(id _Nullable)turboModuleManagerDelegate; +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration; +- (instancetype)initWithTurboModuleDelegate:(id)turboModuleManagerDelegate + hostDelegate:(id)hostdelegate + configuration:(RCTRootViewFactoryConfiguration *)configuration; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties + launchOptions:(NSDictionary *__nullable)launchOptions; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties; +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName; +- (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions; +- (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions; +@end +NS_ASSUME_NONNULL_END /// @dep {packages/react-native/Libraries/AppDelegate/RCTUIConfiguratorProtocol.h} NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, RCTReleaseLevel) { Canary, Experimental, Stable }; @protocol RCTReactNativeFactoryDelegate < RCTBridgeDelegate, RCTUIConfiguratorProtocol, RCTHostDelegate, RCTTurboModuleManagerDelegate, RCTComponentViewFactoryComponentProvider, + RCTJSRuntimeConfiguratorProtocol, RCTArchConfiguratorProtocol> - (NSURL *__nullable)bundleURL; @property (nonatomic, strong) id dependencyProvider; @@ -161,9 +383,16 @@ NS_ASSUME_NONNULL_BEGIN @end @interface RCTReactNativeFactory : NSObject - (instancetype)initWithDelegate:(id)delegate; +- (instancetype)initWithDelegate:(id)delegate releaseLevel:(RCTReleaseLevel)releaseLevel; +- (void)startReactNativeWithModuleName:(NSString *)moduleName inWindow:(UIWindow *_Nullable)window; +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + launchOptions:(NSDictionary *_Nullable)launchOptions; +- (void)startReactNativeWithModuleName:(NSString *)moduleName + inWindow:(UIWindow *_Nullable)window + initialProperties:(NSDictionary *_Nullable)initialProperties + launchOptions:(NSDictionary *_Nullable)launchOptions; @property (nonatomic, nullable) RCTBridge *bridge; -@property (nonatomic, strong, nullable) NSString *moduleName; -@property (nonatomic, strong, nullable) NSDictionary *initialProps; @property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory; @property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; @property (nonatomic, weak) id delegate; @@ -171,7 +400,7 @@ NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END /// @src {packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h}: - +/// @dep {packages/react-native/Libraries/AppDelegate/RCTJSRuntimeConfiguratorProtocol.h} NS_ASSUME_NONNULL_BEGIN typedef UIView *_Nonnull ( ^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps); @@ -183,6 +412,11 @@ typedef NSURL *_Nullable (^RCTBundleURLBlock)(void); typedef NSArray> *_Nonnull (^RCTExtraModulesForBridgeBlock)(RCTBridge *bridge); typedef NSDictionary *_Nonnull (^RCTExtraLazyModuleClassesForBridge)(RCTBridge *bridge); typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *moduleName); +typedef void (^RCTLoadSourceForBridgeWithProgressBlock)( + RCTBridge *bridge, + RCTSourceLoadProgressBlock onProgress, + RCTSourceLoadBlock loadCallback); +typedef void (^RCTLoadSourceForBridgeBlock)(RCTBridge *bridge, RCTSourceLoadBlock loadCallback); @interface RCTRootViewFactoryConfiguration : NSObject @property (nonatomic, assign, readonly) BOOL fabricEnabled; @property (nonatomic, assign, readonly) BOOL bridgelessEnabled; @@ -201,10 +435,13 @@ typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *modu @property (nonatomic, nullable) RCTCreateRootViewWithBridgeBlock createRootViewWithBridge; @property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate; @property (nonatomic, nullable) RCTCustomizeRootViewBlock customizeRootView; +@property (nonatomic, weak, nullable) id jsRuntimeConfiguratorDelegate; @property (nonatomic, nullable) RCTSourceURLForBridgeBlock sourceURLForBridge; @property (nonatomic, nullable) RCTExtraModulesForBridgeBlock extraModulesForBridge; @property (nonatomic, nullable) RCTExtraLazyModuleClassesForBridge extraLazyModuleClassesForBridge; @property (nonatomic, nullable) RCTBridgeDidNotFindModuleBlock bridgeDidNotFindModule; +@property (nonatomic, nullable) RCTLoadSourceForBridgeWithProgressBlock loadSourceForBridgeWithProgress; +@property (nonatomic, nullable) RCTLoadSourceForBridgeBlock loadSourceForBridge; @end @interface RCTRootViewFactory : NSObject @property (nonatomic, strong, nullable) RCTBridge *bridge; @@ -222,18 +459,21 @@ typedef BOOL (^RCTBridgeDidNotFindModuleBlock)(RCTBridge *bridge, NSString *modu - (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *__nullable)initialProperties; - (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName; +- (void)initializeReactHostWithLaunchOptions:(NSDictionary *__nullable)launchOptions; - (RCTHost *)createReactHost:(NSDictionary *__nullable)launchOptions; @end NS_ASSUME_NONNULL_END /// @src {packages/react-native/Libraries/AppDelegate/RCTUIConfiguratorProtocol.h}: +NS_ASSUME_NONNULL_BEGIN @protocol RCTUIConfiguratorProtocol - (RCTColorSpace)defaultColorSpace; - (void)customizeRootView:(RCTRootView *)rootView; - (UIViewController *)createRootViewController; - (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController; @end +NS_ASSUME_NONNULL_END /// @src {packages/react-native/Libraries/Blob/RCTBlobCollector.h}: @@ -247,7 +487,6 @@ class JSI_EXPORT RCTBlobCollector : public jsi::HostObject { } // namespace facebook::react /// @src {packages/react-native/Libraries/Blob/RCTBlobManager.h}: -RCT_EXTERN void RCTEnableBlobManagerProcessingQueue(BOOL enabled); @interface RCTBlobManager : NSObject - (NSString *)store:(NSData *)data; - (void)store:(NSData *)data withId:(NSString *)blobId; @@ -257,7 +496,6 @@ RCT_EXTERN void RCTEnableBlobManagerProcessingQueue(BOOL enabled); - (NSData *)resolveURL:(NSURL *)url; - (void)remove:(NSString *)blobId; - (void)createFromParts:(NSArray *> *)parts withId:(NSString *)blobId; -- (dispatch_queue_t)executionQueue; @end /// @src {packages/react-native/Libraries/Blob/RCTBlobPlugins.h}: @@ -617,8 +855,17 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock; resizeMode:(RCTResizeMode)resizeMode progressHandler:(RCTImageLoaderProgressBlock)progressHandler partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler - completionHandler:(RCTImageLoaderCompletionBlock)completionHandler; + completionHandler:(RCTImageLoaderCompletionBlock)completionHandler + RCT_DEPRECATED; @optional +- (nullable RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL + size:(CGSize)size + scale:(CGFloat)scale + resizeMode:(RCTResizeMode)resizeMode + progressHandler:(RCTImageLoaderProgressBlock)progressHandler + partialLoadHandler:(RCTImageLoaderPartialLoadBlock)partialLoadHandler + completionHandlerWithMetadata: + (RCTImageLoaderCompletionBlockWithMetadata)completionHandlerWithMetadata; - (float)loaderPriority; - (BOOL)requiresScheduling; - (BOOL)shouldCacheLoadedImages; @@ -1133,6 +1380,18 @@ RCT_EXTERN void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfig @interface RCTHTTPRequestHandler : NSObject @end +/// @src {packages/react-native/Libraries/Network/RCTInspectorNetworkReporter.h}: +@interface RCTInspectorNetworkReporter : NSObject ++ (void)reportRequestStart:(NSNumber *)requestId + request:(NSURLRequest *)request + encodedDataLength:(int)encodedDataLength; ++ (void)reportResponseStart:(NSNumber *)requestId + response:(NSURLResponse *)response + statusCode:(int)statusCode + headers:(NSDictionary *)headers; ++ (void)reportResponseEnd:(NSNumber *)requestId encodedDataLength:(int)encodedDataLength; +@end + /// @src {packages/react-native/Libraries/Network/RCTNetworkPlugins.h}: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" @@ -1175,7 +1434,6 @@ typedef NS_ENUM(NSInteger, RCTNetworkTaskStatus) { @end /// @src {packages/react-native/Libraries/Network/RCTNetworking.h}: -RCT_EXTERN void RCTEnableNetworkingRequestQueue(BOOL enabled); @protocol RCTNetworkingRequestHandler - (BOOL)canHandleNetworkingRequest:(NSDictionary *)data; - (NSDictionary *)handleNetworkingRequest:(NSDictionary *)data; @@ -1194,7 +1452,6 @@ RCT_EXTERN void RCTEnableNetworkingRequestQueue(BOOL enabled); - (void)addResponseHandler:(id)handler; - (void)removeRequestHandler:(id)handler; - (void)removeResponseHandler:(id)handler; -- (dispatch_queue_t)requestQueue; @end @interface RCTBridge (RCTNetworking) @property (nonatomic, readonly) RCTNetworking *networking; @@ -1456,6 +1713,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL caretHidden; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewID; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewButtonLabel; +@property (nonatomic, assign) BOOL disableKeyboardShortcuts; @end NS_ASSUME_NONNULL_END @@ -1514,6 +1772,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) BOOL caretHidden; @property (nonatomic, assign) BOOL enablesReturnKeyAutomatically; @property (nonatomic, assign) UITextFieldViewMode clearButtonMode; +@property (nonatomic, assign) UIDataDetectorTypes dataDetectorTypes; @property (nonatomic, getter=isScrollEnabled) BOOL scrollEnabled; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewID; @property (nonatomic, strong, nullable) NSString *inputAccessoryViewButtonLabel; @@ -1521,10 +1780,12 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign, readonly) CGPoint contentOffset; @property (nonatomic, assign, readonly) UIEdgeInsets contentInset; @property (nullable, nonatomic, copy) NSDictionary *typingAttributes; +@property (nonatomic, strong, nullable) NSArray *acceptDragAndDropTypes; - (void)setSelectedTextRange:(nullable UITextRange *)selectedTextRange NS_UNAVAILABLE; - (void)setSelectedTextRange:(nullable UITextRange *)selectedTextRange notifyDelegate:(BOOL)notifyDelegate; - (void)scrollRangeToVisible:(NSRange)selectedTextRange; @property (nonatomic, copy, nullable) NSString *text NS_UNAVAILABLE; +@property (nonatomic, assign) BOOL disableKeyboardShortcuts; @end NS_ASSUME_NONNULL_END @@ -1638,6 +1899,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign, readonly) CGFloat zoomScale; @property (nonatomic, assign, readonly) CGPoint contentOffset; @property (nonatomic, assign, readonly) UIEdgeInsets contentInset; +@property (nonatomic, assign) BOOL disableKeyboardShortcuts; @end NS_ASSUME_NONNULL_END @@ -1896,6 +2158,7 @@ RCT_EXTERN void RCTRegisterModule(Class); typedef NSArray> * (^RCTBridgeModuleListProvider)(void); RCT_EXTERN_C_BEGIN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass); +NSMutableArray *getModulesLoadedWithOldArch(void); BOOL RCTTurboModuleEnabled(void); void RCTEnableTurboModule(BOOL enabled); BOOL RCTTurboModuleInteropEnabled(void); @@ -1917,8 +2180,6 @@ RCTBridgeProxyLoggingLevel RCTTurboModuleInteropBridgeProxyLogLevel(void); void RCTSetTurboModuleInteropBridgeProxyLogLevel(RCTBridgeProxyLoggingLevel logLevel); BOOL RCTTurboModuleInteropForAllTurboModulesEnabled(void); void RCTEnableTurboModuleInteropForAllTurboModules(BOOL enabled); -BOOL RCTBridgeModuleBatchDidCompleteDisabled(void); -void RCTDisableBridgeModuleBatchDidComplete(BOOL disabled); typedef enum { kRCTGlobalScope, kRCTGlobalScopeUsingRetainJSCallback, @@ -1979,7 +2240,6 @@ NS_ASSUME_NONNULL_BEGIN - (NSURL *__nullable)sourceURLForBridge:(RCTBridge *)bridge; @optional - (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge; -- (BOOL)shouldBridgeUseCustomJSC:(RCTBridge *)bridge; - (BOOL)bridge:(RCTBridge *)bridge didNotFindModule:(NSString *)moduleName; - (void)loadSourceForBridge:(RCTBridge *)bridge onProgress:(RCTSourceLoadProgressBlock)onProgress @@ -2227,6 +2487,9 @@ NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/Base/RCTCallInvokerModule.h}: +@protocol RCTCallInvokerModule +@property (nonatomic, nullable, readwrite) RCTCallInvoker *callInvoker; +@end /// @src {packages/react-native/React/Base/RCTComponentEvent.h}: NS_ASSUME_NONNULL_BEGIN @@ -2369,10 +2632,16 @@ RCT_EXTERN NSArray *RCTConvertArrayValue(SEL, id); /// @src {packages/react-native/React/Base/RCTDisplayLink.h}: +@protocol RCTDisplayLinkModuleHolder +- (id)instance; +- (Class)moduleClass; +- (dispatch_queue_t)methodQueue; +@end @interface RCTDisplayLink : NSObject - (instancetype)init; - (void)invalidate; -- (void)registerModuleForFrameUpdates:(id)module withModuleData:(RCTModuleData *)moduleData; +- (void)registerModuleForFrameUpdates:(id)module + withModuleHolder:(id)moduleHolder; - (void)addToRunLoop:(NSRunLoop *)runLoop; @end @@ -2901,7 +3170,10 @@ NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/Base/RCTUtils.h}: NS_ASSUME_NONNULL_BEGIN RCT_EXTERN BOOL RCTIsNewArchEnabled(void); -RCT_EXTERN void RCTSetNewArchEnabled(BOOL enabled); +RCT_EXTERN void RCTSetNewArchEnabled(BOOL enabled) __attribute__((deprecated( + "This function is now no-op. You need to modify the Info.plist adding a RCTNewArchEnabled bool property to control whether the New Arch is enabled or not"))); +; +RCT_EXTERN BOOL RCTAreLegacyLogsEnabled(void); RCT_EXTERN NSString *__nullable RCTJSONStringify(id __nullable jsonObject, NSError **error); RCT_EXTERN id __nullable RCTJSONParse(NSString *__nullable jsonString, NSError **error); RCT_EXTERN id __nullable RCTJSONParseMutable(NSString *__nullable jsonString, NSError **error); @@ -2910,14 +3182,13 @@ RCT_EXTERN NSString *RCTMD5Hash(NSString *string); RCT_EXTERN BOOL RCTIsMainQueue(void); RCT_EXTERN void RCTExecuteOnMainQueue(dispatch_block_t block); RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block); -RCT_EXTERN void RCTComputeScreenScale(void); +RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSyncWithError(dispatch_block_t block, NSString *context); RCT_EXTERN CGFloat RCTScreenScale(void); RCT_EXTERN CGFloat RCTFontSizeMultiplier(void); RCT_EXTERN CGSize RCTScreenSize(void); RCT_EXTERN CGSize RCTViewportSize(void); RCT_EXTERN CGFloat RCTRoundPixelValue(CGFloat value); RCT_EXTERN CGFloat RCTCeilPixelValue(CGFloat value); -RCT_EXTERN CGFloat RCTFloorPixelValue(CGFloat value); RCT_EXTERN CGSize RCTSizeInPixels(CGSize pointSize, CGFloat scale); RCT_EXTERN void RCTSwapClassMethods(Class cls, SEL original, SEL replacement); RCT_EXTERN void RCTSwapInstanceMethods(Class cls, SEL original, SEL replacement); @@ -3089,8 +3360,8 @@ NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/Base/Surface/RCTSurfaceView.h}: NS_ASSUME_NONNULL_BEGIN @interface RCTSurfaceView : UIView -- (instancetype)initWithSurface:(RCTSurface *)surface NS_DESIGNATED_INITIALIZER; -@property (nonatomic, weak, readonly, nullable) RCTSurface *surface; +- (instancetype)initWithSurface:(id)surface NS_DESIGNATED_INITIALIZER; +@property (nonatomic, weak, readonly, nullable) id surface; @end NS_ASSUME_NONNULL_END @@ -3178,7 +3449,6 @@ Class RCTRedBoxCls(void) __attribute__((used)); Class RCTSourceCodeCls(void) __attribute__((used)); Class RCTStatusBarManagerCls(void) __attribute__((used)); Class RCTTimingCls(void) __attribute__((used)); -Class RCTWebSocketExecutorCls(void) __attribute__((used)); Class RCTWebSocketModuleCls(void) __attribute__((used)); Class RCTBlobManagerCls(void) __attribute__((used)); } @@ -3296,9 +3566,7 @@ typedef NSString * (^RCTDevMenuItemTitleBlock)(void); @interface RCTDevSettings : RCTEventEmitter - (instancetype)initWithDataSource:(id)dataSource; @property (nonatomic, readonly) BOOL isHotLoadingAvailable; -@property (nonatomic, readonly) BOOL isRemoteDebuggingAvailable; @property (nonatomic, readonly) BOOL isDeviceDebuggingAvailable; -@property (nonatomic, assign) BOOL isDebuggingRemotely; @property (nonatomic, assign) BOOL isShakeToShowDevMenuEnabled; @property (nonatomic, assign, setter=setProfilingEnabled:) BOOL isProfilingEnabled; @property (nonatomic, assign, setter=setHotLoadingEnabled:) BOOL isHotLoadingEnabled; @@ -3447,9 +3715,6 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END -/// @src {packages/react-native/React/CoreModules/RCTWebSocketExecutor.h}: - - /// @src {packages/react-native/React/CoreModules/RCTWebSocketModule.h}: NS_ASSUME_NONNULL_BEGIN @protocol RCTWebSocketContentHandler @@ -3610,10 +3875,7 @@ class RCTNativeModule : public NativeModule { } // namespace facebook::react /// @src {packages/react-native/React/CxxUtils/RCTFollyConvert.h}: -namespace facebook::react { -folly::dynamic convertIdToFollyDynamic(id json); -id convertFollyDynamicToId(const folly::dynamic& dyn); -} // namespace facebook::react + /// @src {packages/react-native/React/DevSupport/RCTDevLoadingViewProtocol.h}: @@ -3724,7 +3986,7 @@ NS_ASSUME_NONNULL_BEGIN @interface RCTLegacyViewManagerInteropCoordinatorAdapter : NSObject - (instancetype)initWithCoordinator:(RCTLegacyViewManagerInteropCoordinator *)coordinator reactTag:(NSInteger)tag; @property (strong, nonatomic) UIView *paperView; -@property (nonatomic, copy, nullable) void (^eventInterceptor)(std::string eventName, folly::dynamic event); +@property (nonatomic, copy, nullable) void (^eventInterceptor)(std::string eventName, folly::dynamic &&event); - (void)setProps:(const folly::dynamic &)props; - (void)handleCommand:(NSString *)commandName args:(NSArray *)args; @end @@ -3844,7 +4106,7 @@ NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTAccessibilityElement.h}: NS_ASSUME_NONNULL_BEGIN @interface RCTAccessibilityElement : UIAccessibilityElement -@property (nonatomic, assign) CGRect frame; +@property (nonatomic, assign) CGRect frameInContainerSpace; @end NS_ASSUME_NONNULL_END @@ -3928,6 +4190,7 @@ UIReturnKeyType RCTUIReturnKeyTypeFromReturnKeyType(facebook::react::ReturnKeyTy UITextContentType RCTUITextContentTypeFromString(const std::string &contentType); UITextInputPasswordRules *RCTUITextInputPasswordRulesFromString(const std::string &passwordRules); UITextSmartInsertDeleteType RCTUITextSmartInsertDeleteTypeFromOptionalBool(std::optional smartInsertDelete); +UIDataDetectorTypes RCTUITextViewDataDetectorTypesFromStringVector(const std::vector &dataDetectorTypes); NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/Fabric/Mounting/ComponentViews/UnimplementedComponent/RCTUnimplementedNativeComponentView.h}: @@ -3942,6 +4205,15 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END +/// @src {packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewAccessibilityElement.h}: +/// @dep {packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h} +NS_ASSUME_NONNULL_BEGIN +@interface RCTViewAccessibilityElement : UIAccessibilityElement +@property (readonly) RCTViewComponentView *view; +- (instancetype)initWithView:(RCTViewComponentView *)view; +@end +NS_ASSUME_NONNULL_END + /// @src {packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h}: NS_ASSUME_NONNULL_BEGIN @interface RCTViewComponentView : UIView { @@ -3961,6 +4233,9 @@ NS_ASSUME_NONNULL_BEGIN oldLayoutMetrics:(const facebook::react::LayoutMetrics &)oldLayoutMetrics NS_REQUIRES_SUPER; - (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask NS_REQUIRES_SUPER; - (void)prepareForRecycle NS_REQUIRES_SUPER; +- (UIView *)betterHitTest:(CGPoint)point withEvent:(UIEvent *)event; +- (NSString *)accessibilityLabelForCoopting; +- (BOOL)wantsToCooptLabel; - (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN; @end NS_ASSUME_NONNULL_END @@ -4012,7 +4287,6 @@ void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime); @property (nonatomic, weak) id thirdPartyFabricComponentsProvider; + (RCTComponentViewFactory *)currentComponentViewFactory; - (void)registerComponentViewClass:(Class)componentViewClass; -- (BOOL)registerComponentIfPossible:(const std::string &)componentName; - (RCTComponentViewDescriptor)createComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle; - (facebook::react::ComponentDescriptorRegistry::Shared)createComponentDescriptorRegistryWithParameters: (facebook::react::ComponentDescriptorParameters)parameters; @@ -4083,7 +4357,7 @@ NS_ASSUME_NONNULL_BEGIN blockNativeResponder:(BOOL)blockNativeResponder forShadowView:(const facebook::react::ShadowView &)shadowView; - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag - changedProps:(NSDictionary *)props + changedProps:(folly::dynamic)props componentDescriptor:(const facebook::react::ComponentDescriptor &)componentDescriptor; @end NS_ASSUME_NONNULL_END @@ -4354,6 +4628,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)schedulerDidSetIsJSResponder:(BOOL)isJSResponder blockNativeResponder:(BOOL)blockNativeResponder forShadowView:(const facebook::react::ShadowView &)shadowView; +- (void)schedulerDidSynchronouslyUpdateViewOnUIThread:(facebook::react::Tag)reactTag props:(folly::dynamic)props; @end @interface RCTScheduler : NSObject @property (atomic, weak, nullable) id delegate; @@ -4401,7 +4676,8 @@ NS_ASSUME_NONNULL_BEGIN - (id)createFabricSurfaceForModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties; - (nullable RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag; -- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props; +- (void)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props; +- (void)schedulerDidSynchronouslyUpdateViewOnUIThread:(ReactTag)tag props:(folly::dynamic)props; - (void)setupAnimationDriverWithSurfaceHandler:(const facebook::react::SurfaceHandler &)surfaceHandler; - (void)addObserver:(id)observer; - (void)removeObserver:(id)observer; @@ -4495,12 +4771,11 @@ class MainRunLoopObserver final : public PlatformRunLoopObserver { } // namespace facebook::react /// @src {packages/react-native/React/Fabric/Utils/RCTBoxShadow.h}: -RCT_EXTERN UIImage *RCTGetBoxShadowImage( - const std::vector &shadows, +RCT_EXTERN CALayer *RCTGetBoxShadowLayer( + const facebook::react::BoxShadow &shadow, RCTCornerRadii cornerRadii, UIEdgeInsets edgeInsets, - CALayer *layer); -RCT_EXTERN CGRect RCTGetBoundingRect(const std::vector &boxShadows, CGSize layerSize); + CGSize layerSize); /// @src {packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.h}: @interface RCTColorSpaceUtils : NSObject @@ -4518,6 +4793,15 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END +/// @src {packages/react-native/React/Fabric/Utils/RCTGradientUtils.h}: +NS_ASSUME_NONNULL_BEGIN +@interface RCTGradientUtils : NSObject ++ (std::vector)getFixedColorStops: + (const std::vector &)colorStops + gradientLineLength:(CGFloat)gradientLineLength; +@end +NS_ASSUME_NONNULL_END + /// @src {packages/react-native/React/Fabric/Utils/RCTIdentifierPool.h}: namespace facebook::react { template @@ -4550,6 +4834,13 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END +/// @src {packages/react-native/React/Fabric/Utils/RCTRadialGradient.h}: +NS_ASSUME_NONNULL_BEGIN +@interface RCTRadialGradient : NSObject ++ (CALayer *)gradientLayerWithSize:(CGSize)size gradient:(const facebook::react::RadialGradient &)gradient; +@end +NS_ASSUME_NONNULL_END + /// @src {packages/react-native/React/Fabric/Utils/RCTReactTaggedView.h}: NS_ASSUME_NONNULL_BEGIN @interface RCTReactTaggedView : NSObject { @@ -4567,57 +4858,65 @@ NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/I18n/FBXXHashUtils.h}: NS_ASSUME_NONNULL_BEGIN -static const uint64_t PRIME1 = 11400714785074694791ULL; -static const uint64_t PRIME2 = 14029467366897019727ULL; -static const uint64_t PRIME3 = 1609587929392839161ULL; -static const uint64_t PRIME4 = 9650029242287828579ULL; -static const uint64_t PRIME5 = 2870177450012600261ULL; -NS_INLINE uint64_t rotl(uint64_t x, int r) +static const uint64_t METAXXHASHUTILS_PRIME_1 = 11400714785074694791ULL; +static const uint64_t METAXXHASHUTILS_PRIME_2 = 14029467366897019727ULL; +static const uint64_t METAXXHASHUTILS_PRIME_3 = 1609587929392839161ULL; +static const uint64_t METAXXHASHUTILS_PRIME_4 = 9650029242287828579ULL; +static const uint64_t METAXXHASHUTILS_PRIME_5 = 2870177450012600261ULL; +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t rotl(uint64_t x, int r) { return ((x << r) | (x >> (64 - r))); } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t mix1(const uint64_t h, const uint64_t prime, int rshift) { return (h ^ (h >> rshift)) * prime; } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t mix2(const uint64_t p, const uint64_t v) { - return rotl(v + p * PRIME2, 31) * PRIME1; + return rotl(v + p * METAXXHASHUTILS_PRIME_2, 31) * METAXXHASHUTILS_PRIME_1; } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t mix3(const uint64_t h, const uint64_t v) { - return (h ^ mix2(v, 0)) * PRIME1 + PRIME4; + return (h ^ mix2(v, 0)) * METAXXHASHUTILS_PRIME_1 + METAXXHASHUTILS_PRIME_4; } -NS_INLINE uint32_t endian32(const char *v) +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint32_t endian32(const char *v) { return (uint32_t)((uint8_t)(v[0])) | ((uint32_t)((uint8_t)(v[1])) << 8) | ((uint32_t)((uint8_t)(v[2])) << 16) | ((uint32_t)((uint8_t)(v[3])) << 24); } -NS_INLINE uint64_t endian64(const char *v) +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t endian64(const char *v) { return (uint64_t)((uint8_t)(v[0])) | ((uint64_t)((uint8_t)(v[1])) << 8) | ((uint64_t)((uint8_t)(v[2])) << 16) | ((uint64_t)((uint8_t)(v[3])) << 24) | ((uint64_t)((uint8_t)(v[4])) << 32) | ((uint64_t)((uint8_t)(v[5])) << 40) | ((uint64_t)((uint8_t)(v[6])) << 48) | ((uint64_t)((uint8_t)(v[7])) << 56); } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t fetch64(const char *p, const uint64_t v) { return mix2(endian64(p), v); } -NS_INLINE uint64_t fetch32(const char *p) +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t fetch32(const char *p) { - return (uint64_t)(endian32(p))*PRIME1; + return (uint64_t)(endian32(p))*METAXXHASHUTILS_PRIME_1; } -NS_INLINE uint64_t fetch8(const char *p) +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t fetch8(const char *p) { - return (uint8_t)(*p) * PRIME5; + return (uint8_t)(*p) * METAXXHASHUTILS_PRIME_5; } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t finalize(const uint64_t h, const char *p, uint64_t len) { - return (len >= 8) ? (finalize(rotl(h ^ fetch64(p, 0), 27) * PRIME1 + PRIME4, p + 8, len - 8)) - : ((len >= 4) ? (finalize(rotl(h ^ fetch32(p), 23) * PRIME2 + PRIME3, p + 4, len - 4)) - : ((len > 0) ? (finalize(rotl(h ^ fetch8(p), 11) * PRIME1, p + 1, len - 1)) - : (mix1(mix1(mix1(h, PRIME2, 33), PRIME3, 29), 1, 32)))); -} + return (len >= 8) + ? (finalize(rotl(h ^ fetch64(p, 0), 27) * METAXXHASHUTILS_PRIME_1 + METAXXHASHUTILS_PRIME_4, p + 8, len - 8)) + : ((len >= 4) + ? (finalize(rotl(h ^ fetch32(p), 23) * METAXXHASHUTILS_PRIME_2 + METAXXHASHUTILS_PRIME_3, p + 4, len - 4)) + : ((len > 0) ? (finalize(rotl(h ^ fetch8(p), 11) * METAXXHASHUTILS_PRIME_1, p + 1, len - 1)) + : (mix1(mix1(mix1(h, METAXXHASHUTILS_PRIME_2, 33), METAXXHASHUTILS_PRIME_3, 29), 1, 32)))); +} +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t h32bytes_compute( const char *p, uint64_t len, @@ -4630,14 +4929,24 @@ NS_INLINE uint64_t h32bytes_compute( ? h32bytes_compute(p + 32, len - 32, fetch64(p, v1), fetch64(p + 8, v2), fetch64(p + 16, v3), fetch64(p + 24, v4)) : mix3(mix3(mix3(mix3(rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18), v1), v2), v3), v4); } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t h32bytes(const char *p, uint64_t len, const uint64_t seed) { - return h32bytes_compute(p, len, seed + PRIME1 + PRIME2, seed + PRIME2, seed, seed - PRIME1); -} + return h32bytes_compute( + p, + len, + seed + METAXXHASHUTILS_PRIME_1 + METAXXHASHUTILS_PRIME_2, + seed + METAXXHASHUTILS_PRIME_2, + seed, + seed - METAXXHASHUTILS_PRIME_1); +} +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t meta_xxhash64(const char *p, uint64_t len, uint64_t seed) { - return finalize((len >= 32 ? h32bytes(p, len, seed) : seed + PRIME5) + len, p + (len & ~0x1FULL), len & 0x1FULL); + return finalize( + (len >= 32 ? h32bytes(p, len, seed) : seed + METAXXHASHUTILS_PRIME_5) + len, p + (len & ~0x1FULL), len & 0x1FULL); } +NS_SWIFT_UNAVAILABLE("You'll need to bridge to C/ObjC to use this API.") NS_INLINE uint64_t FBxxHash64(const char *p, uint64_t len, uint64_t seed) { return meta_xxhash64(p, len, seed); @@ -4746,7 +5055,7 @@ NS_ASSUME_NONNULL_BEGIN - (id)createFabricSurfaceForModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties; - (nullable UIView *)findComponentViewWithTag_DO_NOT_USE_DEPRECATED:(NSInteger)tag; -- (BOOL)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props; +- (void)synchronouslyUpdateViewOnUIThread:(NSNumber *)reactTag props:(NSDictionary *)props; - (void)addObserver:(id)observer; - (void)removeObserver:(id)observer; @end @@ -4837,17 +5146,15 @@ RCT_EXTERN NSString *const RCTProfileDidStartProfiling; RCT_EXTERN NSString *const RCTProfileDidEndProfiling; RCT_EXTERN const uint64_t RCTProfileTagAlways; -/// @src {packages/react-native/React/UIUtils/RCTUIUtils.h}: -NS_ASSUME_NONNULL_BEGIN +/// @src {packages/react-native/React/Runtime/RCTHermesInstanceFactory.h}: extern "C" { -typedef struct { - struct { - CGFloat width, height, scale, fontScale; - } window, screen; -} RCTDimensions; -extern __attribute__((visibility("default"))) RCTDimensions RCTGetDimensions(CGFloat fontScale); +JSRuntimeFactoryRef jsrt_create_hermes_factory(void); +} + +/// @src {packages/react-native/React/Runtime/RCTJscInstanceFactory.h}: +extern "C" { +JSRuntimeFactoryRef jsrt_create_jsc_factory(void); } -NS_ASSUME_NONNULL_END /// @src {packages/react-native/React/Views/RCTActivityIndicatorView.h}: @interface RCTActivityIndicatorView : UIActivityIndicatorView @@ -4906,12 +5213,16 @@ typedef struct { UIColor *bottom; UIColor *right; } RCTBorderColors; +RCT_EXTERN CGFloat RCTMaxBorderInset(UIEdgeInsets borderInsets); RCT_EXTERN BOOL RCTBorderInsetsAreEqual(UIEdgeInsets borderInsets); RCT_EXTERN BOOL RCTCornerRadiiAreEqualAndSymmetrical(RCTCornerRadii cornerRadii); RCT_EXTERN BOOL RCTBorderColorsAreEqual(RCTBorderColors borderColors); RCT_EXTERN RCTCornerInsets RCTGetCornerInsets(RCTCornerRadii cornerRadii, UIEdgeInsets borderInsets); -RCT_EXTERN CGPathRef -RCTPathCreateWithRoundedRect(CGRect bounds, RCTCornerInsets cornerInsets, const CGAffineTransform *transform); +RCT_EXTERN CGPathRef RCTPathCreateWithRoundedRect( + CGRect bounds, + RCTCornerInsets cornerInsets, + const CGAffineTransform *transform, + const BOOL inverted); RCT_EXTERN UIImage *RCTGetBorderImage( RCTBorderStyle borderStyle, CGSize viewSize, @@ -5531,382 +5842,6 @@ typedef struct { - (NSString *)react_recursiveDescription; @end -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/ALog.h}: - - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/Build.h}: -namespace facebook { -namespace build { -struct Build { - static int getAndroidSdk() { - static auto android_sdk = ([] { - char sdk_version_str[PROP_VALUE_MAX]; - __system_property_get("ro.build.version.sdk", sdk_version_str); - return atoi(sdk_version_str); - })(); - return android_sdk; - } -}; -} // namespace build -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/Countable.h}: -namespace facebook { -class Countable : public noncopyable, public nonmovable { - public: - Countable() : m_refcount(0) {} - virtual ~Countable() { - FBASSERT(m_refcount == 0); - } -}; -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/Environment.h}: -namespace facebook { -namespace jni { -namespace internal { -struct CacheEnvTag {}; -} // namespace internal -struct Environment { - FBEXPORT static JNIEnv* current(); - static void initialize(JavaVM* vm); - FBEXPORT static JNIEnv* ensureCurrentThreadIsAttached(); - FBEXPORT static void detachCurrentThread(); -}; -class FBEXPORT ThreadScope { - public: - ThreadScope(); - ThreadScope(ThreadScope&) = delete; - ThreadScope(ThreadScope&&) = default; - ThreadScope& operator=(ThreadScope&) = delete; - ThreadScope& operator=(ThreadScope&&) = delete; - ~ThreadScope(); - static void WithClassLoader(std::function&& runnable); - static void OnLoad(); - ThreadScope(JNIEnv*, internal::CacheEnvTag); -}; -} // namespace jni -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/ProgramLocation.h}: -namespace facebook { -class ProgramLocation { - public: - ProgramLocation() - : m_functionName("Unspecified"), - m_fileName("Unspecified"), - m_lineNumber(0) {} - ProgramLocation(const char* functionName, const char* fileName, int line) - : m_functionName(functionName), - m_fileName(fileName), - m_lineNumber(line) {} - const char* functionName() const { - return m_functionName; - } - const char* fileName() const { - return m_fileName; - } - int lineNumber() const { - return m_lineNumber; - } - std::string asFormattedString() const { - std::stringstream str; - str << "Function " << m_functionName << " in file " << m_fileName << ":" - << m_lineNumber; - return str.str(); - } - bool operator==(const ProgramLocation& other) const { - return (m_functionName == other.m_functionName) && - (m_fileName == other.m_fileName) && m_lineNumber == other.m_lineNumber; - } -}; -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/RefPtr.h}: -namespace facebook { -template -class RefPtr { - public: - constexpr RefPtr() : m_ptr(nullptr) {} - constexpr RefPtr(std::nullptr_t ptr) : m_ptr(nullptr) {} - RefPtr(const RefPtr& ref) : m_ptr(ref.m_ptr) { - refIfNecessary(m_ptr); - } - template - RefPtr( - const RefPtr& ref, - typename std::enable_if::value, U>::type* = nullptr) - : m_ptr(ref.get()) { - refIfNecessary(m_ptr); - } - RefPtr(RefPtr&& ref) : m_ptr(nullptr) { - *this = std::move(ref); - } - template - RefPtr( - RefPtr&& ref, - typename std::enable_if::value, U>::type* = nullptr) - : m_ptr(nullptr) { - *this = std::move(ref); - } - ~RefPtr() { - unrefIfNecessary(m_ptr); - m_ptr = nullptr; - } - RefPtr& operator=(const RefPtr& ref) { - if (m_ptr != ref.m_ptr) { - unrefIfNecessary(m_ptr); - m_ptr = ref.m_ptr; - refIfNecessary(m_ptr); - } - return *this; - } - RefPtr& operator=(RefPtr&& ref) { - unrefIfNecessary(m_ptr); - m_ptr = ref.m_ptr; - ref.m_ptr = nullptr; - return *this; - } - template - RefPtr& operator=(RefPtr&& ref) { - unrefIfNecessary(m_ptr); - m_ptr = ref.m_ptr; - ref.m_ptr = nullptr; - return *this; - } - void reset() { - unrefIfNecessary(m_ptr); - m_ptr = nullptr; - } - T* get() const { - return m_ptr; - } - T* operator->() const { - return m_ptr; - } - T& operator*() const { - return *m_ptr; - } - template - explicit operator RefPtr() const; - explicit operator bool() const { - return m_ptr ? true : false; - } - bool isTheLastRef() const { - FBASSERT(m_ptr); - return m_ptr->hasOnlyOneRef(); - } - static inline RefPtr assumeAlreadyReffed(T* ptr) { - return RefPtr(ptr, ConstructionMode::External); - } - static inline RefPtr adoptRef(T* ptr) { - return RefPtr(ptr, ConstructionMode::Adopted); - } -}; - RefPtr(T* ptr, ConstructionMode mode) : m_ptr(ptr) { - FBASSERTMSGF( - ptr, - "Got null pointer in %s construction mode", - mode == ConstructionMode::Adopted ? "adopted" : "external"); - ptr->ref(); - if (mode == ConstructionMode::Adopted) { - FBASSERT(ptr->hasOnlyOneRef()); - } - } - static inline void refIfNecessary(T* ptr) { - if (ptr) { - ptr->ref(); - } - } - static inline void unrefIfNecessary(T* ptr) { - if (ptr) { - ptr->unref(); - } - } - template - friend - T* m_ptr; -}; -template -static inline RefPtr assumeAlreadyReffed(T* ptr) { - return RefPtr::assumeAlreadyReffed(ptr); -} -template -static inline RefPtr assumeAlreadyReffedOrNull(T* ptr) { - return ptr ? RefPtr::assumeAlreadyReffed(ptr) : nullptr; -} -template -static inline RefPtr adoptRef(T* ptr) { - return RefPtr::adoptRef(ptr); -} -template -static inline RefPtr createNew(Args&&... arguments) { - return RefPtr::adoptRef(new T(std::forward(arguments)...)); -} -template -template -RefPtr::operator RefPtr() const { - static_assert(std::is_base_of::value, "Invalid static cast"); - return assumeAlreadyReffedOrNull(static_cast(m_ptr)); -} -template -inline bool operator==(const RefPtr& a, const RefPtr& b) { - return a.get() == b.get(); -} -template -inline bool operator!=(const RefPtr& a, const RefPtr& b) { - return a.get() != b.get(); -} -template -inline bool operator==(const RefPtr& ref, U* ptr) { - return ref.get() == ptr; -} -template -inline bool operator!=(const RefPtr& ref, U* ptr) { - return ref.get() != ptr; -} -template -inline bool operator==(U* ptr, const RefPtr& ref) { - return ref.get() == ptr; -} -template -inline bool operator!=(U* ptr, const RefPtr& ref) { - return ref.get() != ptr; -} -template -inline bool operator==(const RefPtr& ref, std::nullptr_t ptr) { - return ref.get() == ptr; -} -template -inline bool operator!=(const RefPtr& ref, std::nullptr_t ptr) { - return ref.get() != ptr; -} -template -inline bool operator==(std::nullptr_t ptr, const RefPtr& ref) { - return ref.get() == ptr; -} -template -inline bool operator!=(std::nullptr_t ptr, const RefPtr& ref) { - return ref.get() != ptr; -} -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/StaticInitialized.h}: -namespace facebook { -template -class StaticInitialized { - public: - constexpr StaticInitialized() : m_instance(nullptr) {} - template - void initialize(Args&&... arguments) { - FBASSERT(!m_instance); - m_instance = new T(std::forward(arguments)...); - } - T* operator->() const { - return m_instance; - } -}; -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/ThreadLocal.h}: -namespace facebook { -template -class ThreadLocal { - public: - ThreadLocal() : m_key(0), m_cleanup(OnThreadExit) { - initialize(); - } - typedef void (*CleanupFunction)(void* obj); - explicit ThreadLocal(CleanupFunction cleanup) : m_key(0), m_cleanup(cleanup) { - FBASSERT(cleanup); - initialize(); - } - T* operator->() const { - return get(); - } - T& operator*() const { - return *get(); - } - T* get() const { - return (T*)pthread_getspecific(m_key); - } - T* release() { - T* obj = get(); - pthread_setspecific(m_key, NULL); - return obj; - } - void reset(T* other = NULL) { - T* old = (T*)pthread_getspecific(m_key); - if (old != other) { - FBASSERT(m_cleanup); - m_cleanup(old); - pthread_setspecific(m_key, other); - } - } -}; -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/assert.h}: -namespace facebook { -FBEXPORT void assertInternal(const char* formatstr, ...) - __attribute__((noreturn)); -typedef void (*AssertHandler)(const char* message); -void setAssertHandler(AssertHandler assertHandler); -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/log.h}: -extern "C" { -typedef enum android_LogPriority { - ANDROID_LOG_UNKNOWN = 0, - ANDROID_LOG_DEFAULT, - ANDROID_LOG_VERBOSE, - ANDROID_LOG_DEBUG, - ANDROID_LOG_INFO, - ANDROID_LOG_WARN, - ANDROID_LOG_ERROR, - ANDROID_LOG_FATAL, - ANDROID_LOG_SILENT, -} android_LogPriority; -int __android_log_write(int prio, const char* tag, const char* text); -int __android_log_print(int prio, const char* tag, const char* fmt, ...) - __attribute__((format(printf, 3, 4))); -typedef void (*LogHandler)(int priority, const char* tag, const char* message); -FBEXPORT void setLogHandler(LogHandler logHandler); -FBEXPORT int fb_printLog(int prio, const char* tag, const char* fmt, ...) - __attribute__((format(printf, 3, 4))); -void logPrintByDelims( - int priority, - const char* tag, - const char* delims, - const char* msg, - ...); -} - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/noncopyable.h}: -namespace facebook { -struct noncopyable { - noncopyable(const noncopyable&) = delete; - noncopyable& operator=(const noncopyable&) = delete; - - protected: - noncopyable() = default; -}; -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/nonmovable.h}: -namespace facebook { -struct nonmovable { - nonmovable(nonmovable&&) = delete; - nonmovable& operator=(nonmovable&&) = delete; - - protected: - nonmovable() = default; -}; -} // namespace facebook - -/// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fb/include/fb/visibility.h}: - - /// @src {packages/react-native/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h}: namespace facebook { namespace gloginit { @@ -6407,6 +6342,7 @@ class JCxxInspectorPackagerConnectionWebSocketDelegate jni::alias_ref posixCode, const std::string& error); void didReceiveMessage(const std::string& message); + void didOpen(); void didClose(); static void registerNatives(); JCxxInspectorPackagerConnectionWebSocketDelegate( @@ -6445,27 +6381,7 @@ class AndroidEventBeat final : public EventBeat, } // namespace facebook::react /// @src {packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h}: -/// @dep {packages/react-native/ReactAndroid/src/main/jni/react/fabric/EventEmitterWrapper.h} -/// @dep {packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.h} -/// @dep {packages/react-native/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.h} - -namespace facebook::react { -class FabricUIManagerBinding : public jni::HybridClass, - public SchedulerDelegate, - public LayoutAnimationStatusDelegate { - public: - constexpr static const char* const kJavaDescriptor = - "Lcom/facebook/react/fabric/FabricUIManagerBinding;"; - static void registerNatives(); - std::shared_ptr getScheduler(); -}; - std::shared_mutex surfaceHandlerRegistryMutex_; - std::mutex pendingTransactionsMutex_; - std::vector pendingTransactions_; - float pointScaleFactor_ = 1; - bool enableFabricLogs_{false}; -}; -} // namespace facebook::react +/// @dep {packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h} /// @src {packages/react-native/ReactAndroid/src/main/jni/react/fabric/ComponentFactory.h}: namespace facebook::react { @@ -6496,14 +6412,11 @@ class EventBeatManager : public jni::HybridClass { constexpr static const char* const kJavaDescriptor = "Lcom/facebook/react/fabric/events/EventBeatManager;"; static void registerNatives(); - explicit EventBeatManager( - jni::alias_ref jhybridobject); void addObserver(const EventBeatManagerObserver& observer) const; void removeObserver(const EventBeatManagerObserver& observer) const; }; mutable std::mutex mutex_; - static jni::local_ref initHybrid( - jni::alias_ref jhybridobject); + static void initHybrid(jni::alias_ref jobj); }; } // namespace facebook::react @@ -6549,6 +6462,9 @@ class FabricMountingManager final { bool blockNativeResponder); void onAnimationStarted(); void onAllAnimationsComplete(); + void synchronouslyUpdateViewOnUIThread( + Tag viewTag, + const folly::dynamic& props); }; std::unordered_map> allocatedViewRegistry_{}; @@ -6560,6 +6476,36 @@ class FabricMountingManager final { /// @src {packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.h}: /// @dep {packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h} +/// @src {packages/react-native/ReactAndroid/src/main/jni/react/fabric/FocusOrderingHelper.h}: +/// @dep {packages/react-native/ReactAndroid/src/main/jni/react/fabric/Binding.h} + +namespace facebook::react { +enum class FocusDirection { + FocusDown = 0, + FocusUp = 1, + FocusRight = 2, + FocusLeft = 3, + FocusForward = 4, + FocusBackward = 5, +}; +class FocusOrderingHelper { + public: + static void traverseAndUpdateNextFocusableElement( + const ShadowNode::Shared& parentShadowNode, + const ShadowNode::Shared& focusedShadowNode, + const ShadowNode::Shared& currNode, + FocusDirection focusDirection, + const UIManager& uimanager, + Rect sourceRect, + std::optional& nextRect, + ShadowNode::Shared& nextNode); + static ShadowNode::Shared findShadowNodeByTagRecursively( + const ShadowNode::Shared& parentShadowNode, + Tag tag); + static std::optional resolveFocusDirection(int direction); +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactAndroid/src/main/jni/react/fabric/JFabricUIManager.h}: namespace facebook::react { class JFabricUIManager : public jni::JavaClass { @@ -6627,6 +6573,7 @@ class StateWrapperImpl : public jni::HybridClass { static void registerNatives(); jni::local_ref getStateMapBufferDataImpl(); jni::local_ref getStateDataImpl(); + jni::local_ref getStateDataReferenceImpl(); void updateStateImpl(NativeMap* map); void setState(std::shared_ptr state); std::shared_ptr getState() const; @@ -6654,7 +6601,8 @@ class SurfaceHandlerBinding : public jni::HybridClass { jfloat offsetY, jboolean doLeftAndRightSwapInRTL, jboolean isRTL, - jfloat pixelDensity); + jfloat pixelDensity, + jfloat fontScale); void setProps(NativeMap* props); const SurfaceHandler& getSurfaceHandler(); }; @@ -6669,90 +6617,108 @@ class JReactNativeFeatureFlagsCxxInterop "Lcom/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop;"; static bool commonTestFlag( facebook::jni::alias_ref); - static bool completeReactInstanceCreationOnBgThreadOnAndroid( + static bool animatedShouldSignalBatch( + facebook::jni::alias_ref); + static bool cxxNativeAnimatedEnabled( facebook::jni::alias_ref); - static bool disableEventLoopOnBridgeless( + static bool disableMainQueueSyncDispatchIOS( facebook::jni::alias_ref); static bool disableMountItemReorderingAndroid( facebook::jni::alias_ref); - static bool enableAccumulatedUpdatesInRawPropsAndroid( + static bool disableTextLayoutManagerCacheAndroid( facebook::jni::alias_ref); - static bool enableAlignItemsBaselineOnFabricIOS( + static bool enableAccessibilityOrder( facebook::jni::alias_ref); - static bool enableAndroidLineHeightCentering( + static bool enableAccumulatedUpdatesInRawPropsAndroid( facebook::jni::alias_ref); static bool enableBridgelessArchitecture( facebook::jni::alias_ref); static bool enableCppPropsIteratorSetter( facebook::jni::alias_ref); - static bool enableDeletionOfUnmountedViews( + static bool enableCustomFocusSearchOnClippedElementsAndroid( facebook::jni::alias_ref); - static bool enableEagerRootViewAttachment( + static bool enableDestroyShadowTreeRevisionAsync( + facebook::jni::alias_ref); + static bool enableDoubleMeasurementFixAndroid( facebook::jni::alias_ref); - static bool enableEventEmitterRetentionDuringGesturesOnAndroid( + static bool enableEagerRootViewAttachment( facebook::jni::alias_ref); static bool enableFabricLogs( facebook::jni::alias_ref); static bool enableFabricRenderer( facebook::jni::alias_ref); - static bool enableFixForViewCommandRace( + static bool enableFixForParentTagDuringReparenting( + facebook::jni::alias_ref); + static bool enableFontScaleChangesUpdatingLayout( facebook::jni::alias_ref); - static bool enableGranularShadowTreeStateReconciliation( + static bool enableIOSTextBaselineOffsetPerLine( facebook::jni::alias_ref); static bool enableIOSViewClipToPaddingBox( facebook::jni::alias_ref); - static bool enableImagePrefetchingAndroid( + static bool enableIntersectionObserverEventLoopIntegration( facebook::jni::alias_ref); static bool enableLayoutAnimationsOnAndroid( facebook::jni::alias_ref); static bool enableLayoutAnimationsOnIOS( facebook::jni::alias_ref); + static bool enableMainQueueCoordinatorOnIOS( + facebook::jni::alias_ref); + static bool enableMainQueueModulesOnIOS( + facebook::jni::alias_ref); + static bool enableModuleArgumentNSNullConversionIOS( + facebook::jni::alias_ref); + static bool enableNativeCSSParsing( + facebook::jni::alias_ref); + static bool enableNetworkEventReporting( + facebook::jni::alias_ref); static bool enableNewBackgroundAndBorderDrawables( facebook::jni::alias_ref); + static bool enablePreparedTextLayout( + facebook::jni::alias_ref); static bool enablePropsUpdateReconciliationAndroid( facebook::jni::alias_ref); + static bool enableResourceTimingAPI( + facebook::jni::alias_ref); static bool enableSynchronousStateUpdates( facebook::jni::alias_ref); + static bool enableViewCulling( + facebook::jni::alias_ref); static bool enableViewRecycling( facebook::jni::alias_ref); - static bool excludeYogaFromRawProps( + static bool enableViewRecyclingForText( facebook::jni::alias_ref); - static bool fixDifferentiatorEmittingUpdatesWithWrongParentTag( + static bool enableViewRecyclingForView( facebook::jni::alias_ref); - static bool fixMappingOfEventPrioritiesBetweenFabricAndReact( + static bool enableVirtualViewDebugFeatures( facebook::jni::alias_ref); - static bool fuseboxEnabledDebug( + static bool fixMappingOfEventPrioritiesBetweenFabricAndReact( facebook::jni::alias_ref); static bool fuseboxEnabledRelease( facebook::jni::alias_ref); - static bool initEagerTurboModulesOnNativeModulesQueueAndroid( - facebook::jni::alias_ref); - static bool lazyAnimationCallbacks( - facebook::jni::alias_ref); - static bool loadVectorDrawablesOnImages( + static bool fuseboxNetworkInspectionEnabled( facebook::jni::alias_ref); static bool traceTurboModulePromiseRejectionsOnAndroid( facebook::jni::alias_ref); + static bool updateRuntimeShadowNodeReferencesOnCommit( + facebook::jni::alias_ref); static bool useAlwaysAvailableJSErrorHandling( facebook::jni::alias_ref); static bool useFabricInterop( facebook::jni::alias_ref); - static bool useImmediateExecutorInAndroidBridgeless( - facebook::jni::alias_ref); static bool useNativeViewConfigsInBridgelessMode( facebook::jni::alias_ref); - static bool useOptimisedViewPreallocationOnAndroid( - facebook::jni::alias_ref); static bool useOptimizedEventBatchingOnAndroid( facebook::jni::alias_ref); static bool useRawPropsJsiValue( facebook::jni::alias_ref); - static bool useRuntimeShadowNodeReferenceUpdate( + static bool useShadowNodeStateOnClone( facebook::jni::alias_ref); static bool useTurboModuleInterop( facebook::jni::alias_ref); static bool useTurboModules( facebook::jni::alias_ref); + static double virtualViewPrerenderRatio( + facebook::jni::alias_ref); static void override( facebook::jni::alias_ref, jni::alias_ref provider); @@ -7211,11 +7177,8 @@ std::unique_ptr loadScriptFromAssets( /// @src {packages/react-native/ReactAndroid/src/main/jni/react/jni/JSLogging.h}: namespace facebook::react { -void reactAndroidLoggingHook( - const std::string& message, - android_LogPriority logLevel); void reactAndroidLoggingHook(const std::string& message, unsigned int logLevel); -} // namespace facebook::react +} /// @src {packages/react-native/ReactAndroid/src/main/jni/react/jni/JWeakRefUtils.h}: namespace facebook::react { @@ -7446,44 +7409,6 @@ class NativeMap : public jni::HybridClass { }; } // namespace facebook::react -/// @src {packages/react-native/ReactAndroid/src/main/jni/react/jni/ProxyExecutor.h}: -namespace facebook::react { -class ProxyExecutorOneTimeFactory : public JSExecutorFactory { - public: - ProxyExecutorOneTimeFactory(jni::global_ref&& executorInstance) - : m_executor(std::move(executorInstance)) {} - virtual std::unique_ptr createJSExecutor( - std::shared_ptr delegate, - std::shared_ptr queue) override; -}; -class ProxyExecutor : public JSExecutor { - public: - ProxyExecutor( - jni::global_ref&& executorInstance, - std::shared_ptr delegate); - virtual ~ProxyExecutor() override; - virtual void initializeRuntime() override; - virtual void loadBundle( - std::unique_ptr script, - std::string sourceURL) override; - virtual void setBundleRegistry( - std::unique_ptr bundle) override; - virtual void registerBundle(uint32_t bundleId, const std::string& bundlePath) - override; - virtual void callFunction( - const std::string& moduleId, - const std::string& methodId, - const folly::dynamic& arguments) override; - virtual void invokeCallback( - const double callbackId, - const folly::dynamic& arguments) override; - virtual void setGlobalVariable( - std::string propName, - std::unique_ptr jsonValue) override; - virtual std::string getDescription() override; -}; -} // namespace facebook::react - /// @src {packages/react-native/ReactAndroid/src/main/jni/react/jni/ReactInstanceManagerInspectorTarget.h}: namespace facebook::react { class ReactInstanceManagerInspectorTarget @@ -7661,11 +7586,13 @@ struct ReadableNativeMap : jni::HybridClass { /// @src {packages/react-native/ReactAndroid/src/main/jni/react/jni/SafeReleaseJniRef.h}: namespace facebook::react { +void ensureThreadDurationJNIEnvAttached(); template class SafeReleaseJniRef { using T = std::remove_reference())>::type; public: + SafeReleaseJniRef() = default; SafeReleaseJniRef(RefT ref) : ref_(std::move(ref)) {} SafeReleaseJniRef(const SafeReleaseJniRef& other) = default; SafeReleaseJniRef(SafeReleaseJniRef&& other) = default; @@ -7673,7 +7600,7 @@ class SafeReleaseJniRef { SafeReleaseJniRef& operator=(SafeReleaseJniRef&& other) = default; ~SafeReleaseJniRef() { if (ref_) { - jni::ThreadScope ts; + ensureThreadDurationJNIEnvAttached(); ref_.reset(); } } @@ -7695,6 +7622,9 @@ class SafeReleaseJniRef { operator RefT() const { return ref_; } + RefT::javaobject get() const { + return ref_.get(); + } }; } // namespace facebook::react @@ -7871,11 +7801,9 @@ class JReadableMapBuffer : public jni::HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/facebook/react/common/mapbuffer/ReadableMapBuffer;"; - static void registerNatives(); static jni::local_ref createWithContents( MapBuffer&& map); explicit JReadableMapBuffer(MapBuffer&& map); - jni::local_ref importByteBuffer(); std::vector data() const; }; } // namespace facebook::react @@ -7901,6 +7829,9 @@ class DefaultComponentsRegistry static std::function)> registerComponentDescriptorsFromEntryPoint; + static std::function)> + registerCodegenComponentDescriptorsFromEntryPoint; }; } // namespace facebook::react @@ -7933,6 +7864,11 @@ class DefaultTurboModuleManagerDelegate : public jni::HybridClass< }; } // namespace facebook::react +/// @src {packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/rncore.h}: +namespace facebook::react { +constexpr auto rncore_ModuleProvider = FBReactNativeSpec_ModuleProvider; +} + /// @src {packages/react-native/ReactAndroid/src/main/jni/react/reactnativeblob/BlobCollector.h}: namespace facebook::react { class BlobCollector : public jni::HybridClass, @@ -7996,8 +7932,7 @@ class JHermesInstance } // namespace facebook::react /// @src {packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JBindingsInstaller.h}: -namespace facebook { -namespace react { +namespace facebook::react { class JBindingsInstaller : public jni::HybridClass, public BindingsInstaller { public: @@ -8005,8 +7940,7 @@ class JBindingsInstaller : public jni::HybridClass, "Lcom/facebook/react/runtime/BindingsInstaller;"; ~JBindingsInstaller() {} }; -} // namespace react -} // namespace facebook +} // namespace facebook::react /// @src {packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JJSRuntimeFactory.h}: namespace facebook::react { @@ -8206,8 +8140,9 @@ class CallInvokerHolder : public jni::HybridClass { public: static auto constexpr kJavaDescriptor = "Lcom/facebook/react/turbomodule/core/CallInvokerHolderImpl;"; - static void registerNatives(); - std::shared_ptr getCallInvoker(); + std::shared_ptr getCallInvoker() { + return callInvoker_; + } }; } // namespace facebook::react @@ -8218,8 +8153,9 @@ class NativeMethodCallInvokerHolder public: static auto constexpr kJavaDescriptor = "Lcom/facebook/react/turbomodule/core/NativeMethodCallInvokerHolderImpl;"; - static void registerNatives(); - std::shared_ptr getNativeMethodCallInvoker(); + std::shared_ptr getNativeMethodCallInvoker() { + return nativeMethodCallInvoker_; + } }; } // namespace facebook::react @@ -8814,7 +8750,6 @@ class __attribute__((visibility("default"))) JSExecutor { static std::string getSyntheticBundlePath( uint32_t bundleId, const std::string& bundlePath); - static double performanceNow(); virtual jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate(); }; } // namespace facebook::react @@ -8866,9 +8801,9 @@ class JSModulesUnbundle { class ModuleNotFound : public std::out_of_range { public: using std::out_of_range::out_of_range; - ModuleNotFound(uint32_t moduleId) + explicit ModuleNotFound(uint32_t moduleId) : std::out_of_range::out_of_range( - folly::to("Module not found: ", moduleId)) {} + "Module not found: " + std::to_string(moduleId)) {} }; struct Module { std::string name; @@ -8884,19 +8819,29 @@ class JSModulesUnbundle { namespace facebook { namespace xplat { namespace detail { +inline std::string toStringHelper() { + return ""; +} +template +inline std::string toStringHelper(const T& value, const Rest&... rest) { + return std::to_string(value) + toStringHelper(rest...); +} +template +inline std::string toStringHelper(const char* value, const Rest&... rest) { + return std::string(value) + toStringHelper(rest...); +} template R jsArg1(const folly::dynamic& arg, M asFoo, const T&... desc) { try { return (arg.*asFoo)(); } catch (const folly::TypeError& ex) { - throw JsArgumentException(folly::to( - "Error converting javascript arg ", desc..., " to C++: ", ex.what())); + throw JsArgumentException( + "Error converting JavaScript arg " + toStringHelper(desc...) + + " to C++: " + ex.what()); } catch (const std::range_error& ex) { - throw JsArgumentException(folly::to( - "Could not convert argument ", - desc..., - " to required type: ", - ex.what())); + throw JsArgumentException( + "Could not convert argument " + toStringHelper(desc...) + + " to required type: " + ex.what()); } } } // namespace detail @@ -8919,13 +8864,10 @@ typename detail::is_dynamic::type& jsArgAsDynamic(T&& args, size_t n) { try { return args[n]; } catch (const std::out_of_range& ex) { - throw JsArgumentException(folly::to( - "JavaScript provided ", - args.size(), - " arguments for C++ method which references at least ", - n + 1, - " arguments: ", - ex.what())); + throw JsArgumentException( + "JavaScript provided " + std::to_string(args.size()) + + " arguments for C++ method which references at least " + + std::to_string(n + 1) + " arguments: " + ex.what()); } } template @@ -8953,13 +8895,9 @@ typename detail::is_dynamic::type& jsArgAsType( if ((ret.*isFoo)()) { return ret; } - throw JsArgumentException(folly::to( - "Argument ", - n + 1, - " of type ", - ret.typeName(), - " is not required type ", - required)); + throw JsArgumentException( + "Argument " + std::to_string(n + 1) + " of type " + ret.typeName() + + " is not required type " + required); } } // namespace detail template @@ -9446,6 +9384,21 @@ class HermesExecutor : public JSIExecutor { /// @src {packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h}: +/// @src {packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeSamplingProfileSerializer.h}: +namespace facebook::react::jsinspector_modern::tracing { +class RawHermesRuntimeProfile : public RawRuntimeProfile { + public: + explicit RawHermesRuntimeProfile( + hermes::sampling_profiler::Profile hermesProfile) + : hermesProfile_{std::move(hermesProfile)} {} +}; +class HermesRuntimeSamplingProfileSerializer { + public: + static tracing::RuntimeSamplingProfile serializeToTracingSamplingProfile( + hermes::sampling_profiler::Profile hermesProfile); +}; +} // namespace facebook::react::jsinspector_modern::tracing + /// @src {packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h}: namespace facebook::react::jsinspector_modern { class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { @@ -9467,6 +9420,9 @@ class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip) override; + void enableSamplingProfiler() override; + void disableSamplingProfiler() override; + tracing::RuntimeSamplingProfile collectSamplingProfile() override; }; } // namespace facebook::react::jsinspector_modern @@ -9606,6 +9562,9 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { const Plain& plain() const { return plain_; } + ICast* castInterface(const UUID& interfaceUUID) override { + return plain().castInterface(interfaceUUID); + } Value evaluateJavaScript( const std::shared_ptr& buffer, const std::string& sourceURL) override { @@ -9668,6 +9627,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { PropNameID createPropNameIDFromString(const String& str) override { return plain_.createPropNameIDFromString(str); }; + PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) + override { + return plain_.createPropNameIDFromUtf16(utf16, length); + } PropNameID createPropNameIDFromSymbol(const Symbol& sym) override { return plain_.createPropNameIDFromSymbol(sym); }; @@ -9704,6 +9667,9 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { String createStringFromUtf8(const uint8_t* utf8, size_t length) override { return plain_.createStringFromUtf8(utf8, length); }; + String createStringFromUtf16(const char16_t* utf16, size_t length) override { + return plain_.createStringFromUtf16(utf16, length); + } std::string utf8(const String& s) override { return plain_.utf8(s); } @@ -9851,6 +9817,15 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { override { return plain_.callAsConstructor(f, args, count); }; + void setRuntimeDataImpl( + const UUID& uuid, + const void* data, + void (*deleter)(const void* data)) override { + return plain_.setRuntimeDataImpl(uuid, data, deleter); + } + const void* getRuntimeDataImpl(const UUID& uuid) override { + return plain_.getRuntimeDataImpl(uuid); + } Runtime::ScopeState* pushScope() override { return plain_.pushScope(); } @@ -9964,6 +9939,10 @@ class WithRuntimeDecorator : public RuntimeDecorator { public: using RD = RuntimeDecorator; WithRuntimeDecorator(Plain& plain, With& with) : RD(plain), with_(with) {} + ICast* castInterface(const UUID& interfaceUUID) override { + Around around{with_}; + return RD::castInterface(interfaceUUID); + } Value evaluateJavaScript( const std::shared_ptr& buffer, const std::string& sourceURL) override { @@ -10038,6 +10017,11 @@ class WithRuntimeDecorator : public RuntimeDecorator { Around around{with_}; return RD::createPropNameIDFromUtf8(utf8, length); }; + PropNameID createPropNameIDFromUtf16(const char16_t* utf16, size_t length) + override { + Around around{with_}; + return RD::createPropNameIDFromUtf16(utf16, length); + } PropNameID createPropNameIDFromString(const String& str) override { Around around{with_}; return RD::createPropNameIDFromString(str); @@ -10090,6 +10074,10 @@ class WithRuntimeDecorator : public RuntimeDecorator { Around around{with_}; return RD::createStringFromUtf8(utf8, length); }; + String createStringFromUtf16(const char16_t* utf16, size_t length) override { + Around around{with_}; + return RD::createStringFromUtf16(utf16, length); + } std::string utf8(const String& s) override { Around around{with_}; return RD::utf8(s); @@ -10306,6 +10294,17 @@ class WithRuntimeDecorator : public RuntimeDecorator { Around around{with_}; RD::setExternalMemoryPressure(obj, amount); }; + void setRuntimeDataImpl( + const UUID& uuid, + const void* data, + void (*deleter)(const void* data)) override { + Around around{with_}; + RD::setRuntimeDataImpl(uuid, data, deleter); + } + const void* getRuntimeDataImpl(const UUID& uuid) override { + Around around{with_}; + return RD::getRuntimeDataImpl(uuid); + } }; With& with_; }; @@ -10416,6 +10415,18 @@ inline const Runtime::PointerValue* Runtime::getPointerValue( const jsi::Value& value) { return value.data_.pointer.ptr_; } +inline void Runtime::setRuntimeData( + const UUID& uuid, + const std::shared_ptr& data) { + auto* dataPtr = new std::shared_ptr(data); + setRuntimeDataImpl(uuid, dataPtr, [](const void* data) { + delete (const std::shared_ptr*)data; + }); +} +inline std::shared_ptr Runtime::getRuntimeData(const UUID& uuid) { + auto* data = (const std::shared_ptr*)getRuntimeDataImpl(uuid); + return data ? *data : nullptr; +} Value Object::getPrototype(Runtime& runtime) const { return runtime.getPrototypeOf(*this); } @@ -10645,6 +10656,71 @@ String BigInt::toString(Runtime& runtime, int radix) const { namespace facebook { namespace jsi { +class __attribute__((visibility("default"))) UUID { + public: + constexpr UUID( + uint32_t timeLow, + uint16_t timeMid, + uint16_t timeHighAndVersion, + uint16_t variantAndClockSeq, + uint64_t node) + : high( + ((uint64_t)(timeLow) << 32) | ((uint64_t)(timeMid) << 16) | + ((uint64_t)(timeHighAndVersion))), + low(((uint64_t)(variantAndClockSeq) << 48) | node) {} + constexpr UUID() : high(0), low(0) {} + constexpr UUID(const UUID&) = default; + constexpr UUID& operator=(const UUID&) = default; + constexpr bool operator==(const UUID& other) const { + return high == other.high && low == other.low; + } + constexpr bool operator!=(const UUID& other) const { + return !(*this == other); + } + constexpr bool operator<(const UUID& other) const { + return (high < other.high) || (high == other.high && low < other.low); + } + struct Hash { + std::size_t operator()(const UUID& uuid) const noexcept { + return std::hash{}(uuid.high) ^ + (std::hash{}(uuid.low) << 1); + } + }; + std::string toString() const { + std::string buffer(36, ' '); + std::snprintf( + buffer.data(), + buffer.size() + 1, + "%08x-%04x-%04x-%04x-%012llx", + getTimeLow(), + getTimeMid(), + getTimeHighAndVersion(), + getVariantAndClockSeq(), + (unsigned long long)getNode()); + return buffer; + } + constexpr uint32_t getTimeLow() const { + return (uint32_t)(high >> 32); + } + constexpr uint16_t getTimeMid() const { + return (uint16_t)(high >> 16); + } + constexpr uint16_t getTimeHighAndVersion() const { + return (uint16_t)high; + } + constexpr uint16_t getVariantAndClockSeq() const { + return (uint16_t)(low >> 48); + } + constexpr uint64_t getNode() const { + return low & 0xFFFFFFFFFFFF; + } +}; +struct __attribute__((visibility("default"))) ICast { + virtual ICast* castInterface(const UUID& interfaceUUID) = 0; + + protected: + ~ICast() = default; +}; class __attribute__((visibility("default"))) Buffer { public: virtual ~Buffer(); @@ -10687,9 +10763,10 @@ class __attribute__((visibility("default"))) NativeState { public: virtual ~NativeState(); }; -class __attribute__((visibility("default"))) Runtime { +class __attribute__((visibility("default"))) Runtime : public ICast { public: virtual ~Runtime(); + ICast* castInterface(const UUID& interfaceUUID) override; virtual Value evaluateJavaScript( const std::shared_ptr& buffer, const std::string& sourceURL) = 0; @@ -10704,6 +10781,8 @@ class __attribute__((visibility("default"))) Runtime { virtual std::string description() = 0; virtual bool isInspectable() = 0; virtual Instrumentation& instrumentation(); + void setRuntimeData(const UUID& uuid, const std::shared_ptr& data); + std::shared_ptr getRuntimeData(const UUID& uuid); protected: friend @@ -10719,6 +10798,11 @@ class __attribute__((visibility("default"))) Runtime { friend friend friend + virtual void setRuntimeDataImpl( + const UUID& uuid, + const void* data, + void (*deleter)(const void* data)); + virtual const void* getRuntimeDataImpl(const UUID& uuid); struct PointerValue { virtual void invalidate() noexcept = 0; @@ -10736,6 +10820,9 @@ class __attribute__((visibility("default"))) Runtime { virtual PropNameID createPropNameIDFromUtf8( const uint8_t* utf8, size_t length) = 0; + virtual PropNameID createPropNameIDFromUtf16( + const char16_t* utf16, + size_t length); virtual PropNameID createPropNameIDFromString(const String& str) = 0; virtual PropNameID createPropNameIDFromSymbol(const Symbol& sym) = 0; virtual std::string utf8(const PropNameID&) = 0; @@ -10749,6 +10836,7 @@ class __attribute__((visibility("default"))) Runtime { virtual String bigintToString(const BigInt&, int) = 0; virtual String createStringFromAscii(const char* str, size_t length) = 0; virtual String createStringFromUtf8(const uint8_t* utf8, size_t length) = 0; + virtual String createStringFromUtf16(const char16_t* utf16, size_t length); virtual std::string utf8(const String&) = 0; virtual Value createValueFromJsonUtf8(const uint8_t* json, size_t length); virtual Object createObject() = 0; @@ -10869,6 +10957,13 @@ class __attribute__((visibility("default"))) PropNameID : public Pointer { return runtime.createPropNameIDFromUtf8( reinterpret_cast(utf8.data()), utf8.size()); } + static PropNameID + forUtf16(Runtime& runtime, const char16_t* utf16, size_t length) { + return runtime.createPropNameIDFromUtf16(utf16, length); + } + static PropNameID forUtf16(Runtime& runtime, const std::u16string& str) { + return runtime.createPropNameIDFromUtf16(str.data(), str.size()); + } static PropNameID forString(Runtime& runtime, const jsi::String& str) { return runtime.createPropNameIDFromString(str); } @@ -10967,6 +11062,13 @@ class __attribute__((visibility("default"))) String : public Pointer { return runtime.createStringFromUtf8( reinterpret_cast(utf8.data()), utf8.length()); } + static String + createFromUtf16(Runtime& runtime, const char16_t* utf16, size_t length) { + return runtime.createStringFromUtf16(utf16, length); + } + static String createFromUtf16(Runtime& runtime, const std::u16string& utf16) { + return runtime.createStringFromUtf16(utf16.data(), utf16.length()); + } static bool strictEquals(Runtime& runtime, const String& a, const String& b) { return runtime.strictEquals(a, b); } @@ -11394,6 +11496,22 @@ class __attribute__((visibility("default"))) JSError : public JSIException { return *value_; } }; +template +U* castInterface(T* ptr) { + if (ptr) { + return static_cast(ptr->castInterface(U::uuid)); + } + return nullptr; +}; +template +std::shared_ptr dynamicInterfaceCast(T&& ptr) { + auto* p = ptr->castInterface(U::uuid); + U* res = static_cast(p); + if (res) { + return std::shared_ptr(std::forward(ptr), res); + } + return nullptr; +} } // namespace jsi } // namespace facebook @@ -11437,7 +11555,7 @@ class SourceJavaScriptPreparation final : public jsi::PreparedJavaScript, /// @src {packages/react-native/ReactCommon/jsi/jsi/test/testlib.h}: namespace facebook { namespace jsi { -using RuntimeFactory = std::function()>; +using RuntimeFactory = std::function()>; std::vector runtimeGenerators(); class JSITestBase : public ::testing::TestWithParam { public: @@ -11454,7 +11572,7 @@ class JSITestBase : public ::testing::TestWithParam { .getBool(); } RuntimeFactory factory; - std::unique_ptr runtime; + std::shared_ptr runtime; Runtime& rt; }; } // namespace jsi @@ -11507,7 +11625,6 @@ class ThreadSafeRuntimeImpl final } // namespace facebook /// @src {packages/react-native/ReactCommon/jsiexecutor/jsireact/JSIExecutor.h}: -/// @dep {packages/react-native/ReactCommon/jsiexecutor/jsireact/JSINativeModules.h} namespace facebook::react { using JSIScopedTimeoutInvoker = std::function& invokee, @@ -11643,45 +11760,6 @@ inline std::string base64Encode(const std::string_view s) { } } // namespace facebook::react::jsinspector_modern -/// @src {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h}: -namespace facebook::react::jsinspector_modern::cdp { -using RequestId = long long; -enum class ErrorCode { - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603 -}; -struct PreparsedRequest { - public: - RequestId id{}; - std::string method; - folly::dynamic params; - inline bool operator==(const PreparsedRequest& rhs) const { - return id == rhs.id && method == rhs.method && params == rhs.params; - } - std::string toJson() const; -}; -PreparsedRequest preparse(std::string_view message); -using TypeError = folly::TypeError; -using ParseError = folly::json::parse_error; -std::string jsonError( - std::optional id, - ErrorCode code, - std::optional message = std::nullopt); -std::string jsonResult( - RequestId id, - const folly::dynamic& result = folly::dynamic::object()); -std::string jsonNotification( - std::string_view method, - std::optional params = std::nullopt); -std::string jsonRequest( - RequestId id, - std::string_view method, - std::optional params = std::nullopt); -} // namespace facebook::react::jsinspector_modern::cdp - /// @src {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h}: /// @dep {packages/react-native/ReactCommon/jsinspector-modern/StackTrace.h} namespace facebook::react::jsinspector_modern { @@ -11799,22 +11877,8 @@ class ExecutionContextManager { /// @src {packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeAgentDelegate.h}: /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -11837,6 +11901,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -11844,6 +11911,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -11861,6 +11932,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -11870,7 +11945,6 @@ class __attribute__((visibility("default"))) RuntimeTarget void emitDebuggerSessionDestroyed(); friend } // namespace facebook::react::jsinspector_modern - namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -11893,6 +11967,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern namespace facebook::react::jsinspector_modern { @@ -11924,22 +12002,7 @@ class FallbackRuntimeAgentDelegate : public RuntimeAgentDelegate { /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} - -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -11962,6 +12025,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -11985,6 +12052,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -11992,6 +12062,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -12009,6 +12083,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -12048,31 +12126,20 @@ class FallbackRuntimeTargetDelegate : public RuntimeTargetDelegate { std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip) override; + void enableSamplingProfiler() override; + void disableSamplingProfiler() override; + tracing::RuntimeSamplingProfile collectSamplingProfile() override; }; } // namespace facebook::react::jsinspector_modern /// @src {packages/react-native/ReactCommon/jsinspector-modern/HostAgent.h}: -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContextManager.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/HostCommand.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -12095,6 +12162,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -12118,6 +12189,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -12125,6 +12199,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -12142,6 +12220,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -12216,7 +12298,7 @@ struct ReadStreamParams { struct NetworkResource { bool success{}; std::optional stream; - std::optional httpStatusCode; + std::optional httpStatusCode; std::optional netErrorName; std::optional headers; folly::dynamic toDynamic() const { @@ -12266,7 +12348,7 @@ class NetworkRequestListener { NetworkRequestListener& operator=(NetworkRequestListener&&) noexcept = default; virtual ~NetworkRequestListener() = default; - virtual void onHeaders(int httpStatusCode, const Headers& headers) = 0; + virtual void onHeaders(uint32_t httpStatusCode, const Headers& headers) = 0; virtual void onData(std::string_view data) = 0; virtual void onError(const std::string& message) = 0; virtual void onCompletion() = 0; @@ -12385,18 +12467,10 @@ class __attribute__((visibility("default"))) HostTarget folly::dynamic createHostMetadataPayload(const HostTargetMetadata& metadata); } // namespace facebook::react::jsinspector_modern namespace facebook::react::jsinspector_modern { -class TracingAgent { - public: - explicit TracingAgent(FrontendChannel frontendChannel) - : frontendChannel_(std::move(frontendChannel)) {} - bool handleRequest(const cdp::PreparsedRequest& req); -}; -} // namespace facebook::react::jsinspector_modern -namespace facebook::react::jsinspector_modern { class HostAgent final { public: HostAgent( - FrontendChannel frontendChannel, + const FrontendChannel& frontendChannel, HostTargetController& targetController, HostTargetMetadata hostMetadata, SessionState& sessionState, @@ -12408,22 +12482,6 @@ class HostAgent final { ~HostAgent(); void handleRequest(const cdp::PreparsedRequest& req); void setCurrentInstanceAgent(std::shared_ptr agent); -}; - void sendInfoLogEntry( - std::string_view text, - std::initializer_list args = {}); - void sendFuseboxNotice(); - void sendNonFuseboxNotice(); - void sendConsoleMessage(SimpleConsoleMessage message); - FrontendChannel frontendChannel_; - HostTargetController& targetController_; - const HostTargetMetadata hostMetadata_; - std::shared_ptr instanceAgent_; - FuseboxClientType fuseboxClientType_{FuseboxClientType::Unknown}; - bool isPausedInDebuggerOverlayVisible_{false}; - SessionState& sessionState_; - NetworkIOAgent networkIOAgent_; - TracingAgent tracingAgent_; }; } // namespace facebook::react::jsinspector_modern @@ -12439,22 +12497,7 @@ enum class HostCommand { DebuggerResume, DebuggerStepOver }; /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} - -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -12477,6 +12520,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -12500,6 +12547,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -12507,6 +12557,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -12524,6 +12578,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -12598,7 +12656,7 @@ struct ReadStreamParams { struct NetworkResource { bool success{}; std::optional stream; - std::optional httpStatusCode; + std::optional httpStatusCode; std::optional netErrorName; std::optional headers; folly::dynamic toDynamic() const { @@ -12648,7 +12706,7 @@ class NetworkRequestListener { NetworkRequestListener& operator=(NetworkRequestListener&&) noexcept = default; virtual ~NetworkRequestListener() = default; - virtual void onHeaders(int httpStatusCode, const Headers& headers) = 0; + virtual void onHeaders(uint32_t httpStatusCode, const Headers& headers) = 0; virtual void onData(std::string_view data) = 0; virtual void onError(const std::string& message) = 0; virtual void onCompletion() = 0; @@ -12774,6 +12832,8 @@ class InspectorFlags { static InspectorFlags& getInstance(); bool getFuseboxEnabled() const; bool getIsProfilingBuild() const; + bool getNetworkInspectionEnabled() const; + void dangerouslyDisableFuseboxForTest(); void dangerouslyResetFlags(); }; InspectorFlags() = default; @@ -12782,6 +12842,7 @@ class InspectorFlags { ~InspectorFlags() = default; mutable std::optional cachedValues_; mutable bool inconsistentFlagsStateLogged_{false}; + bool fuseboxDisabledForTest_{false}; const Values& loadFlagsAndAssertUnchanged() const; }; } // namespace facebook::react::jsinspector_modern @@ -12932,6 +12993,7 @@ class InspectorPackagerConnection::Impl virtual void didFailWithError(std::optional posixCode, std::string error) override; virtual void didReceiveMessage(std::string_view message) override; + virtual void didOpen() override; virtual void didClose() override; virtual void onPageRemoved(int pageId) override; const std::string url_; @@ -12940,6 +13002,7 @@ class InspectorPackagerConnection::Impl const std::unique_ptr delegate_; std::unordered_map inspectorSessions_; std::unique_ptr webSocket_; + bool connected_{false}; bool closed_{false}; bool suppressConnectionErrors_{false}; bool reconnectPending_{false}; @@ -12979,24 +13042,10 @@ class NullRemoteConnection : public IRemoteConnection { } // namespace facebook::react::jsinspector_modern /// @src {packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h}: -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -13019,6 +13068,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -13042,6 +13095,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -13049,6 +13105,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -13066,6 +13126,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -13098,6 +13162,9 @@ class InstanceAgent final { bool handleRequest(const cdp::PreparsedRequest& req); void setCurrentRuntime(RuntimeTarget* runtime); void sendConsoleMessage(SimpleConsoleMessage message); + void startTracing(); + void stopTracing(); + tracing::InstanceTracingProfile collectTracingProfile(); }; } // namespace facebook::react::jsinspector_modern @@ -13106,22 +13173,7 @@ class InstanceAgent final { /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} - -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -13144,6 +13196,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -13167,6 +13223,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -13174,6 +13233,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -13191,6 +13254,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -13249,7 +13316,6 @@ class InstanceTarget : public EnableExecutorFromThis { } // namespace facebook::react::jsinspector_modern /// @src {packages/react-native/ReactCommon/jsinspector-modern/NetworkIOAgent.h}: -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} namespace facebook::react::jsinspector_modern { @@ -13270,7 +13336,7 @@ struct ReadStreamParams { struct NetworkResource { bool success{}; std::optional stream; - std::optional httpStatusCode; + std::optional httpStatusCode; std::optional netErrorName; std::optional headers; folly::dynamic toDynamic() const { @@ -13320,7 +13386,7 @@ class NetworkRequestListener { NetworkRequestListener& operator=(NetworkRequestListener&&) noexcept = default; virtual ~NetworkRequestListener() = default; - virtual void onHeaders(int httpStatusCode, const Headers& headers) = 0; + virtual void onHeaders(uint32_t httpStatusCode, const Headers& headers) = 0; virtual void onData(std::string_view data) = 0; virtual void onError(const std::string& message) = 0; virtual void onCompletion() = 0; @@ -13362,22 +13428,8 @@ class NetworkIOAgent { /// @src {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h}: -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -13401,6 +13453,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -13408,6 +13463,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -13425,6 +13484,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -13434,7 +13497,6 @@ class __attribute__((visibility("default"))) RuntimeTarget void emitDebuggerSessionDestroyed(); friend } // namespace facebook::react::jsinspector_modern - namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -13457,12 +13519,14 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @src {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h}: -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} - namespace facebook::react::jsinspector_modern { class RuntimeAgentDelegate { public: @@ -13482,22 +13546,7 @@ class RuntimeAgentDelegate { /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} - -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -13520,6 +13569,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -13543,6 +13596,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -13550,6 +13606,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -13567,6 +13627,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -13630,22 +13694,8 @@ class EnableExecutorFromThis : public std::enable_shared_from_this { /// @src {packages/react-native/ReactCommon/jsinspector-modern/SessionState.h}: /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} -namespace facebook::react::jsinspector_modern { -class RuntimeAgentDelegate { - public: - class ExportedState { - public: - virtual ~ExportedState() = default; - }; - virtual ~RuntimeAgentDelegate() = default; - virtual bool handleRequest(const cdp::PreparsedRequest& req) = 0; - inline virtual std::unique_ptr getExportedState() { - return std::make_unique(); - } -}; -} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} @@ -13668,6 +13718,9 @@ class RuntimeTargetDelegate { virtual std::unique_ptr captureStackTrace( jsi::Runtime& runtime, size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; }; class RuntimeTargetController { public: @@ -13675,6 +13728,10 @@ class RuntimeTargetController { void installBindingHandler(const std::string& bindingName); void notifyDebuggerSessionCreated(); void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; class __attribute__((visibility("default"))) RuntimeTarget : public EnableExecutorFromThis { @@ -13692,6 +13749,10 @@ class __attribute__((visibility("default"))) RuntimeTarget std::shared_ptr createAgent( FrontendChannel channel, SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; void installBindingHandler(const std::string& bindingName); void installGlobals(); @@ -13701,7 +13762,6 @@ class __attribute__((visibility("default"))) RuntimeTarget void emitDebuggerSessionDestroyed(); friend } // namespace facebook::react::jsinspector_modern - namespace facebook::react::jsinspector_modern { class RuntimeAgent final { public: @@ -13724,6 +13784,10 @@ class RuntimeAgent final { std::unique_ptr delegateState; }; ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); }; } // namespace facebook::react::jsinspector_modern namespace facebook::react::jsinspector_modern { @@ -13757,15 +13821,139 @@ class StackTrace { } // namespace facebook::react::jsinspector_modern /// @src {packages/react-native/ReactCommon/jsinspector-modern/TracingAgent.h}: -/// @dep {packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h} /// @dep {packages/react-native/ReactCommon/jsinspector-modern/InspectorInterfaces.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/ExecutionContext.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h} +namespace facebook::react::jsinspector_modern { +class RuntimeAgent final { + public: + RuntimeAgent( + FrontendChannel frontendChannel, + RuntimeTargetController& targetController, + const ExecutionContextDescription& executionContextDescription, + SessionState& sessionState, + std::unique_ptr delegate); + ~RuntimeAgent(); + bool handleRequest(const cdp::PreparsedRequest& req); + inline const ExecutionContextDescription& getExecutionContextDescription() + const { + return executionContextDescription_; + } + void notifyBindingCalled( + const std::string& bindingName, + const std::string& payload); + struct ExportedState { + std::unique_ptr delegateState; + }; + ExportedState getExportedState(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); +}; +} // namespace facebook::react::jsinspector_modern +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/ScopedExecutor.h} + +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/WeakList.h} +namespace facebook::react::jsinspector_modern { +class RuntimeTargetDelegate { + public: + virtual ~RuntimeTargetDelegate() = default; + virtual std::unique_ptr createAgentDelegate( + FrontendChannel channel, + SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) = 0; + virtual void addConsoleMessage( + jsi::Runtime& runtime, + ConsoleMessage message) = 0; + virtual bool supportsConsole() const = 0; + virtual std::unique_ptr captureStackTrace( + jsi::Runtime& runtime, + size_t framesToSkip = 0) = 0; + virtual void enableSamplingProfiler() = 0; + virtual void disableSamplingProfiler() = 0; + virtual tracing::RuntimeSamplingProfile collectSamplingProfile() = 0; +}; +class RuntimeTargetController { + public: + explicit RuntimeTargetController(RuntimeTarget& target); + void installBindingHandler(const std::string& bindingName); + void notifyDebuggerSessionCreated(); + void notifyDebuggerSessionDestroyed(); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); +}; +class __attribute__((visibility("default"))) RuntimeTarget + : public EnableExecutorFromThis { + public: + static std::shared_ptr create( + const ExecutionContextDescription& executionContextDescription, + RuntimeTargetDelegate& delegate, + RuntimeExecutor jsExecutor, + VoidExecutor selfExecutor); + RuntimeTarget(const RuntimeTarget&) = delete; + RuntimeTarget(RuntimeTarget&&) = delete; + RuntimeTarget& operator=(const RuntimeTarget&) = delete; + RuntimeTarget& operator=(RuntimeTarget&&) = delete; + ~RuntimeTarget(); + std::shared_ptr createAgent( + FrontendChannel channel, + SessionState& sessionState); + void registerForTracing(); + void enableSamplingProfiler(); + void disableSamplingProfiler(); + tracing::RuntimeSamplingProfile collectSamplingProfile(); +}; + void installBindingHandler(const std::string& bindingName); + void installGlobals(); + void installConsoleHandler(); + void installDebuggerSessionObserver(); + void emitDebuggerSessionCreated(); + void emitDebuggerSessionDestroyed(); + friend +} // namespace facebook::react::jsinspector_modern +namespace facebook::react::jsinspector_modern { +struct SessionState { + public: + bool isDebuggerDomainEnabled{false}; + bool isLogDomainEnabled{false}; + bool isReactNativeApplicationDomainEnabled{false}; + bool isRuntimeDomainEnabled{false}; + std::unordered_map + subscribedBindings; + std::vector pendingSimpleConsoleMessages; + RuntimeAgent::ExportedState lastRuntimeAgentExportedState; +}; +} // namespace facebook::react::jsinspector_modern +namespace facebook::react::jsinspector_modern { +class InstanceAgent final { + public: + explicit InstanceAgent( + FrontendChannel frontendChannel, + InstanceTarget& target, + SessionState& sessionState); + bool handleRequest(const cdp::PreparsedRequest& req); + void setCurrentRuntime(RuntimeTarget* runtime); + void sendConsoleMessage(SimpleConsoleMessage message); + void startTracing(); + void stopTracing(); + tracing::InstanceTracingProfile collectTracingProfile(); +}; +} // namespace facebook::react::jsinspector_modern namespace facebook::react::jsinspector_modern { class TracingAgent { public: explicit TracingAgent(FrontendChannel frontendChannel) : frontendChannel_(std::move(frontendChannel)) {} bool handleRequest(const cdp::PreparsedRequest& req); + void setCurrentInstanceAgent(std::shared_ptr agent); }; } // namespace facebook::react::jsinspector_modern @@ -13872,10 +14060,167 @@ class IWebSocketDelegate { std::optional posixCode, std::string error) = 0; virtual void didReceiveMessage(std::string_view message) = 0; + virtual void didOpen() = 0; virtual void didClose() = 0; }; } // namespace facebook::react::jsinspector_modern +/// @src {packages/react-native/ReactCommon/jsinspector-modern/cdp/CdpJson.h}: +namespace facebook::react::jsinspector_modern::cdp { +using RequestId = long long; +enum class ErrorCode { + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603 +}; +struct PreparsedRequest { + public: + RequestId id{}; + std::string method; + folly::dynamic params; + inline bool operator==(const PreparsedRequest& rhs) const { + return id == rhs.id && method == rhs.method && params == rhs.params; + } + std::string toJson() const; +}; +PreparsedRequest preparse(std::string_view message); +using TypeError = folly::TypeError; +using ParseError = folly::json::parse_error; +std::string jsonError( + std::optional id, + ErrorCode code, + std::optional message = std::nullopt); +std::string jsonResult( + RequestId id, + const folly::dynamic& result = folly::dynamic::object()); +std::string jsonNotification( + std::string_view method, + std::optional params = std::nullopt); +std::string jsonRequest( + RequestId id, + std::string_view method, + std::optional params = std::nullopt); +} // namespace facebook::react::jsinspector_modern::cdp + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/network/CdpNetwork.h}: +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/network/NetworkTypes.h} +namespace facebook::react::jsinspector_modern::cdp::network { +struct Request { + std::string url; + std::string method; + std::optional headers; + std::optional postData; + static Request fromInputParams(const RequestInfo& requestInfo); + folly::dynamic toDynamic() const; +}; +struct Response { + std::string url; + uint16_t status; + std::string statusText; + std::optional headers; + std::string mimeType; + int encodedDataLength; + static Response fromInputParams( + const ResponseInfo& responseInfo, + int encodedDataLength); + folly::dynamic toDynamic() const; +}; +struct RequestWillBeSentParams { + std::string requestId; + std::string loaderId; + std::string documentURL; + Request request; + double timestamp; + double wallTime; + folly::dynamic initiator; + bool redirectHasExtraInfo; + std::optional redirectResponse; + folly::dynamic toDynamic() const; +}; +struct ResponseReceivedParams { + std::string requestId; + std::string loaderId; + double timestamp; + std::string type; + Response response; + bool hasExtraInfo; + folly::dynamic toDynamic() const; +}; +struct LoadingFinishedParams { + std::string requestId; + double timestamp; + int encodedDataLength; + folly::dynamic toDynamic() const; +}; +std::string resourceTypeFromMimeType(const std::string& mimeType); +} // namespace facebook::react::jsinspector_modern::cdp::network + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/network/HttpUtils.h}: +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/network/NetworkTypes.h} +namespace facebook::react::jsinspector_modern { +std::string httpReasonPhrase(uint16_t status); +std::string mimeTypeFromHeaders(const Headers& headers); +} // namespace facebook::react::jsinspector_modern + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/network/NetworkReporter.h}: +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/network/NetworkTypes.h} +namespace facebook::react::jsinspector_modern { +using FrontendChannel = std::function; +struct ResourceTimingData { + std::string url; + HighResTimeStamp fetchStart; + HighResTimeStamp requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; + std::optional responseStatus; +}; +class NetworkReporter { + public: + static NetworkReporter& getInstance(); + void setFrontendChannel(FrontendChannel frontendChannel); + bool enableDebugging(); + bool disableDebugging(); + void reportRequestStart( + const std::string& requestId, + const RequestInfo& requestInfo, + int encodedDataLength, + const std::optional& redirectResponse); + void reportConnectionTiming(const std::string& requestId); + void reportRequestFailed(const std::string& requestId) const; + void reportResponseStart( + const std::string& requestId, + const ResponseInfo& responseInfo, + int encodedDataLength); + void reportDataReceived(const std::string& requestId); + void reportResponseEnd(const std::string& requestId, int encodedDataLength); +}; + inline bool isDebuggingEnabledNoSync() const { + return debuggingEnabled_.load(std::memory_order_relaxed); + } + std::unordered_map perfTimingsBuffer_{}; + std::mutex perfTimingsMutex_; +}; +} // namespace facebook::react::jsinspector_modern + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/network/NetworkTypes.h}: +namespace facebook::react::jsinspector_modern { +using Headers = std::map; +struct RequestInfo { + std::string url; + std::string httpMethod; + std::optional headers; + std::optional httpBody; +}; +struct ResponseInfo { + std::string url; + uint16_t statusCode; + std::optional headers; +}; +} // namespace facebook::react::jsinspector_modern + /// @src {packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h}: /// @dep {packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h} namespace facebook::react::jsinspector_modern { @@ -13905,8 +14250,8 @@ class JsiIntegrationTestHermesEngineAdapter { /// @src {packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h}: namespace facebook::react::jsinspector_modern { struct InspectorFlagOverrides { - std::optional fuseboxEnabledDebug; - std::optional isProfilingBuild; + std::optional fuseboxEnabledRelease; + std::optional networkInspectionEnabled; }; class InspectorFlagOverridesGuard { public: @@ -13928,40 +14273,492 @@ struct DevToolsTrackEntryPayload { }; } // namespace facebook::react::jsinspector_modern +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/EventLoopReporter.h}: +namespace facebook::react::jsinspector_modern::tracing { +enum class EventLoopPhase { + Task, + Microtasks, +}; +struct EventLoopReporter { + public: + explicit EventLoopReporter(EventLoopPhase phase); + EventLoopReporter(const EventLoopReporter&) = delete; + EventLoopReporter(EventLoopReporter&&) = delete; + EventLoopReporter& operator=(const EventLoopReporter&) = delete; + EventLoopReporter& operator=(EventLoopReporter&&) = delete; + ~EventLoopReporter(); +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/InstanceTracingProfile.h}: +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/RuntimeSamplingProfile.h} + +namespace facebook::react::jsinspector_modern::tracing { +struct InstanceTracingProfile { + public: + explicit InstanceTracingProfile(RuntimeSamplingProfile runtimeSamplingProfile) + : runtimeSamplingProfile_(std::move(runtimeSamplingProfile)) {} + const RuntimeSamplingProfile& getRuntimeSamplingProfile() const { + return runtimeSamplingProfile_; + } +}; +} // namespace facebook::react::jsinspector_modern::tracing + /// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/PerformanceTracer.h}: /// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/CdpTracing.h} -namespace facebook::react::jsinspector_modern { -namespace { -struct TraceEvent { - std::string name; - std::string cat; - char ph; - uint64_t ts; - uint64_t pid; - uint64_t tid; - folly::dynamic args = folly::dynamic::object(); - std::optional dur; -}; -} // namespace +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceEvent.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceEventProfile.h} +namespace facebook::react::jsinspector_modern::tracing { class PerformanceTracer { public: static PerformanceTracer& getInstance(); bool startTracing(); - bool stopTracingAndCollectEvents( + bool stopTracing(); + bool isTracing() const { + return tracing_; + } + void collectEvents( const std::function& - resultCallback); - void reportMark(const std::string_view& name, uint64_t start); + resultCallback, + uint16_t chunkSize); + void reportMark(const std::string_view& name, HighResTimeStamp start); void reportMeasure( const std::string_view& name, - uint64_t start, - uint64_t duration, + HighResTimeStamp start, + HighResDuration duration, const std::optional& trackMetadata); + void reportProcess(uint64_t id, const std::string& name); + void reportThread(uint64_t id, const std::string& name); + void reportJavaScriptThread(); + void reportEventLoopTask(HighResTimeStamp start, HighResTimeStamp end); + void reportEventLoopMicrotasks(HighResTimeStamp start, HighResTimeStamp end); + folly::dynamic getSerializedRuntimeProfileTraceEvent( + uint64_t threadId, + uint16_t profileId, + HighResTimeStamp profileTimestamp); + folly::dynamic getSerializedRuntimeProfileChunkTraceEvent( + uint16_t profileId, + uint64_t threadId, + HighResTimeStamp chunkTimestamp, + const TraceEventProfileChunk& traceEventProfileChunk); +}; + uint64_t processId_; + uint32_t performanceMeasureCount_{0}; + std::vector buffer_; + std::mutex mutex_; +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/ProfileTreeNode.h}: +namespace facebook::react::jsinspector_modern::tracing { +class ProfileTreeNode { + public: + enum class CodeType { + JavaScript, + Other, + }; + static constexpr uint32_t NO_PARENT = UINT32_MAX; + ProfileTreeNode( + uint32_t id, + CodeType codeType, + RuntimeSamplingProfile::SampleCallStackFrame callFrame, + uint32_t parentId = NO_PARENT) + : id_(id), + codeType_(codeType), + parentId_(parentId), + callFrame_(std::move(callFrame)) {} + uint32_t getId() const { + return id_; + } + CodeType getCodeType() const { + return codeType_; + } + inline bool hasParent() const { + return parentId_ != NO_PARENT; + } + uint32_t getParentId() const { + return parentId_; + } + const RuntimeSamplingProfile::SampleCallStackFrame& getCallFrame() const { + return callFrame_; + } + ProfileTreeNode* getIfAlreadyExists( + CodeType childCodeType, + const RuntimeSamplingProfile::SampleCallStackFrame& childCallFrame) { + for (auto& existingChild : children_) { + if (existingChild.getCodeType() == childCodeType && + existingChild.getCallFrame() == childCallFrame) { + return &existingChild; + } + } + return nullptr; + } + ProfileTreeNode* addChild( + uint32_t childId, + CodeType childCodeType, + RuntimeSamplingProfile::SampleCallStackFrame childCallFrame) { + return &children_.emplace_back( + childId, childCodeType, std::move(childCallFrame), id_); + } +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/RuntimeSamplingProfile.h}: +namespace facebook::react::jsinspector_modern::tracing { +class RawRuntimeProfile { + public: + virtual ~RawRuntimeProfile() = default; }; - std::unordered_map customTrackIdMap_; +struct RuntimeSamplingProfile { + public: + struct SampleCallStackFrame { + enum class Kind { + JSFunction, + NativeFunction, + HostFunction, + GarbageCollector, + }; + + public: + SampleCallStackFrame( + const Kind kind, + const uint32_t scriptId, + std::string_view functionName, + std::optional url = std::nullopt, + const std::optional& lineNumber = std::nullopt, + const std::optional& columnNumber = std::nullopt) + : kind_(kind), + scriptId_(scriptId), + functionName_(std::move(functionName)), + url_(std::move(url)), + lineNumber_(lineNumber), + columnNumber_(columnNumber) {} + Kind getKind() const { + return kind_; + } + uint32_t getScriptId() const { + return scriptId_; + } + std::string_view getFunctionName() const { + return functionName_; + } + bool hasUrl() const { + return url_.has_value(); + } + std::string_view getUrl() const { + return url_.value(); + } + bool hasLineNumber() const { + return lineNumber_.has_value(); + } + uint32_t getLineNumber() const { + return lineNumber_.value(); + } + bool hasColumnNumber() const { + return columnNumber_.has_value(); + } + uint32_t getColumnNumber() const { + return columnNumber_.value(); + } + inline bool operator==(const SampleCallStackFrame& rhs) const noexcept { + return kind_ == rhs.kind_ && scriptId_ == rhs.scriptId_ && + functionName_ == rhs.functionName_ && url_ == rhs.url_ && + lineNumber_ == rhs.lineNumber_ && columnNumber_ == rhs.columnNumber_; + } + + private: + Kind kind_; + uint32_t scriptId_; + std::string_view functionName_; + std::optional url_; + std::optional lineNumber_; + std::optional columnNumber_; + }; + struct Sample { + public: + Sample( + uint64_t timestamp, + uint64_t threadId, + std::vector callStack) + : timestamp_(timestamp), + threadId_(threadId), + callStack_(std::move(callStack)) {} + Sample& operator=(Sample&&) = default; + Sample(Sample&&) = default; + Sample(const Sample&) = delete; + Sample& operator=(const Sample&) = delete; + uint64_t getTimestamp() const { + return timestamp_; + } + uint64_t getThreadId() const { + return threadId_; + } + const std::vector& getCallStack() const { + return callStack_; + } + + private: + uint64_t timestamp_; + uint64_t threadId_; + std::vector callStack_; + }; + RuntimeSamplingProfile( + std::string runtimeName, + std::vector samples, + std::unique_ptr rawRuntimeProfile) + : runtimeName_(std::move(runtimeName)), + samples_(std::move(samples)), + rawRuntimeProfile_(std::move(rawRuntimeProfile)) {} + RuntimeSamplingProfile& operator=(RuntimeSamplingProfile&&) = default; + RuntimeSamplingProfile(RuntimeSamplingProfile&&) = default; + RuntimeSamplingProfile(const RuntimeSamplingProfile&) = delete; + RuntimeSamplingProfile& operator=(const RuntimeSamplingProfile&) = delete; + const std::string& getRuntimeName() const { + return runtimeName_; + } + const std::vector& getSamples() const { + return samples_; + } +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/RuntimeSamplingProfileTraceEventSerializer.h}: +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/CdpTracing.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceEvent.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceEventProfile.h} +namespace facebook::react::jsinspector_modern::tracing { +class PerformanceTracer { + public: + static PerformanceTracer& getInstance(); + bool startTracing(); + bool stopTracing(); + bool isTracing() const { + return tracing_; + } + void collectEvents( + const std::function& + resultCallback, + uint16_t chunkSize); + void reportMark(const std::string_view& name, HighResTimeStamp start); + void reportMeasure( + const std::string_view& name, + HighResTimeStamp start, + HighResDuration duration, + const std::optional& trackMetadata); + void reportProcess(uint64_t id, const std::string& name); + void reportThread(uint64_t id, const std::string& name); + void reportJavaScriptThread(); + void reportEventLoopTask(HighResTimeStamp start, HighResTimeStamp end); + void reportEventLoopMicrotasks(HighResTimeStamp start, HighResTimeStamp end); + folly::dynamic getSerializedRuntimeProfileTraceEvent( + uint64_t threadId, + uint16_t profileId, + HighResTimeStamp profileTimestamp); + folly::dynamic getSerializedRuntimeProfileChunkTraceEvent( + uint16_t profileId, + uint64_t threadId, + HighResTimeStamp chunkTimestamp, + const TraceEventProfileChunk& traceEventProfileChunk); +}; + uint64_t processId_; + uint32_t performanceMeasureCount_{0}; std::vector buffer_; std::mutex mutex_; }; -} // namespace facebook::react::jsinspector_modern +} // namespace facebook::react::jsinspector_modern::tracing +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/ProfileTreeNode.h} +/// @dep {packages/react-native/ReactCommon/jsinspector-modern/tracing/RuntimeSamplingProfile.h} +namespace facebook::react::jsinspector_modern::tracing { +namespace { +struct NodeIdGenerator { + public: + uint32_t getNext() { + return ++counter_; + } +}; +} // namespace +class RuntimeSamplingProfileTraceEventSerializer { + struct ProfileChunk { + ProfileChunk( + uint16_t chunkSize, + uint64_t chunkThreadId, + HighResTimeStamp chunkTimestamp) + : size(chunkSize), threadId(chunkThreadId), timestamp(chunkTimestamp) { + samples.reserve(size); + timeDeltas.reserve(size); + } + bool isFull() const { + return samples.size() == size; + } + bool isEmpty() const { + return samples.empty(); + } + std::vector nodes; + std::vector samples; + std::vector timeDeltas; + uint16_t size; + uint64_t threadId; + HighResTimeStamp timestamp; + }; + + public: + RuntimeSamplingProfileTraceEventSerializer( + PerformanceTracer& performanceTracer, + std::function + notificationCallback, + uint16_t traceEventChunkSize, + uint16_t profileChunkSize = 10) + : performanceTracer_(performanceTracer), + notificationCallback_(std::move(notificationCallback)), + traceEventChunkSize_(traceEventChunkSize), + profileChunkSize_(profileChunkSize) { + traceEventBuffer_ = folly::dynamic::array(); + traceEventBuffer_.reserve(traceEventChunkSize); + } + void serializeAndNotify( + const RuntimeSamplingProfile& profile, + HighResTimeStamp tracingStartTime); +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/Timing.h}: +namespace facebook::react::jsinspector_modern::tracing { +constexpr HighResTimeStamp TRACING_TIME_ORIGIN = + HighResTimeStamp::fromChronoSteadyClockTimePoint( + std::chrono::steady_clock::time_point()); +inline uint64_t highResTimeStampToTracingClockTimeStamp( + HighResTimeStamp timestamp) { + assert( + timestamp >= TRACING_TIME_ORIGIN && + "Provided timestamp is before time origin"); + auto duration = timestamp - TRACING_TIME_ORIGIN; + return static_cast( + static_cast(duration.toNanoseconds()) / 1e3); +} +inline int64_t highResDurationToTracingClockDuration(HighResDuration duration) { + return static_cast( + static_cast(duration.toNanoseconds()) / 1e3); +} +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceEvent.h}: +namespace facebook::react::jsinspector_modern::tracing { +struct TraceEvent { + std::optional id; + std::string name; + std::string cat; + char ph; + HighResTimeStamp ts; + uint64_t pid; + uint64_t tid; + folly::dynamic args = folly::dynamic::object(); + std::optional dur; +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsinspector-modern/tracing/TraceEventProfile.h}: +namespace facebook::react::jsinspector_modern::tracing { +struct TraceEventProfileChunk { + struct TimeDeltas { + folly::dynamic toDynamic() const { + auto value = folly::dynamic::array(); + value.reserve(deltas.size()); + for (const auto& delta : deltas) { + value.push_back(highResDurationToTracingClockDuration(delta)); + } + return value; + } + std::vector deltas; + }; + struct CPUProfile { + struct Node { + struct CallFrame { + folly::dynamic toDynamic() const { + folly::dynamic dynamicCallFrame = folly::dynamic::object(); + dynamicCallFrame["codeType"] = codeType; + dynamicCallFrame["scriptId"] = scriptId; + dynamicCallFrame["functionName"] = functionName; + if (url.has_value()) { + dynamicCallFrame["url"] = url.value(); + } + if (lineNumber.has_value()) { + dynamicCallFrame["lineNumber"] = lineNumber.value(); + } + if (columnNumber.has_value()) { + dynamicCallFrame["columnNumber"] = columnNumber.value(); + } + return dynamicCallFrame; + } + std::string codeType; + uint32_t scriptId; + std::string functionName; + std::optional url; + std::optional lineNumber; + std::optional columnNumber; + }; + folly::dynamic toDynamic() const { + folly::dynamic dynamicNode = folly::dynamic::object(); + dynamicNode["callFrame"] = callFrame.toDynamic(); + dynamicNode["id"] = id; + if (parentId.has_value()) { + dynamicNode["parent"] = parentId.value(); + } + return dynamicNode; + } + uint32_t id; + CallFrame callFrame; + std::optional parentId; + }; + folly::dynamic toDynamic() const { + folly::dynamic dynamicNodes = folly::dynamic::array(); + dynamicNodes.reserve(nodes.size()); + for (const auto& node : nodes) { + dynamicNodes.push_back(node.toDynamic()); + } + folly::dynamic dynamicSamples = + folly::dynamic::array(samples.begin(), samples.end()); + return folly::dynamic::object("nodes", dynamicNodes)( + "samples", dynamicSamples); + } + std::vector nodes; + std::vector samples; + }; + folly::dynamic toDynamic() const { + return folly::dynamic::object("cpuProfile", cpuProfile.toDynamic())( + "timeDeltas", timeDeltas.toDynamic()); + } + CPUProfile cpuProfile; + TimeDeltas timeDeltas; +}; +} // namespace facebook::react::jsinspector_modern::tracing + +/// @src {packages/react-native/ReactCommon/jsitooling/react/runtime/JSRuntimeFactory.h}: +namespace facebook::react { +class JSRuntime { + public: + virtual jsi::Runtime& getRuntime() noexcept = 0; + virtual ~JSRuntime() = default; + virtual jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate(); + virtual void unstable_initializeOnJsThread() {} +}; +class JSRuntimeFactory { + public: + virtual std::unique_ptr createJSRuntime( + std::shared_ptr msgQueueThread) noexcept = 0; + virtual ~JSRuntimeFactory() = default; +}; +class JSIRuntimeHolder : public JSRuntime { + public: + jsi::Runtime& getRuntime() noexcept override; + explicit JSIRuntimeHolder(std::unique_ptr runtime); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/jsitooling/react/runtime/JSRuntimeFactoryCAPI.h}: +extern "C" { +typedef void* JSRuntimeFactoryRef; +void js_runtime_factory_destroy(JSRuntimeFactoryRef factory); +} /// @src {packages/react-native/ReactCommon/logger/react_native_log.h}: enum ReactNativeLogLevel { @@ -13981,6 +14778,12 @@ void _react_native_log(ReactNativeLogLevel level, const char* text); void _react_native_log_default(ReactNativeLogLevel level, const char* text); } +/// @src {packages/react-native/ReactCommon/oscompat/OSCompat.h}: +namespace facebook::react::oscompat { +uint64_t getCurrentProcessId(); +uint64_t getCurrentThreadId(); +} // namespace facebook::react::oscompat + /// @src {packages/react-native/ReactCommon/react/bridging/AString.h}: namespace facebook::react { template <> @@ -14115,13 +14918,13 @@ struct Bridging { namespace bridging { namespace detail { template -template -struct function_wrapper { - using type = std::function; +template +struct function_wrapper { + using type = std::function; }; -template -struct function_wrapper { - using type = std::function; +template +struct function_wrapper { + using type = std::function; }; template struct bridging_wrapper { @@ -14135,33 +14938,42 @@ struct bridging_wrapper< } // namespace detail template using bridging_t = typename detail::bridging_wrapper::type; -template , int> = 0> -auto fromJs(jsi::Runtime& rt, T&& value, const std::shared_ptr&) - -> decltype(static_cast( - std::move(convert(rt, std::forward(value))))) { - return static_cast(std::move(convert(rt, std::forward(value)))); -} -template -auto fromJs(jsi::Runtime& rt, T&& value, const std::shared_ptr&) - -> decltype(Bridging>::fromJs( +template + requires is_jsi_v +auto fromJs( + jsi::Runtime& rt, + JSArgT&& value, + const std::shared_ptr&) + -> decltype(static_cast( + std::move(convert(rt, std::forward(value))))) { + return static_cast( + std::move(convert(rt, std::forward(value)))); +} +template +auto fromJs( + jsi::Runtime& rt, + JSArgT&& value, + const std::shared_ptr&) + -> decltype(Bridging>::fromJs( rt, - convert(rt, std::forward(value)))) { - return Bridging>::fromJs( - rt, convert(rt, std::forward(value))); + convert(rt, std::forward(value)))) { + return Bridging>::fromJs( + rt, convert(rt, std::forward(value))); } -template +template auto fromJs( jsi::Runtime& rt, - T&& value, + JSArgT&& value, const std::shared_ptr& jsInvoker) - -> decltype(Bridging>::fromJs( + -> decltype(Bridging>::fromJs( rt, - convert(rt, std::forward(value)), + convert(rt, std::forward(value)), jsInvoker)) { - return Bridging>::fromJs( - rt, convert(rt, std::forward(value)), jsInvoker); + return Bridging>::fromJs( + rt, convert(rt, std::forward(value)), jsInvoker); } -template , int> = 0> +template + requires is_jsi_v auto toJs( jsi::Runtime& rt, T&& value, @@ -14207,32 +15019,32 @@ inline constexpr bool supportsFromJs< nullptr))>> = true; template inline constexpr bool supportsToJs = false; -template +template inline constexpr bool supportsToJs< - T, - Ret, + JSReturnT, + ReturnT, std::void_t(), - std::declval(), + std::declval(), nullptr))>> = std::is_convertible_v< decltype(toJs( std::declval(), - std::declval(), + std::declval(), nullptr)), - Ret>; -template + ReturnT>; +template inline constexpr bool supportsToJs< - T, + ReturnT, jsi::Value, std::void_t(), - std::declval(), + std::declval(), nullptr))>> = std::is_convertible_v< decltype(toJs( std::declval(), - std::declval(), + std::declval(), nullptr)), jsi::Value>; } // namespace bridging @@ -14245,7 +15057,7 @@ struct Bridging { static bool fromJs(jsi::Runtime&, const jsi::Value& value) { return value.asBool(); } - static jsi::Value toJs(jsi::Runtime&, bool value) { + static bool toJs(jsi::Runtime&, bool value) { return value; } }; @@ -14287,48 +15099,51 @@ class CallbackWrapper : public LongLivedObject { public: /// @src {packages/react-native/ReactCommon/react/bridging/Class.h}: namespace facebook::react::bridging { template < - typename T, - typename C, - typename R, - typename... Args, - typename... JSArgs> -T callFromJs( + typename JSReturnT, + typename ClassT, + typename ReturnT, + typename... ArgsT, + typename... JSArgsT> +JSReturnT callFromJs( jsi::Runtime& rt, - R (C::*method)(jsi::Runtime&, Args...), + ReturnT (ClassT::*method)(jsi::Runtime&, ArgsT...), const std::shared_ptr& jsInvoker, - C* instance, - JSArgs&&... args) { + ClassT* instance, + JSArgsT&&... args) { static_assert( - sizeof...(Args) == sizeof...(JSArgs), "Incorrect arguments length"); + sizeof...(ArgsT) == sizeof...(JSArgsT), "Incorrect arguments length"); static_assert( - (supportsFromJs && ...), "Incompatible arguments"); - if constexpr (std::is_void_v) { + (supportsFromJs && ...), "Incompatible arguments"); + if constexpr (std::is_void_v) { (instance->*method)( - rt, fromJs(rt, std::forward(args), jsInvoker)...); - } else if constexpr (std::is_void_v) { + rt, fromJs(rt, std::forward(args), jsInvoker)...); + } else if constexpr (std::is_void_v) { static_assert( - std::is_same_v, + std::is_same_v, "Void functions may only return undefined"); (instance->*method)( - rt, fromJs(rt, std::forward(args), jsInvoker)...); + rt, fromJs(rt, std::forward(args), jsInvoker)...); return jsi::Value(); - } else if constexpr (is_jsi_v) { - static_assert(supportsToJs, "Incompatible return type"); + } else if constexpr ( + is_jsi_v || supportsToJs) { + static_assert(supportsToJs, "Incompatible return type"); return toJs( rt, (instance->*method)( - rt, fromJs(rt, std::forward(args), jsInvoker)...), + rt, fromJs(rt, std::forward(args), jsInvoker)...), jsInvoker); - } else if constexpr (is_optional_jsi_v) { + } else if constexpr (is_optional_jsi_v) { static_assert( - is_optional_v - ? supportsToJs - : supportsToJs, + is_optional_v + ? supportsToJs< + typename ReturnT::value_type, + typename JSReturnT::value_type> + : supportsToJs, "Incompatible return type"); auto result = toJs( rt, (instance->*method)( - rt, fromJs(rt, std::forward(args), jsInvoker)...), + rt, fromJs(rt, std::forward(args), jsInvoker)...), jsInvoker); if constexpr (std::is_same_v) { if (result.isNull() || result.isUndefined()) { @@ -14337,18 +15152,19 @@ T callFromJs( } return convert(rt, std::move(result)); } else { - static_assert(std::is_convertible_v, "Incompatible return type"); + static_assert( + std::is_convertible_v, "Incompatible return type"); return (instance->*method)( - rt, fromJs(rt, std::forward(args), jsInvoker)...); + rt, fromJs(rt, std::forward(args), jsInvoker)...); } } -template -constexpr size_t getParameterCount(R (*)(Args...)) { - return sizeof...(Args); +template +constexpr size_t getParameterCount(ReturnT (*)(ArgsT...)) { + return sizeof...(ArgsT); } -template -constexpr size_t getParameterCount(R (C::*)(Args...)) { - return sizeof...(Args); +template +constexpr size_t getParameterCount(ReturnT (Class::*)(ArgsT...)) { + return sizeof...(ArgsT); } } // namespace facebook::react::bridging @@ -14800,6 +15616,28 @@ template struct Bridging : Bridging> {}; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/bridging/HighResTimeStamp.h}: +namespace facebook::react { +template <> +struct Bridging { + static HighResTimeStamp fromJs(jsi::Runtime&, const jsi::Value& jsiValue) { + return HighResTimeStamp::fromDOMHighResTimeStamp(jsiValue.asNumber()); + } + static double toJs(jsi::Runtime&, const HighResTimeStamp& value) { + return value.toDOMHighResTimeStamp(); + } +}; +template <> +struct Bridging { + static HighResDuration fromJs(jsi::Runtime&, const jsi::Value& jsiValue) { + return HighResDuration::fromDOMHighResTimeStamp(jsiValue.asNumber()); + } + static double toJs(jsi::Runtime&, const HighResDuration& value) { + return value.toDOMHighResTimeStamp(); + } +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/bridging/LongLivedObject.h}: namespace facebook::react { class LongLivedObject { @@ -14831,7 +15669,7 @@ struct Bridging { static double fromJs(jsi::Runtime&, const jsi::Value& value) { return value.asNumber(); } - static jsi::Value toJs(jsi::Runtime&, double value) { + static double toJs(jsi::Runtime&, double value) { return value; } }; @@ -14840,8 +15678,8 @@ struct Bridging { static float fromJs(jsi::Runtime&, const jsi::Value& value) { return (float)value.asNumber(); } - static jsi::Value toJs(jsi::Runtime&, float value) { - return (double)value; + static float toJs(jsi::Runtime&, float value) { + return value; } }; template <> @@ -14849,7 +15687,7 @@ struct Bridging { static int32_t fromJs(jsi::Runtime&, const jsi::Value& value) { return (int32_t)value.asNumber(); } - static jsi::Value toJs(jsi::Runtime&, int32_t value) { + static int32_t toJs(jsi::Runtime&, int32_t value) { return value; } }; @@ -14859,7 +15697,7 @@ struct Bridging { return (uint32_t)value.asNumber(); } static jsi::Value toJs(jsi::Runtime&, uint32_t value) { - return (double)value; + return double(value); } }; } // namespace facebook::react @@ -15390,6 +16228,17 @@ class RAIICallbackWrapperDestroyer { }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleWithJSIBindings.h}: +namespace facebook::react { +class TurboModuleWithJSIBindings { + public: + virtual ~TurboModuleWithJSIBindings() = default; + static void installJSIBindings( + const std::shared_ptr& cxxModule, + jsi::Runtime& runtime); +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaInteropTurboModule.h}: /// @dep {packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h} @@ -15443,7 +16292,12 @@ class JSI_EXPORT JavaTurboModule : public TurboModule { const jsi::Value* args, size_t argCount, jmethodID& cachedMethodID); - void setEventEmitterCallback(jni::alias_ref instance); + + protected: + void configureEventEmitterCallback(); + [[deprecated]] void setEventEmitterCallback(jni::alias_ref) { + configureEventEmitterCallback(); + } }; } // namespace facebook::react @@ -15488,7 +16342,11 @@ namespace facebook::react { using EventEmitterCallback = std::function; namespace TurboModuleConvertUtils { jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value); -id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker); +id convertJSIValueToObjCObject( + jsi::Runtime &runtime, + const jsi::Value &value, + const std::shared_ptr &jsInvoker, + BOOL useNSNull = NO); } // namespace TurboModuleConvertUtils template <> struct Bridging { @@ -15542,9 +16400,11 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { facebook::react::EventEmitterCallback _eventEmitterCallback; } @end -@protocol RCTTurboModule +@protocol RCTModuleProvider - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params; +@end +@protocol RCTTurboModule @optional - (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; @end @@ -15559,7 +16419,11 @@ namespace facebook::react { using EventEmitterCallback = std::function; namespace TurboModuleConvertUtils { jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value); -id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr jsInvoker); +id convertJSIValueToObjCObject( + jsi::Runtime &runtime, + const jsi::Value &value, + const std::shared_ptr &jsInvoker, + BOOL useNSNull = NO); } // namespace TurboModuleConvertUtils template <> struct Bridging { @@ -15635,7 +16499,7 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { NSInvocation *inv, NSMutableArray *retainedObjectsForInvocation); using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper); - jsi::Value createPromise(jsi::Runtime &runtime, std::string methodName, PromiseInvocationBlock invoke); + jsi::Value createPromise(jsi::Runtime &runtime, const std::string &methodName, PromiseInvocationBlock invoke); }; } // namespace facebook::react @interface EventEmitterCallbackWrapper : NSObject { @@ -15643,9 +16507,11 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { facebook::react::EventEmitterCallback _eventEmitterCallback; } @end -@protocol RCTTurboModule +@protocol RCTModuleProvider - (std::shared_ptr)getTurboModule: (const facebook::react::ObjCTurboModule::InitParams &)params; +@end +@protocol RCTTurboModule @optional - (void)setEventEmitterCallback:(EventEmitterCallbackWrapper *)eventEmitterCallbackWrapper; @end @@ -15658,6 +16524,7 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { - (Class)getModuleClassFromName:(const char *)name; - (id)getModuleInstanceFromClass:(Class)moduleClass; @optional +- (id)getModuleProvider:(const char *)name; - (std::shared_ptr)getTurboModule:(const std::string &)name jsInvoker: (std::shared_ptr)jsInvoker; @@ -15685,6 +16552,30 @@ class JSI_EXPORT ObjCTurboModule : public TurboModule { __attribute__((deprecated("Use 'installJSIBindingsWithRuntime:callInvoker:' instead"))); @end +/// @src {packages/react-native/ReactCommon/react/nativemodule/cputime/CPUTime.h}: +namespace facebook::react { +inline double getCPUTimeNanos() { + auto now = std::chrono::steady_clock::now(); + return static_cast( + std::chrono::duration_cast( + now.time_since_epoch()) + .count()); +} +inline bool hasAccurateCPUTimeNanosForBenchmarks() { + return false; +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/nativemodule/cputime/NativeCPUTime.h}: +namespace facebook::react { +class NativeCPUTime : public NativeCPUTimeCxxSpec { + public: + explicit NativeCPUTime(std::shared_ptr jsInvoker); + double getCPUTimeNanos(jsi::Runtime& runtime); + bool hasAccurateCPUTimeNanosForBenchmarks(jsi::Runtime& runtime); +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.h}: namespace facebook::react { struct DefaultTurboModules { @@ -15713,116 +16604,159 @@ namespace facebook::react { class NativeDOM : public NativeDOMCxxSpec { public: NativeDOM(std::shared_ptr jsInvoker); - jsi::Value getParentNode(jsi::Runtime& rt, jsi::Value shadowNodeValue); + double compareDocumentPosition( + jsi::Runtime& rt, + jsi::Value nativeNodeReference, + jsi::Value otherNativeNodeReference); std::vector getChildNodes( jsi::Runtime& rt, - jsi::Value shadowNodeValue); - bool isConnected(jsi::Runtime& rt, jsi::Value shadowNodeValue); - double compareDocumentPosition( + jsi::Value nativeNodeReference); + jsi::Value getParentNode(jsi::Runtime& rt, jsi::Value nativeNodeReference); + bool isConnected(jsi::Runtime& rt, jsi::Value nativeNodeReference); + std::tuple getBorderWidth( jsi::Runtime& rt, - jsi::Value shadowNodeValue, - jsi::Value otherShadowNodeValue); - std::string getTextContent(jsi::Runtime& rt, jsi::Value shadowNodeValue); + ShadowNode::Shared shadowNode); std::tuple getBoundingClientRect( jsi::Runtime& rt, - jsi::Value shadowNodeValue, + ShadowNode::Shared shadowNode, bool includeTransform); - std::tuple getOffset( + std::tuple getInnerSize( jsi::Runtime& rt, - jsi::Value shadowNodeValue); + ShadowNode::Shared shadowNode); std::tuple getScrollPosition( jsi::Runtime& rt, - jsi::Value shadowNodeValue); + ShadowNode::Shared shadowNode); std::tuple getScrollSize( jsi::Runtime& rt, - jsi::Value shadowNodeValue); - std::tuple getInnerSize( - jsi::Runtime& rt, - jsi::Value shadowNodeValue); - std::tuple getBorderWidth( - jsi::Runtime& rt, - jsi::Value shadowNodeValue); - std::string getTagName(jsi::Runtime& rt, jsi::Value shadowNodeValue); + ShadowNode::Shared shadowNode); + std::string getTagName(jsi::Runtime& rt, ShadowNode::Shared shadowNode); + std::string getTextContent(jsi::Runtime& rt, ShadowNode::Shared shadowNode); bool hasPointerCapture( jsi::Runtime& rt, - jsi::Value shadowNodeValue, + ShadowNode::Shared shadowNode, double pointerId); - void setPointerCapture( + void releasePointerCapture( jsi::Runtime& rt, - jsi::Value shadowNodeValue, + ShadowNode::Shared shadowNode, double pointerId); - void releasePointerCapture( + void setPointerCapture( jsi::Runtime& rt, - jsi::Value shadowNodeValue, + ShadowNode::Shared shadowNode, double pointerId); - void - measure(jsi::Runtime& rt, jsi::Value shadowNodeValue, jsi::Function callback); + std::tuple getOffset( + jsi::Runtime& rt, + ShadowNode::Shared shadowNode); + jsi::Value linkRootNode( + jsi::Runtime& rt, + SurfaceId surfaceId, + jsi::Value instanceHandle); + void measure( + jsi::Runtime& rt, + ShadowNode::Shared shadowNode, + jsi::Function callback); void measureInWindow( jsi::Runtime& rt, - jsi::Value shadowNodeValue, + ShadowNode::Shared shadowNode, jsi::Function callback); void measureLayout( jsi::Runtime& rt, - jsi::Value shadowNodeValue, - jsi::Value relativeToShadowNodeValue, + ShadowNode::Shared shadowNode, + ShadowNode::Shared relativeToShadowNode, jsi::Function onFail, jsi::Function onSuccess); + void setNativeProps( + jsi::Runtime& rt, + ShadowNode::Shared shadowNode, + jsi::Value updatePayload); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/nativemodule/fantomtestspecificmethods/NativeFantomTestSpecificMethods.h}: +namespace facebook::react { +class NativeFantomTestSpecificMethods + : public NativeFantomTestSpecificMethodsCxxSpec< + NativeFantomTestSpecificMethods> { + public: + explicit NativeFantomTestSpecificMethods( + std::shared_ptr jsInvoker); + void registerForcedCloneCommitHook(jsi::Runtime& runtime); +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/nativemodule/fantomtestspecificmethods/internal/FantomForcedCloneCommitHook.h}: +namespace facebook::react { +struct FantomForcedCloneCommitHook : public UIManagerCommitHook { + void commitHookWasRegistered(const UIManager&) noexcept override; + void commitHookWasUnregistered(const UIManager&) noexcept override; + RootShadowNode::Unshared shadowTreeWillCommit( + const ShadowTree& shadowTree, + const RootShadowNode::Shared& oldRootShadowNode, + const RootShadowNode::Unshared& newRootShadowNode) noexcept override; }; } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h}: namespace facebook::react { class NativeReactNativeFeatureFlags - : public NativeReactNativeFeatureFlagsCxxSpec< - NativeReactNativeFeatureFlags> { + : public NativeReactNativeFeatureFlagsCxxSpecJSI { public: NativeReactNativeFeatureFlags(std::shared_ptr jsInvoker); + static constexpr std::string_view kModuleName = + "NativeReactNativeFeatureFlagsCxx"; bool commonTestFlag(jsi::Runtime& runtime); bool commonTestFlagWithoutNativeImplementation(jsi::Runtime& runtime); - bool completeReactInstanceCreationOnBgThreadOnAndroid(jsi::Runtime& runtime); - bool disableEventLoopOnBridgeless(jsi::Runtime& runtime); + bool animatedShouldSignalBatch(jsi::Runtime& runtime); + bool cxxNativeAnimatedEnabled(jsi::Runtime& runtime); + bool disableMainQueueSyncDispatchIOS(jsi::Runtime& runtime); bool disableMountItemReorderingAndroid(jsi::Runtime& runtime); + bool disableTextLayoutManagerCacheAndroid(jsi::Runtime& runtime); + bool enableAccessibilityOrder(jsi::Runtime& runtime); bool enableAccumulatedUpdatesInRawPropsAndroid(jsi::Runtime& runtime); - bool enableAlignItemsBaselineOnFabricIOS(jsi::Runtime& runtime); - bool enableAndroidLineHeightCentering(jsi::Runtime& runtime); bool enableBridgelessArchitecture(jsi::Runtime& runtime); bool enableCppPropsIteratorSetter(jsi::Runtime& runtime); - bool enableDeletionOfUnmountedViews(jsi::Runtime& runtime); + bool enableCustomFocusSearchOnClippedElementsAndroid(jsi::Runtime& runtime); + bool enableDestroyShadowTreeRevisionAsync(jsi::Runtime& runtime); + bool enableDoubleMeasurementFixAndroid(jsi::Runtime& runtime); bool enableEagerRootViewAttachment(jsi::Runtime& runtime); - bool enableEventEmitterRetentionDuringGesturesOnAndroid( - jsi::Runtime& runtime); bool enableFabricLogs(jsi::Runtime& runtime); bool enableFabricRenderer(jsi::Runtime& runtime); - bool enableFixForViewCommandRace(jsi::Runtime& runtime); - bool enableGranularShadowTreeStateReconciliation(jsi::Runtime& runtime); + bool enableFixForParentTagDuringReparenting(jsi::Runtime& runtime); + bool enableFontScaleChangesUpdatingLayout(jsi::Runtime& runtime); + bool enableIOSTextBaselineOffsetPerLine(jsi::Runtime& runtime); bool enableIOSViewClipToPaddingBox(jsi::Runtime& runtime); - bool enableImagePrefetchingAndroid(jsi::Runtime& runtime); + bool enableIntersectionObserverEventLoopIntegration(jsi::Runtime& runtime); bool enableLayoutAnimationsOnAndroid(jsi::Runtime& runtime); bool enableLayoutAnimationsOnIOS(jsi::Runtime& runtime); + bool enableMainQueueCoordinatorOnIOS(jsi::Runtime& runtime); + bool enableMainQueueModulesOnIOS(jsi::Runtime& runtime); + bool enableModuleArgumentNSNullConversionIOS(jsi::Runtime& runtime); + bool enableNativeCSSParsing(jsi::Runtime& runtime); + bool enableNetworkEventReporting(jsi::Runtime& runtime); bool enableNewBackgroundAndBorderDrawables(jsi::Runtime& runtime); + bool enablePreparedTextLayout(jsi::Runtime& runtime); bool enablePropsUpdateReconciliationAndroid(jsi::Runtime& runtime); + bool enableResourceTimingAPI(jsi::Runtime& runtime); bool enableSynchronousStateUpdates(jsi::Runtime& runtime); + bool enableViewCulling(jsi::Runtime& runtime); bool enableViewRecycling(jsi::Runtime& runtime); - bool excludeYogaFromRawProps(jsi::Runtime& runtime); - bool fixDifferentiatorEmittingUpdatesWithWrongParentTag( - jsi::Runtime& runtime); + bool enableViewRecyclingForText(jsi::Runtime& runtime); + bool enableViewRecyclingForView(jsi::Runtime& runtime); + bool enableVirtualViewDebugFeatures(jsi::Runtime& runtime); bool fixMappingOfEventPrioritiesBetweenFabricAndReact(jsi::Runtime& runtime); - bool fuseboxEnabledDebug(jsi::Runtime& runtime); bool fuseboxEnabledRelease(jsi::Runtime& runtime); - bool initEagerTurboModulesOnNativeModulesQueueAndroid(jsi::Runtime& runtime); - bool lazyAnimationCallbacks(jsi::Runtime& runtime); - bool loadVectorDrawablesOnImages(jsi::Runtime& runtime); + bool fuseboxNetworkInspectionEnabled(jsi::Runtime& runtime); bool traceTurboModulePromiseRejectionsOnAndroid(jsi::Runtime& runtime); + bool updateRuntimeShadowNodeReferencesOnCommit(jsi::Runtime& runtime); bool useAlwaysAvailableJSErrorHandling(jsi::Runtime& runtime); bool useFabricInterop(jsi::Runtime& runtime); - bool useImmediateExecutorInAndroidBridgeless(jsi::Runtime& runtime); bool useNativeViewConfigsInBridgelessMode(jsi::Runtime& runtime); - bool useOptimisedViewPreallocationOnAndroid(jsi::Runtime& runtime); bool useOptimizedEventBatchingOnAndroid(jsi::Runtime& runtime); bool useRawPropsJsiValue(jsi::Runtime& runtime); - bool useRuntimeShadowNodeReferenceUpdate(jsi::Runtime& runtime); + bool useShadowNodeStateOnClone(jsi::Runtime& runtime); bool useTurboModuleInterop(jsi::Runtime& runtime); bool useTurboModules(jsi::Runtime& runtime); + double virtualViewPrerenderRatio(jsi::Runtime& runtime); }; } // namespace facebook::react @@ -15830,7 +16764,8 @@ class NativeReactNativeFeatureFlags namespace facebook::react { using CallbackHandle = jsi::Object; using NativeRequestIdleCallbackOptions = - NativeIdleCallbacksRequestIdleCallbackOptions>; + NativeIdleCallbacksRequestIdleCallbackOptions< + std::optional>; template <> struct Bridging : NativeIdleCallbacksRequestIdleCallbackOptionsBridging< @@ -15854,7 +16789,8 @@ using RectAsTuple = std::tuple; using NativeIntersectionObserverObserveOptions = NativeIntersectionObserverNativeIntersectionObserverObserveOptions< NativeIntersectionObserverIntersectionObserverId, - jsi::Object, + std::optional, + ShadowNode::Shared, std::vector, std::optional>>; template <> @@ -15867,9 +16803,9 @@ using NativeIntersectionObserverEntry = jsi::Value, RectAsTuple, RectAsTuple, - std::optional, + RectAsTuple, bool, - double>; + HighResTimeStamp>; template <> struct Bridging : NativeIntersectionObserverNativeIntersectionObserverEntryBridging< @@ -15878,13 +16814,22 @@ class NativeIntersectionObserver : public NativeIntersectionObserverCxxSpec { public: NativeIntersectionObserver(std::shared_ptr jsInvoker); + [[deprecated("Please use observeV2")]] void observe( jsi::Runtime& runtime, NativeIntersectionObserverObserveOptions options); + [[deprecated("Please use unobserveV2")]] void unobserve( jsi::Runtime& runtime, IntersectionObserverObserverId intersectionObserverId, - jsi::Object targetShadowNode); + ShadowNode::Shared targetShadowNode); + jsi::Object observeV2( + jsi::Runtime& runtime, + NativeIntersectionObserverObserveOptions options); + void unobserveV2( + jsi::Runtime& runtime, + IntersectionObserverObserverId intersectionObserverId, + jsi::Object targetToken); void connect( jsi::Runtime& runtime, AsyncCallback<> notifyIntersectionObserversCallback); @@ -15894,7 +16839,7 @@ class NativeIntersectionObserver }; static UIManager& getUIManagerFromRuntime(jsi::Runtime& runtime); static NativeIntersectionObserverEntry convertToNativeModuleEntry( - IntersectionObserverEntry entry, + const IntersectionObserverEntry& entry, jsi::Runtime& runtime); }; } // namespace facebook::react @@ -15913,7 +16858,7 @@ namespace facebook::react { using NativeMutationObserverObserveOptions = NativeMutationObserverNativeMutationObserverObserveOptions< MutationObserverId, - jsi::Object, + ShadowNode::Shared, bool>; template <> struct Bridging @@ -15935,10 +16880,9 @@ class NativeMutationObserver void observe( jsi::Runtime& runtime, NativeMutationObserverObserveOptions options); - void unobserve( + void unobserveAll( jsi::Runtime& runtime, - MutationObserverId mutationObserverId, - jsi::Object targetShadowNode); + MutationObserverId mutationObserverId); void connect( jsi::Runtime& runtime, jsi::Function notifyMutationObservers, @@ -16086,19 +17030,35 @@ using NativePerformancePerformanceObserverObserveOptions = std::optional>, std::optional, std::optional, - std::optional>; + std::optional>; template <> struct Bridging { static PerformanceEntryType fromJs(jsi::Runtime&, const jsi::Value& value) { return static_cast(value.asNumber()); } - static jsi::Value toJs(jsi::Runtime&, const PerformanceEntryType& value) { - return {static_cast(value)}; + static int toJs(jsi::Runtime&, const PerformanceEntryType& value) { + return static_cast(value); } }; +struct NativePerformanceEntry { + std::string name; + PerformanceEntryType entryType; + HighResTimeStamp startTime; + HighResDuration duration; + std::optional processingStart; + std::optional processingEnd; + std::optional interactionId; + std::optional fetchStart; + std::optional requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; + std::optional responseEnd; + std::optional responseStatus; +}; template <> -struct Bridging - : NativePerformanceRawPerformanceEntryBridging {}; +struct Bridging + : NativePerformanceRawPerformanceEntryBridging {}; template <> struct Bridging : NativePerformancePerformanceObserverInitBridging< @@ -16106,17 +17066,17 @@ struct Bridging class NativePerformance : public NativePerformanceCxxSpec { public: NativePerformance(std::shared_ptr jsInvoker); - double now(jsi::Runtime& rt); - double markWithResult( + HighResTimeStamp now(jsi::Runtime& rt); + HighResTimeStamp markWithResult( jsi::Runtime& rt, std::string name, - std::optional startTime); - std::tuple measureWithResult( + std::optional startTime); + std::tuple measureWithResult( jsi::Runtime& rt, std::string name, - double startTime, - double endTime, - std::optional duration, + HighResTimeStamp startTime, + HighResTimeStamp endTime, + std::optional duration, std::optional startMark, std::optional endMark); void clearMarks( @@ -16125,11 +17085,11 @@ class NativePerformance : public NativePerformanceCxxSpec { void clearMeasures( jsi::Runtime& rt, std::optional entryName = std::nullopt); - std::vector getEntries(jsi::Runtime& rt); - std::vector getEntriesByType( + std::vector getEntries(jsi::Runtime& rt); + std::vector getEntriesByType( jsi::Runtime& rt, PerformanceEntryType entryType); - std::vector getEntriesByName( + std::vector getEntriesByName( jsi::Runtime& rt, std::string entryName, std::optional entryType = std::nullopt); @@ -16142,7 +17102,7 @@ class NativePerformance : public NativePerformanceCxxSpec { jsi::Object observer, NativePerformancePerformanceObserverObserveOptions options); void disconnect(jsi::Runtime& rt, jsi::Object observer); - std::vector + std::vector takeRecords(jsi::Runtime& rt, jsi::Object observerObj, bool sort); std::vector getSupportedPerformanceEntryTypes( jsi::Runtime& rt); @@ -16155,8 +17115,6 @@ class NativePerformance : public NativePerformanceCxxSpec { } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/performance/timeline/CircularBuffer.h}: -/// @dep {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h} - namespace facebook::react { template class CircularBuffer { @@ -16238,26 +17196,59 @@ enum class PerformanceEntryType { MEASURE = 2, EVENT = 3, LONGTASK = 4, - _NEXT = 5, + RESOURCE = 5, + _NEXT = 6, }; -struct PerformanceEntry { +struct AbstractPerformanceEntry { std::string name; - PerformanceEntryType entryType; - DOMHighResTimeStamp startTime; - DOMHighResTimeStamp duration = 0; - std::optional processingStart; - std::optional processingEnd; - std::optional interactionId; -}; -constexpr size_t NUM_PERFORMANCE_ENTRY_TYPES = - (size_t)PerformanceEntryType::_NEXT - 1; + HighResTimeStamp startTime; + HighResDuration duration = HighResDuration::zero(); +}; +struct PerformanceMark : AbstractPerformanceEntry { + static constexpr PerformanceEntryType entryType = PerformanceEntryType::MARK; +}; +struct PerformanceMeasure : AbstractPerformanceEntry { + static constexpr PerformanceEntryType entryType = + PerformanceEntryType::MEASURE; +}; +struct PerformanceEventTiming : AbstractPerformanceEntry { + static constexpr PerformanceEntryType entryType = PerformanceEntryType::EVENT; + HighResTimeStamp processingStart; + HighResTimeStamp processingEnd; + PerformanceEntryInteractionId interactionId; +}; +struct PerformanceLongTaskTiming : AbstractPerformanceEntry { + static constexpr PerformanceEntryType entryType = + PerformanceEntryType::LONGTASK; +}; +struct PerformanceResourceTiming : AbstractPerformanceEntry { + static constexpr PerformanceEntryType entryType = + PerformanceEntryType::RESOURCE; + HighResTimeStamp fetchStart; + HighResTimeStamp requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; + std::optional responseEnd; + std::optional responseStatus; +}; +using PerformanceEntry = std::variant< + PerformanceMark, + PerformanceMeasure, + PerformanceEventTiming, + PerformanceLongTaskTiming, + PerformanceResourceTiming>; struct PerformanceEntrySorter { bool operator()(const PerformanceEntry& lhs, const PerformanceEntry& rhs) { - if (lhs.startTime != rhs.startTime) { - return lhs.startTime < rhs.startTime; - } else { - return lhs.duration < rhs.duration; - } + return std::visit( + [](const auto& left, const auto& right) { + if (left.startTime != right.startTime) { + return left.startTime < right.startTime; + } + return left.duration < right.duration; + }, + lhs, + rhs); } }; } // namespace facebook::react @@ -16266,10 +17257,10 @@ struct PerformanceEntrySorter { /// @dep {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h} namespace facebook::react { -constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; +constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); class PerformanceEntryBuffer { public: - double durationThreshold{DEFAULT_DURATION_THRESHOLD}; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; size_t droppedEntriesCount{0}; explicit PerformanceEntryBuffer() = default; virtual ~PerformanceEntryBuffer() = default; @@ -16285,11 +17276,13 @@ class PerformanceEntryBuffer { /// @src {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryCircularBuffer.h}: /// @dep {packages/react-native/ReactCommon/react/performance/timeline/CircularBuffer.h} +/// @dep {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h} + namespace facebook::react { -constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; +constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); class PerformanceEntryBuffer { public: - double durationThreshold{DEFAULT_DURATION_THRESHOLD}; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; size_t droppedEntriesCount{0}; explicit PerformanceEntryBuffer() = default; virtual ~PerformanceEntryBuffer() = default; @@ -16322,10 +17315,10 @@ class PerformanceEntryCircularBuffer : public PerformanceEntryBuffer { /// @dep {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h} namespace facebook::react { -constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; +constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); class PerformanceEntryBuffer { public: - double durationThreshold{DEFAULT_DURATION_THRESHOLD}; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; size_t droppedEntriesCount{0}; explicit PerformanceEntryBuffer() = default; virtual ~PerformanceEntryBuffer() = default; @@ -16357,11 +17350,13 @@ class PerformanceEntryKeyedBuffer : public PerformanceEntryBuffer { /// @src {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h}: /// @dep {packages/react-native/ReactCommon/react/performance/timeline/CircularBuffer.h} +/// @dep {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h} + namespace facebook::react { -constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; +constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); class PerformanceEntryBuffer { public: - double durationThreshold{DEFAULT_DURATION_THRESHOLD}; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; size_t droppedEntriesCount{0}; explicit PerformanceEntryBuffer() = default; virtual ~PerformanceEntryBuffer() = default; @@ -16416,7 +17411,9 @@ class PerformanceObserverRegistry { namespace facebook::react { constexpr size_t EVENT_BUFFER_SIZE = 150; constexpr size_t LONG_TASK_BUFFER_SIZE = 200; -constexpr DOMHighResTimeStamp LONG_TASK_DURATION_THRESHOLD_MS = 50.0; +constexpr size_t RESOURCE_TIMING_BUFFER_SIZE = 250; +constexpr HighResDuration LONG_TASK_DURATION_THRESHOLD = + HighResDuration::fromMilliseconds(50); class PerformanceEntryReporter { public: PerformanceEntryReporter(); @@ -16443,8 +17440,8 @@ class PerformanceEntryReporter { void clearEntries( PerformanceEntryType entryType, const std::string& entryName); - DOMHighResTimeStamp getCurrentTimeStamp() const; - void setTimeStampProvider(std::function provider) { + HighResTimeStamp getCurrentTimeStamp() const; + void setTimeStampProvider(std::function provider) { timeStampProvider_ = std::move(provider); } static std::vector getSupportedEntryTypes(); @@ -16452,33 +17449,42 @@ class PerformanceEntryReporter { const std::unordered_map& getEventCounts() const { return eventCounts_; } - PerformanceEntry reportMark( + std::optional getMarkTime( + const std::string& markName) const; + PerformanceMark reportMark( const std::string& name, - const std::optional& startTime = std::nullopt); - PerformanceEntry reportMeasure( - const std::string_view& name, - double startTime, - double endTime, - const std::optional& duration = std::nullopt, - const std::optional& startMark = std::nullopt, - const std::optional& endMark = std::nullopt, + const std::optional& startTime = std::nullopt); + PerformanceMeasure reportMeasure( + const std::string& name, + HighResTimeStamp startTime, + HighResTimeStamp endTime, const std::optional& trackMetadata = std::nullopt); void reportEvent( std::string name, - double startTime, - double duration, - double processingStart, - double processingEnd, + HighResTimeStamp startTime, + HighResDuration duration, + HighResTimeStamp processingStart, + HighResTimeStamp processingEnd, uint32_t interactionId); - void reportLongTask(double startTime, double duration); + void reportLongTask(HighResTimeStamp startTime, HighResDuration duration); + PerformanceResourceTiming reportResourceTiming( + const std::string& url, + HighResTimeStamp fetchStart, + HighResTimeStamp requestStart, + std::optional connectStart, + std::optional connectEnd, + HighResTimeStamp responseStart, + HighResTimeStamp responseEnd, + const std::optional& responseStatus); }; PerformanceEntryCircularBuffer longTaskBuffer_{LONG_TASK_BUFFER_SIZE}; + PerformanceEntryCircularBuffer resourceTimingBuffer_{ + RESOURCE_TIMING_BUFFER_SIZE}; PerformanceEntryKeyedBuffer markBuffer_; PerformanceEntryKeyedBuffer measureBuffer_; std::unordered_map eventCounts_; - std::function timeStampProvider_ = nullptr; - double getMarkTime(const std::string& markName) const; + std::function timeStampProvider_ = nullptr; const inline PerformanceEntryBuffer& getBuffer( PerformanceEntryType entryType) const { switch (entryType) { @@ -16490,6 +17496,8 @@ class PerformanceEntryReporter { return measureBuffer_; case PerformanceEntryType::LONGTASK: return longTaskBuffer_; + case PerformanceEntryType::RESOURCE: + return resourceTimingBuffer_; case PerformanceEntryType::_NEXT: throw std::logic_error("Cannot get buffer for _NEXT entry type"); } @@ -16505,11 +17513,15 @@ class PerformanceEntryReporter { return measureBuffer_; case PerformanceEntryType::LONGTASK: return longTaskBuffer_; + case PerformanceEntryType::RESOURCE: + return resourceTimingBuffer_; case PerformanceEntryType::_NEXT: throw std::logic_error("Cannot get buffer for _NEXT entry type"); } throw std::logic_error("Unhandled PerformanceEntryType"); } + void traceMark(const PerformanceMark& entry) const; + void traceMeasure(const PerformanceMeasure& entry) const; }; } // namespace facebook::react @@ -16517,10 +17529,10 @@ class PerformanceEntryReporter { /// @dep {packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h} namespace facebook::react { -constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; +constexpr HighResDuration DEFAULT_DURATION_THRESHOLD = HighResDuration::zero(); class PerformanceEntryBuffer { public: - double durationThreshold{DEFAULT_DURATION_THRESHOLD}; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; size_t droppedEntriesCount{0}; explicit PerformanceEntryBuffer() = default; virtual ~PerformanceEntryBuffer() = default; @@ -16542,17 +17554,16 @@ class PerformanceObserverRegistry { void queuePerformanceEntry(const PerformanceEntry& entry); }; } // namespace facebook::react - namespace facebook::react { using PerformanceObserverEntryTypeFilter = std::unordered_set; using PerformanceObserverCallback = std::function; struct PerformanceObserverObserveMultipleOptions { - double durationThreshold = 0.0; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; }; struct PerformanceObserverObserveSingleOptions { bool buffered = false; - double durationThreshold = 0.0; + HighResDuration durationThreshold = DEFAULT_DURATION_THRESHOLD; }; class PerformanceObserver : public std::enable_shared_from_this {}; @@ -16578,10 +17589,6 @@ class PerformanceObserver void observe(std::unordered_set types); void disconnect() noexcept; uint32_t getDroppedEntriesCount() noexcept; -}; - std::vector buffer_; - bool didScheduleFlushBuffer_ = false; - bool requiresDroppedEntries_ = false; }; inline bool operator==( const PerformanceObserver& lhs, @@ -17032,14 +18039,10 @@ static inline bool shouldFirstComeBeforeSecondMutation( } else { if (lhs.type == ShadowViewMutation::Type::Remove && lhs.parentTag == rhs.parentTag) { - if (lhs.index > rhs.index) { - return true; - } else { - return false; - } + return lhs.index > rhs.index; } } - return false; + return &lhs < &rhs; } std::pair calculateAnimationProgress( uint64_t now, @@ -17061,7 +18064,6 @@ class AttributedString : public Sealable, public DebugStringConvertible { bool isAttachment() const; bool isContentEqual(const Fragment& rhs) const; bool operator==(const Fragment& rhs) const; - bool operator!=(const Fragment& rhs) const; }; class Range { public: @@ -17080,7 +18082,6 @@ class AttributedString : public Sealable, public DebugStringConvertible { bool compareTextAttributesWithoutFrame(const AttributedString& rhs) const; bool isContentEqual(const AttributedString& rhs) const; bool operator==(const AttributedString& rhs) const; - bool operator!=(const AttributedString& rhs) const; }; } // namespace facebook::react namespace std { @@ -17091,7 +18092,7 @@ struct hash { return facebook::react::hash_combine( fragment.string, fragment.textAttributes, - fragment.parentShadowView, + fragment.parentShadowView.tag, fragment.parentShadowView.layoutMetrics); } }; @@ -17100,6 +18101,8 @@ struct hash { size_t operator()( const facebook::react::AttributedString& attributedString) const { auto seed = size_t{0}; + facebook::react::hash_combine( + seed, attributedString.getBaseTextAttributes()); for (const auto& fragment : attributedString.getFragments()) { facebook::react::hash_combine(seed, fragment); } @@ -17155,6 +18158,8 @@ class ParagraphAttributes : public DebugStringConvertible { HyphenationFrequency android_hyphenationFrequency{}; Float minimumFontSize{std::numeric_limits::quiet_NaN()}; Float maximumFontSize{std::numeric_limits::quiet_NaN()}; + Float minimumFontScale{std::numeric_limits::quiet_NaN()}; + std::optional textAlignVertical{}; bool operator==(const ParagraphAttributes&) const; bool operator!=(const ParagraphAttributes&) const; }; @@ -17172,11 +18177,29 @@ struct hash { attributes.minimumFontSize, attributes.maximumFontSize, attributes.includeFontPadding, - attributes.android_hyphenationFrequency); + attributes.android_hyphenationFrequency, + attributes.minimumFontScale, + attributes.textAlignVertical); } }; } // namespace std +/// @src {packages/react-native/ReactCommon/react/renderer/attributedstring/PlaceholderAttributedString.h}: +namespace facebook::react { +inline AttributedString ensurePlaceholderIfEmpty_DO_NOT_USE( + const AttributedString& attributedString) { + if (attributedString.isEmpty()) { + AttributedString placeholder{attributedString}; + placeholder.appendFragment( + {.string = "I", + .textAttributes = attributedString.getBaseTextAttributes(), + .parentShadowView = {}}); + return placeholder; + } + return attributedString; +} +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h}: namespace facebook::react { using SharedTextAttributes = std::shared_ptr; @@ -17193,6 +18216,7 @@ class TextAttributes : public DebugStringConvertible { std::optional fontStyle{}; std::optional fontVariant{}; std::optional allowFontScaling{}; + Float maxFontSizeMultiplier{std::numeric_limits::quiet_NaN()}; std::optional dynamicTypeRamp{}; Float letterSpacing{std::numeric_limits::quiet_NaN()}; std::optional textTransform{}; @@ -17212,10 +18236,8 @@ class TextAttributes : public DebugStringConvertible { std::optional layoutDirection{}; std::optional accessibilityRole{}; std::optional role{}; - std::optional textAlignVertical{}; void apply(TextAttributes textAttributes); bool operator==(const TextAttributes& rhs) const; - bool operator!=(const TextAttributes& rhs) const; }; } // namespace facebook::react namespace std { @@ -17229,6 +18251,7 @@ struct hash { textAttributes.opacity, textAttributes.fontFamily, textAttributes.fontSize, + textAttributes.maxFontSizeMultiplier, textAttributes.fontSizeMultiplier, textAttributes.fontWeight, textAttributes.fontStyle, @@ -17238,7 +18261,6 @@ struct hash { textAttributes.textTransform, textAttributes.lineHeight, textAttributes.alignment, - textAttributes.textAlignVertical, textAttributes.baseWritingDirection, textAttributes.lineBreakStrategy, textAttributes.lineBreakMode, @@ -17410,7 +18432,7 @@ inline void fromRawValue( const PropsParserContext& context, const RawValue& value, FontWeight& result) { - react_native_expect(value.hasType()); + react_native_expect(value.hasType() || value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "normal") { @@ -17439,7 +18461,32 @@ inline void fromRawValue( result = FontWeight::Weight900; } else { LOG(ERROR) << "Unsupported FontWeight value: " << string; - react_native_expect(false); + result = FontWeight::Regular; + } + return; + } + if (value.hasType()) { + auto numeric = (int)value; + if (numeric == 100) { + result = FontWeight::Weight100; + } else if (numeric == 200) { + result = FontWeight::Weight200; + } else if (numeric == 300) { + result = FontWeight::Weight300; + } else if (numeric == 400) { + result = FontWeight::Weight400; + } else if (numeric == 500) { + result = FontWeight::Weight500; + } else if (numeric == 600) { + result = FontWeight::Weight600; + } else if (numeric == 700) { + result = FontWeight::Weight700; + } else if (numeric == 800) { + result = FontWeight::Weight800; + } else if (numeric == 900) { + result = FontWeight::Weight900; + } else { + LOG(ERROR) << "Unsupported FontWeight value: " << numeric; result = FontWeight::Regular; } return; @@ -17449,7 +18496,7 @@ inline void fromRawValue( result = FontWeight::Regular; } inline std::string toString(const FontWeight& fontWeight) { - return folly::to((int)fontWeight); + return std::to_string((int)fontWeight); } inline void fromRawValue( const PropsParserContext& context, @@ -17508,6 +18555,53 @@ inline void fromRawValue( } else if (item == "proportional-nums") { result = (FontVariant)((int)result | (int)FontVariant::ProportionalNums); + } else if (item == "stylistic-one") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticOne); + } else if (item == "stylistic-two") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticTwo); + } else if (item == "stylistic-three") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticThree); + } else if (item == "stylistic-four") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticFour); + } else if (item == "stylistic-five") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticFive); + } else if (item == "stylistic-six") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticSix); + } else if (item == "stylistic-seven") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticSeven); + } else if (item == "stylistic-eight") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticEight); + } else if (item == "stylistic-nine") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticNine); + } else if (item == "stylistic-ten") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticTen); + } else if (item == "stylistic-eleven") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticEleven); + } else if (item == "stylistic-twelve") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticTwelve); + } else if (item == "stylistic-thirteen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticThirteen); + } else if (item == "stylistic-fourteen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticFourteen); + } else if (item == "stylistic-fifteen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticFifteen); + } else if (item == "stylistic-sixteen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticSixteen); + } else if (item == "stylistic-seventeen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticSeventeen); + } else if (item == "stylistic-eighteen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticEighteen); + } else if (item == "stylistic-nineteen") { + result = + (FontVariant)((int)result | (int)FontVariant::StylisticNineteen); + } else if (item == "stylistic-twenty") { + result = (FontVariant)((int)result | (int)FontVariant::StylisticTwenty); } else { LOG(ERROR) << "Unsupported FontVariant value: " << item; react_native_expect(false); @@ -17536,6 +18630,66 @@ inline std::string toString(const FontVariant& fontVariant) { if ((int)fontVariant & (int)FontVariant::ProportionalNums) { result += "proportional-nums" + separator; } + if ((int)fontVariant & (int)FontVariant::StylisticOne) { + result += "stylistic-one" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticTwo) { + result += "stylistic-two" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticThree) { + result += "stylistic-three" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticFour) { + result += "stylistic-four" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticFive) { + result += "stylistic-five" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticSix) { + result += "stylistic-six" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticSeven) { + result += "stylistic-seven" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticEight) { + result += "stylistic-eight" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticNine) { + result += "stylistic-nine" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticTen) { + result += "stylistic-ten" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticEleven) { + result += "stylistic-eleven" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticTwelve) { + result += "stylistic-twelve" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticThirteen) { + result += "stylistic-thirteen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticFourteen) { + result += "stylistic-fourteen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticFifteen) { + result += "stylistic-fifteen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticSixteen) { + result += "stylistic-sixteen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticSeventeen) { + result += "stylistic-seventeen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticEighteen) { + result += "stylistic-eighteen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticNineteen) { + result += "stylistic-nineteen" + separator; + } + if ((int)fontVariant & (int)FontVariant::StylisticTwenty) { + result += "stylistic-twenty" + separator; + } if (!result.empty()) { result.erase(result.length() - separator.length()); } @@ -17938,6 +19092,12 @@ inline ParagraphAttributes convertRawProp( "adjustsFontSizeToFit", sourceParagraphAttributes.adjustsFontSizeToFit, defaultParagraphAttributes.adjustsFontSizeToFit); + paragraphAttributes.minimumFontScale = convertRawProp( + context, + rawProps, + "minimumFontScale", + sourceParagraphAttributes.minimumFontScale, + defaultParagraphAttributes.minimumFontScale); paragraphAttributes.minimumFontSize = convertRawProp( context, rawProps, @@ -17962,6 +19122,12 @@ inline ParagraphAttributes convertRawProp( "android_hyphenationFrequency", sourceParagraphAttributes.android_hyphenationFrequency, defaultParagraphAttributes.android_hyphenationFrequency); + paragraphAttributes.textAlignVertical = convertRawProp( + context, + rawProps, + "textAlignVertical", + sourceParagraphAttributes.textAlignVertical, + defaultParagraphAttributes.textAlignVertical); return paragraphAttributes; } inline void fromRawValue( @@ -17979,8 +19145,8 @@ inline void fromRawValue( } } inline std::string toString(const AttributedString::Range& range) { - return "{location: " + folly::to(range.location) + - ", length: " + folly::to(range.length) + "}"; + return "{location: " + std::to_string(range.location) + + ", length: " + std::to_string(range.length) + "}"; } } // namespace facebook::react @@ -18014,7 +19180,27 @@ enum class FontVariant : int { OldstyleNums = 1 << 2, LiningNums = 1 << 3, TabularNums = 1 << 4, - ProportionalNums = 1 << 5 + ProportionalNums = 1 << 5, + StylisticOne = 1 << 6, + StylisticTwo = 1 << 7, + StylisticThree = 1 << 8, + StylisticFour = 1 << 9, + StylisticFive = 1 << 10, + StylisticSix = 1 << 11, + StylisticSeven = 1 << 12, + StylisticEight = 1 << 13, + StylisticNine = 1 << 14, + StylisticTen = 1 << 15, + StylisticEleven = 1 << 16, + StylisticTwelve = 1 << 17, + StylisticThirteen = 1 << 18, + StylisticFourteen = 1 << 19, + StylisticFifteen = 1 << 20, + StylisticSixteen = 1 << 21, + StylisticSeventeen = 1 << 22, + StylisticEighteen = 1 << 23, + StylisticNineteen = 1 << 24, + StylisticTwenty = 1 << 25 }; enum class DynamicTypeRamp { Caption2, @@ -18058,6 +19244,35 @@ enum class TextTransform { enum class HyphenationFrequency { None, Normal, Full }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/bridging/bridging.h}: +namespace facebook::react { +template <> +struct Bridging { + static ShadowNode::Shared fromJs( + jsi::Runtime& rt, + const jsi::Value& jsiValue) { + auto object = jsiValue.asObject(rt); + if (!object.hasNativeState(rt)) { + throw jsi::JSINativeException("Value is not a ShadowNode reference"); + } + auto nativeState = object.getNativeState(rt); + auto shadowNodeWrapper = + std::dynamic_pointer_cast(nativeState); + if (shadowNodeWrapper == nullptr || + shadowNodeWrapper->shadowNode == nullptr) { + throw jsi::JSINativeException( + "Value state is nullptr, expected a ShadowNode reference"); + } + return shadowNodeWrapper->shadowNode; + } + static jsi::Value toJs(jsi::Runtime& rt, const ShadowNode::Shared& value) { + jsi::Object obj(rt); + obj.setNativeState(rt, std::make_shared(value)); + return obj; + } +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorFactory.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h} @@ -18456,7 +19671,7 @@ extern const char LegacyViewManagerInteropComponentName[]; using LegacyViewManagerInteropShadowNode = ConcreteViewShadowNode< LegacyViewManagerInteropComponentName, LegacyViewManagerInteropViewProps, - LegacyViewManagerInteropViewEventEmitter, + ViewEventEmitter, LegacyViewManagerInteropState>; } // namespace facebook::react @@ -18468,18 +19683,6 @@ class LegacyViewManagerInteropState final { }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewEventEmitter.h}: -namespace facebook::react { -using SharedLegacyViewManagerInteropViewEventEmitter = - std::shared_ptr; -class LegacyViewManagerInteropViewEventEmitter : public ViewEventEmitter { - public: - using ViewEventEmitter::ViewEventEmitter; - void dispatchEvent(const std::string& type, const folly::dynamic& payload) - const; -}; -} // namespace facebook::react - /// @src {packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.h}: namespace facebook::react { class LegacyViewManagerInteropViewProps final : public ViewProps { @@ -18495,7 +19698,7 @@ class LegacyViewManagerInteropViewProps final : public ViewProps { /// @src {packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h}: NS_ASSUME_NONNULL_BEGIN -typedef void (^InterceptorBlock)(std::string eventName, folly::dynamic event); +typedef void (^InterceptorBlock)(std::string eventName, folly::dynamic &&event); @interface RCTLegacyViewManagerInteropCoordinator : NSObject - (instancetype)initWithComponentData:(RCTComponentData *)componentData bridge:(nullable RCTBridge *)bridge @@ -18587,6 +19790,7 @@ class ModalHostViewShadowNode final : public ConcreteViewShadowNode< static ShadowNodeTraits BaseTraits() { auto traits = ConcreteViewShadowNode::BaseTraits(); traits.set(ShadowNodeTraits::Trait::RootNodeKind); + traits.set(ShadowNodeTraits::Trait::Unstable_uncullableView); return traits; } }; @@ -18644,7 +19848,6 @@ class AndroidProgressBarMeasurementsManager { const AndroidProgressBarProps& props, LayoutConstraints layoutConstraints) const; }; -}; } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/AndroidProgressBarShadowNode.h}: @@ -18719,6 +19922,7 @@ class RootShadowNode final const LayoutConstraints& layoutConstraints, const LayoutContext& layoutContext) const; Transform getTransform() const override; + void setInstanceHandle(InstanceHandle::Shared instanceHandle) const; }; } // namespace facebook::react @@ -18759,6 +19963,64 @@ class SafeAreaViewState final { }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.h}: +namespace facebook::react { +class BaseScrollViewProps : public ViewProps { + public: + BaseScrollViewProps() = default; + BaseScrollViewProps( + const PropsParserContext& context, + const BaseScrollViewProps& sourceProps, + const RawProps& rawProps); + void setProp( + const PropsParserContext& context, + RawPropsPropNameHash hash, + const char* propName, + const RawValue& value); + bool alwaysBounceHorizontal{}; + bool alwaysBounceVertical{}; + bool bounces{true}; + bool bouncesZoom{true}; + bool canCancelContentTouches{true}; + bool centerContent{}; + bool automaticallyAdjustContentInsets{}; + bool automaticallyAdjustsScrollIndicatorInsets{true}; + bool automaticallyAdjustKeyboardInsets{false}; + Float decelerationRate{0.998f}; + Float endDraggingSensitivityMultiplier{1}; + bool directionalLockEnabled{}; + ScrollViewIndicatorStyle indicatorStyle{}; + ScrollViewKeyboardDismissMode keyboardDismissMode{}; + std::optional + maintainVisibleContentPosition{}; + Float maximumZoomScale{1.0f}; + Float minimumZoomScale{1.0f}; + bool scrollEnabled{true}; + bool pagingEnabled{}; + bool pinchGestureEnabled{true}; + bool scrollsToTop{true}; + bool showsHorizontalScrollIndicator{true}; + bool showsVerticalScrollIndicator{true}; + bool persistentScrollbar{false}; + bool horizontal{false}; + Float scrollEventThrottle{}; + Float zoomScale{1.0f}; + EdgeInsets contentInset{}; + Point contentOffset{}; + EdgeInsets scrollIndicatorInsets{}; + Float snapToInterval{}; + ScrollViewSnapToAlignment snapToAlignment{}; + bool disableIntervalMomentum{false}; + std::vector snapToOffsets{}; + bool snapToStart{true}; + bool snapToEnd{true}; + ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{ + ContentInsetAdjustmentBehavior::Never}; + bool scrollToOverflowEnabled{false}; + bool isInvertedVirtualizedList{false}; +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/RCTComponentViewHelpers.h}: NS_ASSUME_NONNULL_BEGIN @protocol RCTScrollViewProtocol @@ -18819,6 +20081,17 @@ struct ScrollEvent : public EventPayload { folly::dynamic asDynamic() const; jsi::Value asJSIValue(jsi::Runtime& runtime) const override; EventPayloadType getType() const override; + std::optional extractValue( + const std::vector& path) const override; +}; +struct ScrollEndDragEvent : public ScrollEvent { + Point targetContentOffset; + Point velocity; + ScrollEndDragEvent() = default; + ScrollEndDragEvent(const ScrollEvent& scrollEvent) + : ScrollEvent(scrollEvent), targetContentOffset({}), velocity({}) {} + folly::dynamic asDynamic() const; + jsi::Value asJSIValue(jsi::Runtime& runtime) const override; }; } // namespace facebook::react @@ -18834,9 +20107,10 @@ class ScrollViewEventEmitter : public ViewEventEmitter { public: using ViewEventEmitter::ViewEventEmitter; using Metrics = ScrollEvent; + using EndDragMetrics = ScrollEndDragEvent; void onScroll(const ScrollEvent& scrollEvent) const; void onScrollBeginDrag(const ScrollEvent& scrollEvent) const; - void onScrollEndDrag(const ScrollEvent& scrollEvent) const; + void onScrollEndDrag(const ScrollEndDragEvent& scrollEvent) const; void onMomentumScrollBegin(const ScrollEvent& scrollEvent) const; void onMomentumScrollEnd(const ScrollEvent& scrollEvent) const; void onScrollToTop(const ScrollEvent& scrollEvent) const; @@ -18845,60 +20119,8 @@ class ScrollViewEventEmitter : public ViewEventEmitter { /// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h}: namespace facebook::react { -class ScrollViewProps final : public ViewProps { - public: - ScrollViewProps() = default; - ScrollViewProps( - const PropsParserContext& context, - const ScrollViewProps& sourceProps, - const RawProps& rawProps); - void setProp( - const PropsParserContext& context, - RawPropsPropNameHash hash, - const char* propName, - const RawValue& value); - bool alwaysBounceHorizontal{}; - bool alwaysBounceVertical{}; - bool bounces{true}; - bool bouncesZoom{true}; - bool canCancelContentTouches{true}; - bool centerContent{}; - bool automaticallyAdjustContentInsets{}; - bool automaticallyAdjustsScrollIndicatorInsets{true}; - bool automaticallyAdjustKeyboardInsets{false}; - Float decelerationRate{0.998f}; - Float endDraggingSensitivityMultiplier{1}; - bool directionalLockEnabled{}; - ScrollViewIndicatorStyle indicatorStyle{}; - ScrollViewKeyboardDismissMode keyboardDismissMode{}; - std::optional - maintainVisibleContentPosition{}; - Float maximumZoomScale{1.0f}; - Float minimumZoomScale{1.0f}; - bool scrollEnabled{true}; - bool pagingEnabled{}; - bool pinchGestureEnabled{true}; - bool scrollsToTop{true}; - bool showsHorizontalScrollIndicator{true}; - bool showsVerticalScrollIndicator{true}; - bool persistentScrollbar{false}; - bool horizontal{false}; - Float scrollEventThrottle{}; - Float zoomScale{1.0f}; - EdgeInsets contentInset{}; - Point contentOffset{}; - EdgeInsets scrollIndicatorInsets{}; - Float snapToInterval{}; - ScrollViewSnapToAlignment snapToAlignment{}; - bool disableIntervalMomentum{false}; - std::vector snapToOffsets{}; - bool snapToStart{true}; - bool snapToEnd{true}; - ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{ - ContentInsetAdjustmentBehavior::Never}; - bool scrollToOverflowEnabled{false}; - bool isInvertedVirtualizedList{false}; -}; +using ScrollViewProps = HostPlatformScrollViewProps; +using SharedScrollViewProps = std::shared_ptr; } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.h}: @@ -19067,6 +20289,32 @@ class AndroidHorizontalScrollContentViewShadowNode final }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/platform/android/react/renderer/components/scrollview/HostPlatformScrollViewProps.h}: +namespace facebook::react { +class HostPlatformScrollViewProps final : public BaseScrollViewProps { + public: + HostPlatformScrollViewProps() = default; + HostPlatformScrollViewProps( + const PropsParserContext& context, + const HostPlatformScrollViewProps& sourceProps, + const RawProps& rawProps); + void setProp( + const PropsParserContext& context, + RawPropsPropNameHash hash, + const char* propName, + const RawValue& value); + bool sendMomentumEvents{}; + bool nestedScrollEnabled{}; + ComponentName getDiffPropsImplementationTarget() const override; + folly::dynamic getDiffProps(const Props* prevProps) const override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/platform/cxx/react/renderer/components/scrollview/HostPlatformScrollViewProps.h}: +namespace facebook::react { +using HostPlatformScrollViewProps = BaseScrollViewProps; +} + /// @src {packages/react-native/ReactCommon/react/renderer/components/scrollview/primitives.h}: namespace facebook::react { enum class ScrollViewSnapToAlignment { Start, Center, End }; @@ -19144,7 +20392,6 @@ class AndroidSwitchMeasurementsManager { : contextContainer_(contextContainer) {} Size measure(SurfaceId surfaceId, LayoutConstraints layoutConstraints) const; }; -}; } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/switch/androidswitch/react/renderer/components/androidswitch/AndroidSwitchShadowNode.h}: @@ -19205,9 +20452,6 @@ class BaseTextShadowNode { const ShadowNode& parentNode, AttributedString& outAttributedString, Attachments& outAttachments); - inline static std::string getEmptyPlaceholder() { - return "I"; - } }; } // namespace facebook::react @@ -19269,11 +20513,14 @@ class ParagraphShadowNode final : public ConcreteViewShadowNode< ParagraphComponentName, ParagraphProps, ParagraphEventEmitter, - ParagraphState, - true>, + ParagraphState>, public BaseTextShadowNode { public: using ConcreteViewShadowNode::ConcreteViewShadowNode; + ParagraphShadowNode( + const ShadowNodeFragment& fragment, + const ShadowNodeFamily::Shared& family, + ShadowNodeTraits traits); ParagraphShadowNode( const ShadowNode& sourceShadowNode, const ShadowNodeFragment& fragment); @@ -19297,17 +20544,13 @@ class ParagraphShadowNode final : public ConcreteViewShadowNode< ParagraphAttributes paragraphAttributes; Attachments attachments; }; -}; -}; -} // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/text/ParagraphState.h}: -namespace facebook::react { -class ParagraphState final { - public: - AttributedString attributedString; - ParagraphAttributes paragraphAttributes; - std::weak_ptr layoutManager; + protected: + bool shouldNewRevisionDirtyMeasurement( + const ShadowNode& sourceShadowNode, + const ShadowNodeFragment& fragment) const override; +}; + mutable std::vector measuredLayouts_; }; } // namespace facebook::react @@ -19387,6 +20630,56 @@ class TextShadowNode : public ConcreteShadowNode< /// @src {packages/react-native/ReactCommon/react/renderer/components/text/conversions.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h} +/// @src {packages/react-native/ReactCommon/react/renderer/components/text/platform/android/react/renderer/components/text/ParagraphState.h}: +namespace facebook::react { +constexpr static MapBuffer::Key TX_STATE_KEY_ATTRIBUTED_STRING = 0; +constexpr static MapBuffer::Key TX_STATE_KEY_PARAGRAPH_ATTRIBUTES = 1; +constexpr static MapBuffer::Key TX_STATE_KEY_HASH = 2; +constexpr static MapBuffer::Key TX_STATE_KEY_MOST_RECENT_EVENT_COUNT = 3; +class ParagraphState final { + public: + AttributedString attributedString; + ParagraphAttributes paragraphAttributes; + std::weak_ptr layoutManager; + MeasuredPreparedLayout measuredLayout; + ParagraphState( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + std::weak_ptr layoutManager, + MeasuredPreparedLayout measuredLayout) + : attributedString(std::move(attributedString)), + paragraphAttributes(std::move(paragraphAttributes)), + layoutManager(std::move(layoutManager)), + measuredLayout(std::move(measuredLayout)) {} + ParagraphState( + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + std::weak_ptr layoutManager) + : ParagraphState( + std::move(attributedString), + std::move(paragraphAttributes), + std::move(layoutManager), + {}) {} + ParagraphState() = default; + ParagraphState(const ParagraphState&, const folly::dynamic&) { + react_native_assert(false && "Not supported"); + }; + folly::dynamic getDynamic() const; + MapBuffer getMapBuffer() const; + jni::local_ref getJNIReference() const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/text/platform/cxx/react/renderer/components/text/ParagraphState.h}: +namespace facebook::react { +class ParagraphState final { + public: + AttributedString attributedString; + ParagraphAttributes paragraphAttributes; + std::weak_ptr layoutManager; +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.h}: namespace facebook::react { class BaseTextInputProps : public ViewProps, public BaseTextProps { @@ -19403,7 +20696,6 @@ class BaseTextInputProps : public ViewProps, public BaseTextProps { const RawValue& value); SubmitBehavior getNonDefaultSubmitBehavior() const; TextAttributes getEffectiveTextAttributes(Float fontSizeMultiplier) const; - ParagraphAttributes getEffectiveParagraphAttributes() const; ParagraphAttributes paragraphAttributes{}; std::string defaultValue{}; std::string placeholder{}; @@ -19421,6 +20713,8 @@ class BaseTextInputProps : public ViewProps, public BaseTextProps { bool readOnly{false}; SubmitBehavior submitBehavior{SubmitBehavior::Default}; bool multiline{false}; + bool disableKeyboardShortcuts{false}; + std::optional> acceptDragAndDropTypes{}; }; } // namespace facebook::react @@ -19430,22 +20724,19 @@ template < const char* concreteComponentName, typename ViewPropsT, typename ViewEventEmitterT, - typename StateDataT, - bool usesMapBufferForStateData = false> + typename StateDataT> class BaseTextInputShadowNode : public ConcreteViewShadowNode< concreteComponentName, ViewPropsT, ViewEventEmitterT, - StateDataT, - usesMapBufferForStateData>, + StateDataT>, public BaseTextShadowNode { public: using BaseShadowNode = ConcreteViewShadowNode< concreteComponentName, ViewPropsT, ViewEventEmitterT, - StateDataT, - usesMapBufferForStateData>; + StateDataT>; using BaseShadowNode::ConcreteViewShadowNode; static ShadowNodeTraits BaseTraits() { auto traits = BaseShadowNode::BaseTraits(); @@ -19465,15 +20756,19 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode< const LayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const override { const auto& props = BaseShadowNode::getConcreteProps(); + auto textConstraints = getTextConstraints(layoutConstraints); TextLayoutContext textLayoutContext{ - .pointScaleFactor = layoutContext.pointScaleFactor}; - return textLayoutManager_ - ->measure( - attributedStringBoxToMeasure(layoutContext), - props.getEffectiveParagraphAttributes(), - textLayoutContext, - layoutConstraints) - .size; + .pointScaleFactor = layoutContext.pointScaleFactor, + .surfaceId = BaseShadowNode::getSurfaceId(), + }; + auto textSize = textLayoutManager_ + ->measure( + attributedStringBoxToMeasure(layoutContext), + props.paragraphAttributes, + textLayoutContext, + textConstraints) + .size; + return layoutConstraints.clamp(textSize); } void layout(LayoutContext layoutContext) override { updateStateIfNeeded(layoutContext); @@ -19483,31 +20778,43 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode< const auto& props = BaseShadowNode::getConcreteProps(); auto attributedString = getAttributedString(layoutContext); if (attributedString.isEmpty()) { - auto placeholderString = !props.placeholder.empty() - ? props.placeholder - : BaseTextShadowNode::getEmptyPlaceholder(); - auto textAttributes = - props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier); - attributedString.appendFragment( - {std::move(placeholderString), textAttributes, {}}); + attributedString = getPlaceholderAttributedString(layoutContext); } auto top = YGNodeLayoutGetBorder( &(YogaLayoutableShadowNode::yogaNode_), YGEdgeTop) + YGNodeLayoutGetPadding( &(YogaLayoutableShadowNode::yogaNode_), YGEdgeTop); AttributedStringBox attributedStringBox{attributedString}; - return textLayoutManager_->baseline( - attributedStringBox, - props.getEffectiveParagraphAttributes(), - size) + - top; - } -}; - attributedString.appendFragment(AttributedString::Fragment{ - .string = props.text, - .textAttributes = textAttributes, - .parentShadowView = ShadowView(*this)}); - auto attachments = BaseTextShadowNode::Attachments{}; + if constexpr (TextLayoutManagerExtended::supportsLineMeasurement()) { + auto lines = + TextLayoutManagerExtended(*textLayoutManager_) + .measureLines( + attributedStringBox, props.paragraphAttributes, size); + return LineMeasurement::baseline(lines) + top; + } else { + LOG(WARNING) + << "Baseline alignment is not supported by the current platform"; + return top; + } + } + LayoutConstraints getTextConstraints( + const LayoutConstraints& layoutConstraints) const { + if (BaseShadowNode::getConcreteProps().multiline) { + return layoutConstraints; + } else { + return LayoutConstraints{ + .minimumSize = layoutConstraints.minimumSize, + .maximumSize = + Size{ + .width = std::numeric_limits::infinity(), + .height = layoutConstraints.maximumSize.height, + }, + .layoutDirection = layoutConstraints.layoutDirection, + }; + } + } + std::shared_ptr textLayoutManager_; +}; BaseTextShadowNode::buildAttributedString( textAttributes, *this, attributedString, attachments); attributedString.setBaseTextAttributes(textAttributes); @@ -19517,7 +20824,10 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode< const LayoutContext& layoutContext) const { bool meaningfulState = BaseShadowNode::getState() && BaseShadowNode::getState()->getRevision() != - State::initialRevisionValue; + State::initialRevisionValue && + BaseShadowNode::getStateData() + .reactTreeAttributedString.getBaseTextAttributes() + .fontSizeMultiplier == layoutContext.fontSizeMultiplier; if (meaningfulState) { const auto& stateData = BaseShadowNode::getStateData(); auto attributedStringBox = stateData.attributedStringBox; @@ -19531,18 +20841,24 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode< ? AttributedString{} : getAttributedString(layoutContext); if (attributedString.isEmpty()) { - const auto& props = BaseShadowNode::getConcreteProps(); - auto placeholder = props.placeholder; - auto string = !placeholder.empty() - ? placeholder - : BaseTextShadowNode::getEmptyPlaceholder(); - auto textAttributes = - props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier); - attributedString.appendFragment({string, textAttributes, {}}); + attributedString = getPlaceholderAttributedString(layoutContext); } return AttributedStringBox{attributedString}; } - std::shared_ptr textLayoutManager_; + AttributedString getPlaceholderAttributedString( + const LayoutContext& layoutContext) const { + const auto& props = BaseShadowNode::getConcreteProps(); + AttributedString attributedString; + attributedString.setBaseTextAttributes( + props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier)); + if (!props.placeholder.empty()) { + attributedString.appendFragment( + {.string = props.placeholder, + .textAttributes = attributedString.getBaseTextAttributes(), + .parentShadowView = {}}); + } + return attributedString; + } }; } // namespace facebook::react @@ -19588,7 +20904,11 @@ class TextInputState final { AttributedStringBox attributedStringBox, AttributedString reactTreeAttributedString, ParagraphAttributes paragraphAttributes, - int64_t mostRecentEventCount); + int64_t mostRecentEventCount) + : attributedStringBox(std::move(attributedStringBox)), + reactTreeAttributedString(std::move(reactTreeAttributedString)), + paragraphAttributes(std::move(paragraphAttributes)), + mostRecentEventCount(mostRecentEventCount) {} AttributedStringBox attributedStringBox; AttributedString reactTreeAttributedString{}; ParagraphAttributes paragraphAttributes; @@ -19640,14 +20960,14 @@ enum class SubmitBehavior { /// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h} /// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.h} namespace facebook::react { extern const char AndroidTextInputComponentName[]; class AndroidTextInputShadowNode final : public ConcreteViewShadowNode< AndroidTextInputComponentName, AndroidTextInputProps, AndroidTextInputEventEmitter, - TextInputState, - true> { + AndroidTextInputState> { public: using ConcreteViewShadowNode::ConcreteViewShadowNode; static ShadowNodeTraits BaseTraits() { @@ -19657,15 +20977,18 @@ class AndroidTextInputShadowNode final : public ConcreteViewShadowNode< traits.set(ShadowNodeTraits::Trait::BaselineYogaNode); return traits; } - AttributedString getAttributedString() const; - AttributedString getPlaceholderAttributedString() const; void setTextLayoutManager( std::shared_ptr textLayoutManager); + + protected: Size measureContent( const LayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const override; void layout(LayoutContext layoutContext) override; Float baseline(const LayoutContext& layoutContext, Size size) const override; + std::shared_ptr textLayoutManager_; + LayoutConstraints getTextConstraints( + const LayoutConstraints& layoutConstraints) const; }; } // namespace facebook::react namespace facebook::react { @@ -19708,7 +21031,8 @@ class AndroidTextInputComponentDescriptor final env->DeleteLocalRef(defaultTextInputPaddingArray); } return std::make_shared( - std::make_shared(TextInputState({}, {}, {}, 0)), + std::make_shared( + AndroidTextInputState({}, {}, {}, 0)), family); } @@ -19791,6 +21115,11 @@ struct AndroidTextInputTextShadowOffsetStruct { double width; double height; }; +inline static bool operator==( + const AndroidTextInputTextShadowOffsetStruct& lhs, + const AndroidTextInputTextShadowOffsetStruct& rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height; +} static inline void fromRawValue( const PropsParserContext& context, const RawValue& value, @@ -19871,20 +21200,22 @@ class AndroidTextInputProps final : public BaseTextInputProps { bool hasPaddingBottom{}; bool hasPaddingStart{}; bool hasPaddingEnd{}; + ComponentName getDiffPropsImplementationTarget() const override; + folly::dynamic getDiffProps(const Props* prevProps) const override; }; } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputEventEmitter.h} /// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.h} namespace facebook::react { extern const char AndroidTextInputComponentName[]; class AndroidTextInputShadowNode final : public ConcreteViewShadowNode< AndroidTextInputComponentName, AndroidTextInputProps, AndroidTextInputEventEmitter, - TextInputState, - true> { + AndroidTextInputState> { public: using ConcreteViewShadowNode::ConcreteViewShadowNode; static ShadowNodeTraits BaseTraits() { @@ -19894,15 +21225,56 @@ class AndroidTextInputShadowNode final : public ConcreteViewShadowNode< traits.set(ShadowNodeTraits::Trait::BaselineYogaNode); return traits; } - AttributedString getAttributedString() const; - AttributedString getPlaceholderAttributedString() const; void setTextLayoutManager( std::shared_ptr textLayoutManager); + + protected: Size measureContent( const LayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const override; void layout(LayoutContext layoutContext) override; Float baseline(const LayoutContext& layoutContext, Size size) const override; + std::shared_ptr textLayoutManager_; + LayoutConstraints getTextConstraints( + const LayoutConstraints& layoutConstraints) const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputState.h}: +namespace facebook::react { +class AndroidTextInputState final { + public: + AndroidTextInputState() = default; + AndroidTextInputState( + AttributedStringBox attributedStringBox, + AttributedString reactTreeAttributedString, + ParagraphAttributes paragraphAttributes, + int64_t mostRecentEventCount) + : attributedStringBox(std::move(attributedStringBox)), + reactTreeAttributedString(std::move(reactTreeAttributedString)), + paragraphAttributes(std::move(paragraphAttributes)), + mostRecentEventCount(mostRecentEventCount) {} + AndroidTextInputState( + const AndroidTextInputState& previousState, + const folly::dynamic& data) + : attributedStringBox(previousState.attributedStringBox), + reactTreeAttributedString(previousState.reactTreeAttributedString), + paragraphAttributes(previousState.paragraphAttributes), + mostRecentEventCount(data.getDefault( + "mostRecentEventCount", + previousState.mostRecentEventCount) + .getInt()), + cachedAttributedStringId(data.getDefault( + "opaqueCacheId", + previousState.cachedAttributedStringId) + .getInt()) {} + folly::dynamic getDynamic() const; + MapBuffer getMapBuffer() const; + AttributedStringBox attributedStringBox; + AttributedString reactTreeAttributedString{}; + ParagraphAttributes paragraphAttributes; + int64_t mostRecentEventCount{0}; + int64_t cachedAttributedStringId{0}; }; } // namespace facebook::react @@ -19926,22 +21298,7 @@ class TextInputComponentDescriptor final } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h}: -namespace facebook::react { -class TextInputProps final : public BaseTextInputProps { - public: - TextInputProps() = default; - TextInputProps( - const PropsParserContext& context, - const TextInputProps& sourceProps, - const RawProps& rawProps); - const TextInputTraits traits{}; - std::optional selection{}; - const std::string inputAccessoryViewID{}; - const std::string inputAccessoryViewButtonLabel{}; - bool onKeyPressSync{false}; - bool onChangeSync{false}; -}; -} // namespace facebook::react +/// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/TextInputProps.h} /// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputShadowNode.h}: namespace facebook::react { @@ -19979,7 +21336,7 @@ inline void fromRawValue( result = AutocapitalizationType::Characters; return; } - abort(); + result = AutocapitalizationType::None; } inline void fromRawValue( const PropsParserContext& context, @@ -19998,7 +21355,7 @@ inline void fromRawValue( result = KeyboardAppearance::Dark; return; } - abort(); + result = KeyboardAppearance::Default; } inline void fromRawValue( const PropsParserContext& context, @@ -20061,7 +21418,7 @@ inline void fromRawValue( result = ReturnKeyType::Continue; return; } - abort(); + result = ReturnKeyType::Default; } inline void fromRawValue( const PropsParserContext& context, @@ -20084,7 +21441,7 @@ inline void fromRawValue( result = TextInputAccessoryVisibilityMode::Always; return; } - abort(); + result = TextInputAccessoryVisibilityMode::Never; } inline void fromRawValue( const PropsParserContext& context, @@ -20147,7 +21504,7 @@ inline void fromRawValue( result = KeyboardType::VisiblePassword; return; } - abort(); + result = KeyboardType::Default; } } // namespace facebook::react @@ -20227,6 +21584,7 @@ class TextInputTraits final { bool showSoftInputOnFocus{true}; ReturnKeyType returnKeyType{ReturnKeyType::Default}; bool selectTextOnFocus{false}; + std::vector dataDetectorTypes{}; std::string textContentType{}; std::string passwordRules{}; std::optional smartInsertDelete{}; @@ -20355,6 +21713,12 @@ static TextInputTraits convertRawProp( "smartInsertDelete", sourceTraits.smartInsertDelete, defaultTraits.smartInsertDelete); + traits.dataDetectorTypes = convertRawProp( + context, + rawProps, + "dataDetectorTypes", + sourceTraits.dataDetectorTypes, + defaultTraits.dataDetectorTypes); return traits; } inline void fromRawValue( @@ -20391,153 +21755,728 @@ inline void fromRawValue( } } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/MacOSTextInputEventEmitter.h}: namespace facebook::react { -class UnimplementedViewComponentDescriptor final - : public ConcreteComponentDescriptor { +class MacOSTextInputEventEmitter : public TextInputEventEmitter { public: - using ConcreteComponentDescriptor::ConcreteComponentDescriptor; - ComponentHandle getComponentHandle() const override; - ComponentName getComponentName() const override; - Props::Shared cloneProps( - const PropsParserContext& context, - const Props::Shared& props, - RawProps rawProps) const override; + using TextInputEventEmitter::TextInputEventEmitter; + struct OnAutoCorrectChange { + bool enabled; + }; + void onAutoCorrectChange(OnAutoCorrectChange value) const; + struct OnSpellCheckChange { + bool enabled; + }; + void onSpellCheckChange(OnSpellCheckChange value) const; + struct OnGrammarCheckChange { + bool enabled; + }; + void onGrammarCheckChange(OnGrammarCheckChange value) const; + struct PasteEvent { + std::vector dataTransferItems; + }; + void onPaste(const PasteEvent& pasteEvent) const; }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewProps.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/TextInputComponentDescriptor.h}: namespace facebook::react { -class UnimplementedViewProps final : public ViewProps { +class TextInputComponentDescriptor final + : public ConcreteComponentDescriptor { public: - using ViewProps::ViewProps; - void setComponentName(ComponentName componentName); - ComponentName getComponentName() const; -}; + TextInputComponentDescriptor(const ComponentDescriptorParameters& parameters) + : ConcreteComponentDescriptor(parameters) { + textLayoutManager_ = + std::make_shared(contextContainer_); + } + + protected: + void adopt(ShadowNode& shadowNode) const override { + ConcreteComponentDescriptor::adopt(shadowNode); + auto& concreteShadowNode = static_cast(shadowNode); + concreteShadowNode.setTextLayoutManager(textLayoutManager_); + } }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewShadowNode.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/TextInputProps.h}: +/// @dep {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h} + +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/TextInputShadowNode.h}: namespace facebook::react { -extern const char UnimplementedViewComponentName[]; -using UnimplementedViewShadowNode = ConcreteViewShadowNode< - UnimplementedViewComponentName, - UnimplementedViewProps>; +extern const char TextInputComponentName[]; +class TextInputShadowNode final : public BaseTextInputShadowNode< + TextInputComponentName, + TextInputProps, + MacOSTextInputEventEmitter, + TextInputState> { + public: + using BaseTextInputShadowNode::BaseTextInputShadowNode; +}; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/conversions.h}: namespace facebook::react { -enum class AccessibilityTraits : uint32_t { - None = 0, - Button = (1 << 0), - Link = (1 << 1), - Image = (1 << 2), - Selected = (1 << 3), - PlaysSound = (1 << 4), - KeyboardKey = (1 << 5), - StaticText = (1 << 6), - SummaryElement = (1 << 7), - NotEnabled = (1 << 8), - UpdatesFrequently = (1 << 9), - SearchField = (1 << 10), - StartsMediaSession = (1 << 11), - Adjustable = (1 << 12), - AllowsDirectInteraction = (1 << 13), - CausesPageTurn = (1 << 14), - Header = (1 << 15), - Switch = (1 << 16), - TabBar = (1 << 17), -}; -constexpr enum AccessibilityTraits operator|( - const enum AccessibilityTraits lhs, - const enum AccessibilityTraits rhs) { - return (enum AccessibilityTraits)((uint32_t)lhs | (uint32_t)rhs); -} -constexpr enum AccessibilityTraits operator&( - const enum AccessibilityTraits lhs, - const enum AccessibilityTraits rhs) { - return (enum AccessibilityTraits)((uint32_t)lhs & (uint32_t)rhs); -} -struct AccessibilityAction { - std::string name{""}; - std::optional label{}; -}; -inline static bool operator==( - const AccessibilityAction& lhs, - const AccessibilityAction& rhs) { - return lhs.name == rhs.name && lhs.label == rhs.label; -} -inline static bool operator!=( - const AccessibilityAction& lhs, - const AccessibilityAction& rhs) { - return !(rhs == lhs); -} -struct AccessibilityState { - bool disabled{false}; - bool selected{false}; - bool busy{false}; - std::optional expanded{std::nullopt}; - enum { Unchecked, Checked, Mixed, None } checked{None}; -}; -constexpr bool operator==( - const AccessibilityState& lhs, - const AccessibilityState& rhs) { - return lhs.disabled == rhs.disabled && lhs.selected == rhs.selected && - lhs.checked == rhs.checked && lhs.busy == rhs.busy && - lhs.expanded == rhs.expanded; -} -constexpr bool operator!=( - const AccessibilityState& lhs, - const AccessibilityState& rhs) { - return !(rhs == lhs); +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + AutocapitalizationType& result) { + auto string = (std::string)value; + if (string == "none") { + result = AutocapitalizationType::None; + return; + } + if (string == "words") { + result = AutocapitalizationType::Words; + return; + } + if (string == "sentences") { + result = AutocapitalizationType::Sentences; + return; + } + if (string == "characters") { + result = AutocapitalizationType::Characters; + return; + } + abort(); } -struct AccessibilityLabelledBy { - std::vector value{}; -}; -inline static bool operator==( - const AccessibilityLabelledBy& lhs, - const AccessibilityLabelledBy& rhs) { - return lhs.value == rhs.value; +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + KeyboardAppearance& result) { + auto string = (std::string)value; + if (string == "default") { + result = KeyboardAppearance::Default; + return; + } + if (string == "light") { + result = KeyboardAppearance::Light; + return; + } + if (string == "dark") { + result = KeyboardAppearance::Dark; + return; + } + abort(); } -inline static bool operator!=( - const AccessibilityLabelledBy& lhs, - const AccessibilityLabelledBy& rhs) { - return !(lhs == rhs); +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + ReturnKeyType& result) { + auto string = (std::string)value; + if (string == "default") { + result = ReturnKeyType::Default; + return; + } + if (string == "done") { + result = ReturnKeyType::Done; + return; + } + if (string == "go") { + result = ReturnKeyType::Go; + return; + } + if (string == "next") { + result = ReturnKeyType::Next; + return; + } + if (string == "search") { + result = ReturnKeyType::Search; + return; + } + if (string == "send") { + result = ReturnKeyType::Send; + return; + } + if (string == "none") { + result = ReturnKeyType::None; + return; + } + if (string == "previous") { + result = ReturnKeyType::Previous; + return; + } + if (string == "emergency-call") { + result = ReturnKeyType::EmergencyCall; + return; + } + if (string == "google") { + result = ReturnKeyType::Google; + return; + } + if (string == "join") { + result = ReturnKeyType::Join; + return; + } + if (string == "route") { + result = ReturnKeyType::Route; + return; + } + if (string == "yahoo") { + result = ReturnKeyType::Yahoo; + return; + } + if (string == "continue") { + result = ReturnKeyType::Continue; + return; + } + abort(); } -struct AccessibilityValue { - std::optional min; - std::optional max; - std::optional now; - std::optional text{}; -}; -constexpr bool operator==( - const AccessibilityValue& lhs, - const AccessibilityValue& rhs) { - return lhs.min == rhs.min && lhs.max == rhs.max && lhs.now == rhs.now && - lhs.text == rhs.text; +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + TextInputAccessoryVisibilityMode& result) { + auto string = (std::string)value; + if (string == "never") { + result = TextInputAccessoryVisibilityMode::Never; + return; + } + if (string == "while-editing") { + result = TextInputAccessoryVisibilityMode::WhileEditing; + return; + } + if (string == "unless-editing") { + result = TextInputAccessoryVisibilityMode::UnlessEditing; + return; + } + if (string == "always") { + result = TextInputAccessoryVisibilityMode::Always; + return; + } + abort(); } -constexpr bool operator!=( - const AccessibilityValue& lhs, - const AccessibilityValue& rhs) { - return !(rhs == lhs); +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + KeyboardType& result) { + auto string = (std::string)value; + if (string == "default") { + result = KeyboardType::Default; + return; + } + if (string == "email-address") { + result = KeyboardType::EmailAddress; + return; + } + if (string == "numeric") { + result = KeyboardType::Numeric; + return; + } + if (string == "phone-pad") { + result = KeyboardType::PhonePad; + return; + } + if (string == "number-pad") { + result = KeyboardType::NumberPad; + return; + } + if (string == "url") { + result = KeyboardType::URL; + return; + } + if (string == "decimal-pad") { + result = KeyboardType::DecimalPad; + return; + } + if (string == "ascii-capable") { + result = KeyboardType::ASCIICapable; + return; + } + if (string == "numbers-and-punctuation") { + result = KeyboardType::NumbersAndPunctuation; + return; + } + if (string == "name-phone-pad") { + result = KeyboardType::NamePhonePad; + return; + } + if (string == "twitter") { + result = KeyboardType::Twitter; + return; + } + if (string == "web-search") { + result = KeyboardType::WebSearch; + return; + } + if (string == "ascii-capable-number-pad") { + result = KeyboardType::ASCIICapableNumberPad; + return; + } + if (string == "visible-password") { + result = KeyboardType::VisiblePassword; + return; + } + abort(); } -enum class ImportantForAccessibility : uint8_t { - Auto, - Yes, - No, - NoHideDescendants, -}; -enum class AccessibilityLiveRegion : uint8_t { +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/primitives.h}: +namespace facebook::react { +enum class AutocapitalizationType { None, - Polite, - Assertive, + Words, + Sentences, + Characters, }; -enum class AccessibilityRole { - None, - Button, - Dropdownlist, - Togglebutton, - Link, +enum class KeyboardAppearance { + Default, + Light, + Dark, +}; +enum class ReturnKeyType { + Default, + Done, + Go, + Next, + Search, + Send, + None, + Previous, + EmergencyCall, + Google, + Join, + Route, + Yahoo, + Continue, +}; +enum class TextInputAccessoryVisibilityMode { + Never, + WhileEditing, + UnlessEditing, + Always, +}; +enum class KeyboardType { + Default, + EmailAddress, + Numeric, + PhonePad, + NumberPad, + DecimalPad, + ASCIICapable, + NumbersAndPunctuation, + URL, + NamePhonePad, + Twitter, + WebSearch, + ASCIICapableNumberPad, + VisiblePassword, +}; +class Selection final { + public: + int start{0}; + int end{0}; +}; +class TextInputTraits final { + public: + AutocapitalizationType autocapitalizationType{ + AutocapitalizationType::Sentences}; + std::optional autoCorrect{}; + bool contextMenuHidden{false}; + bool editable{true}; + bool enablesReturnKeyAutomatically{false}; + KeyboardAppearance keyboardAppearance{KeyboardAppearance::Default}; + std::optional spellCheck{}; + bool caretHidden{false}; + TextInputAccessoryVisibilityMode clearButtonMode{ + TextInputAccessoryVisibilityMode::Never}; + bool scrollEnabled{true}; + bool secureTextEntry{false}; + bool clearTextOnFocus{false}; + KeyboardType keyboardType{KeyboardType::Default}; + bool showSoftInputOnFocus{true}; + ReturnKeyType returnKeyType{ReturnKeyType::Default}; + bool selectTextOnFocus{false}; + std::string textContentType{}; + std::string passwordRules{}; + std::vector submitKeyEvents{}; + bool clearTextOnSubmit{false}; + std::optional grammarCheck{}; + std::optional smartInsertDelete{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/textinput/platform/macos/react/renderer/components/iostextinput/propsConversions.h}: +namespace facebook::react { +static TextInputTraits convertRawProp( + const PropsParserContext& context, + const RawProps& rawProps, + const TextInputTraits& sourceTraits, + const TextInputTraits& defaultTraits) { + auto traits = TextInputTraits{}; + traits.autocapitalizationType = convertRawProp( + context, + rawProps, + "autoCapitalize", + sourceTraits.autocapitalizationType, + defaultTraits.autocapitalizationType); + traits.autoCorrect = convertRawProp( + context, + rawProps, + "autoCorrect", + sourceTraits.autoCorrect, + defaultTraits.autoCorrect); + traits.contextMenuHidden = convertRawProp( + context, + rawProps, + "contextMenuHidden", + sourceTraits.contextMenuHidden, + defaultTraits.contextMenuHidden); + traits.editable = convertRawProp( + context, + rawProps, + "editable", + sourceTraits.editable, + defaultTraits.editable); + traits.enablesReturnKeyAutomatically = convertRawProp( + context, + rawProps, + "enablesReturnKeyAutomatically", + sourceTraits.enablesReturnKeyAutomatically, + defaultTraits.enablesReturnKeyAutomatically); + traits.keyboardAppearance = convertRawProp( + context, + rawProps, + "keyboardAppearance", + sourceTraits.keyboardAppearance, + defaultTraits.keyboardAppearance); + traits.spellCheck = convertRawProp( + context, + rawProps, + "spellCheck", + sourceTraits.spellCheck, + defaultTraits.spellCheck); + traits.caretHidden = convertRawProp( + context, + rawProps, + "caretHidden", + sourceTraits.caretHidden, + defaultTraits.caretHidden); + traits.clearButtonMode = convertRawProp( + context, + rawProps, + "clearButtonMode", + sourceTraits.clearButtonMode, + defaultTraits.clearButtonMode); + traits.scrollEnabled = convertRawProp( + context, + rawProps, + "scrollEnabled", + sourceTraits.scrollEnabled, + defaultTraits.scrollEnabled); + traits.secureTextEntry = convertRawProp( + context, + rawProps, + "secureTextEntry", + sourceTraits.secureTextEntry, + defaultTraits.secureTextEntry); + traits.clearTextOnFocus = convertRawProp( + context, + rawProps, + "clearTextOnFocus", + sourceTraits.clearTextOnFocus, + defaultTraits.clearTextOnFocus); + traits.keyboardType = convertRawProp( + context, + rawProps, + "keyboardType", + sourceTraits.keyboardType, + defaultTraits.keyboardType); + traits.showSoftInputOnFocus = convertRawProp( + context, + rawProps, + "showSoftInputOnFocus", + sourceTraits.showSoftInputOnFocus, + defaultTraits.showSoftInputOnFocus); + traits.returnKeyType = convertRawProp( + context, + rawProps, + "returnKeyType", + sourceTraits.returnKeyType, + defaultTraits.returnKeyType); + traits.selectTextOnFocus = convertRawProp( + context, + rawProps, + "selectTextOnFocus", + sourceTraits.selectTextOnFocus, + defaultTraits.selectTextOnFocus); + traits.textContentType = convertRawProp( + context, + rawProps, + "textContentType", + sourceTraits.textContentType, + defaultTraits.textContentType); + traits.passwordRules = convertRawProp( + context, + rawProps, + "passwordRules", + sourceTraits.passwordRules, + defaultTraits.passwordRules); + traits.grammarCheck = convertRawProp( + context, + rawProps, + "grammarCheck", + sourceTraits.grammarCheck, + defaultTraits.grammarCheck); + traits.smartInsertDelete = convertRawProp( + context, + rawProps, + "smartInsertDelete", + sourceTraits.smartInsertDelete, + defaultTraits.smartInsertDelete); + return traits; +} +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + Selection& result) { + if (value.hasType>()) { + auto map = (std::unordered_map)value; + for (const auto& pair : map) { + if (pair.first == "start") { + result.start = pair.second; + } else if (pair.first == "end") { + result.end = pair.second; + } else { + LOG(ERROR) << "Unsupported Selection map key: " << pair.first; + react_native_expect(false); + } + } + return; + } + react_native_expect(value.hasType>()); + if (value.hasType>()) { + auto array = (std::vector)value; + react_native_expect(array.size() == 2); + if (array.size() >= 2) { + result = {array.at(0), array.at(1)}; + } else { + result = {0, 0}; + LOG(ERROR) << "Unsupported Selection vector size: " << array.size(); + } + } else { + LOG(ERROR) << "Unsupported Selection type"; + } +} +static inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + KeyEvent& result) { + auto map = (std::unordered_map)value; + auto tmp_key = map.find("key"); + if (tmp_key != map.end()) { + fromRawValue(context, tmp_key->second, result.key); + } + auto tmp_altKey = map.find("altKey"); + if (tmp_altKey != map.end()) { + fromRawValue(context, tmp_altKey->second, result.altKey); + } + auto tmp_shiftKey = map.find("shiftKey"); + if (tmp_shiftKey != map.end()) { + fromRawValue(context, tmp_shiftKey->second, result.shiftKey); + } + auto tmp_ctrlKey = map.find("ctrlKey"); + if (tmp_ctrlKey != map.end()) { + fromRawValue(context, tmp_ctrlKey->second, result.ctrlKey); + } + auto tmp_metaKey = map.find("metaKey"); + if (tmp_metaKey != map.end()) { + fromRawValue(context, tmp_metaKey->second, result.metaKey); + } + auto tmp_functionKey = map.find("functionKey"); + if (tmp_functionKey != map.end()) { + fromRawValue(context, tmp_functionKey->second, result.functionKey); + } +} +static inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + auto items = (std::vector)value; + for (const auto& item : items) { + KeyEvent newItem; + fromRawValue(context, item, newItem); + result.emplace_back(newItem); + } +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.h}: +namespace facebook::react { +class UnimplementedViewComponentDescriptor final + : public ConcreteComponentDescriptor { + public: + using ConcreteComponentDescriptor::ConcreteComponentDescriptor; + ComponentHandle getComponentHandle() const override; + ComponentName getComponentName() const override; + Props::Shared cloneProps( + const PropsParserContext& context, + const Props::Shared& props, + RawProps rawProps) const override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewProps.h}: +namespace facebook::react { +class UnimplementedViewProps final : public ViewProps { + public: + using ViewProps::ViewProps; + void setComponentName(ComponentName componentName); + ComponentName getComponentName() const; +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewShadowNode.h}: +namespace facebook::react { +extern const char UnimplementedViewComponentName[]; +using UnimplementedViewShadowNode = ConcreteViewShadowNode< + UnimplementedViewComponentName, + UnimplementedViewProps>; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h}: +namespace facebook::react { +enum class AccessibilityTraits : uint32_t { + None = 0, + Button = (1 << 0), + Link = (1 << 1), + Image = (1 << 2), + Selected = (1 << 3), + PlaysSound = (1 << 4), + KeyboardKey = (1 << 5), + StaticText = (1 << 6), + SummaryElement = (1 << 7), + NotEnabled = (1 << 8), + UpdatesFrequently = (1 << 9), + SearchField = (1 << 10), + StartsMediaSession = (1 << 11), + Adjustable = (1 << 12), + AllowsDirectInteraction = (1 << 13), + CausesPageTurn = (1 << 14), + Header = (1 << 15), + Switch = (1 << 16), + TabBar = (1 << 17), +}; +constexpr enum AccessibilityTraits operator|( + const enum AccessibilityTraits lhs, + const enum AccessibilityTraits rhs) { + return (enum AccessibilityTraits)((uint32_t)lhs | (uint32_t)rhs); +} +constexpr enum AccessibilityTraits operator&( + const enum AccessibilityTraits lhs, + const enum AccessibilityTraits rhs) { + return (enum AccessibilityTraits)((uint32_t)lhs & (uint32_t)rhs); +} +struct AccessibilityAction { + std::string name; + std::optional label{}; +}; +inline std::string toString(const AccessibilityAction& accessibilityAction) { + std::string result = accessibilityAction.name; + if (accessibilityAction.label.has_value()) { + result += ": '" + accessibilityAction.label.value() + "'"; + } + return result; +} +inline std::string toString( + std::vector accessibilityActions) { + std::string result = "["; + for (size_t i = 0; i < accessibilityActions.size(); i++) { + result += toString(accessibilityActions[i]); + if (i < accessibilityActions.size() - 1) { + result += ", "; + } + } + result += "]"; + return result; +} +inline static bool operator==( + const AccessibilityAction& lhs, + const AccessibilityAction& rhs) { + return lhs.name == rhs.name && lhs.label == rhs.label; +} +inline static bool operator!=( + const AccessibilityAction& lhs, + const AccessibilityAction& rhs) { + return !(rhs == lhs); +} +struct AccessibilityState { + bool disabled{false}; + bool selected{false}; + bool busy{false}; + std::optional expanded{std::nullopt}; + enum { Unchecked, Checked, Mixed, None } checked{None}; +}; +constexpr bool operator==( + const AccessibilityState& lhs, + const AccessibilityState& rhs) { + return lhs.disabled == rhs.disabled && lhs.selected == rhs.selected && + lhs.checked == rhs.checked && lhs.busy == rhs.busy && + lhs.expanded == rhs.expanded; +} +constexpr bool operator!=( + const AccessibilityState& lhs, + const AccessibilityState& rhs) { + return !(rhs == lhs); +} +struct AccessibilityLabelledBy { + std::vector value{}; +}; +inline static bool operator==( + const AccessibilityLabelledBy& lhs, + const AccessibilityLabelledBy& rhs) { + return lhs.value == rhs.value; +} +inline static bool operator!=( + const AccessibilityLabelledBy& lhs, + const AccessibilityLabelledBy& rhs) { + return !(lhs == rhs); +} +struct AccessibilityValue { + std::optional min; + std::optional max; + std::optional now; + std::optional text{}; +}; +constexpr bool operator==( + const AccessibilityValue& lhs, + const AccessibilityValue& rhs) { + return lhs.min == rhs.min && lhs.max == rhs.max && lhs.now == rhs.now && + lhs.text == rhs.text; +} +constexpr bool operator!=( + const AccessibilityValue& lhs, + const AccessibilityValue& rhs) { + return !(rhs == lhs); +} +enum class ImportantForAccessibility : uint8_t { + Auto, + Yes, + No, + NoHideDescendants, +}; +enum class AccessibilityLiveRegion : uint8_t { + None, + Polite, + Assertive, +}; +inline std::string toString( + const AccessibilityLiveRegion& accessibilityLiveRegion) { + switch (accessibilityLiveRegion) { + case AccessibilityLiveRegion::None: + return "none"; + case AccessibilityLiveRegion::Polite: + return "polite"; + case AccessibilityLiveRegion::Assertive: + return "assertive"; + } +} +enum class AccessibilityRole { + None, + Button, + Dropdownlist, + Togglebutton, + Link, Search, Image, Keyboardkey, @@ -20659,21 +22598,23 @@ class AccessibilityProps { const RawValue& value); bool accessible{false}; std::optional accessibilityState{std::nullopt}; - std::string accessibilityLabel{""}; + std::string accessibilityLabel; + std::vector accessibilityOrder{}; AccessibilityLabelledBy accessibilityLabelledBy{}; AccessibilityLiveRegion accessibilityLiveRegion{ AccessibilityLiveRegion::None}; AccessibilityTraits accessibilityTraits{AccessibilityTraits::None}; - std::string accessibilityRole{""}; - std::string accessibilityHint{""}; - std::string accessibilityLanguage{""}; - std::string accessibilityLargeContentTitle{""}; + std::string accessibilityRole; + std::string accessibilityHint; + std::string accessibilityLanguage; + std::string accessibilityLargeContentTitle; AccessibilityValue accessibilityValue; std::vector accessibilityActions{}; bool accessibilityShowsLargeContentViewer{false}; bool accessibilityViewIsModal{false}; bool accessibilityElementsHidden{false}; bool accessibilityIgnoresInvertColors{false}; + bool accessibilityRespondsToUserInteraction{true}; bool onAccessibilityTap{}; bool onAccessibilityMagicTap{}; bool onAccessibilityEscape{}; @@ -20681,7 +22622,7 @@ class AccessibilityProps { ImportantForAccessibility importantForAccessibility{ ImportantForAccessibility::Auto}; Role role{Role::None}; - std::string testId{""}; + std::string testId; }; } // namespace facebook::react @@ -20794,121 +22735,736 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/components/view/ConcreteViewShadowNode.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/BoxShadowPropsConversions.h}: namespace facebook::react { -template < - const char* concreteComponentName, - typename ViewPropsT = ViewProps, - typename ViewEventEmitterT = ViewEventEmitter, - typename StateDataT = StateData, - bool usesMapBufferForStateData = false> -class ConcreteViewShadowNode : public ConcreteShadowNode< - concreteComponentName, - YogaLayoutableShadowNode, - ViewPropsT, - ViewEventEmitterT, - StateDataT, - usesMapBufferForStateData> { - static_assert( - std::is_base_of::value, - "ViewPropsT must be a descendant of ViewProps"); - static_assert( - std::is_base_of::value, - "ViewPropsT must be a descendant of YogaStylableProps"); - static_assert( - std::is_base_of::value, - "ViewPropsT must be a descendant of AccessibilityProps"); - - public: - using BaseShadowNode = ConcreteShadowNode< - concreteComponentName, - YogaLayoutableShadowNode, - ViewPropsT, - ViewEventEmitterT, - StateDataT, - usesMapBufferForStateData>; - ConcreteViewShadowNode( - const ShadowNodeFragment& fragment, - const ShadowNodeFamily::Shared& family, - ShadowNodeTraits traits) - : BaseShadowNode(fragment, family, traits) { - initialize(); - } - ConcreteViewShadowNode( - const ShadowNode& sourceShadowNode, - const ShadowNodeFragment& fragment) - : BaseShadowNode(sourceShadowNode, fragment) { - initialize(); - } - using ConcreteViewProps = ViewPropsT; - using BaseShadowNode::BaseShadowNode; - static ShadowNodeTraits BaseTraits() { - auto traits = BaseShadowNode::BaseTraits(); - traits.set(ShadowNodeTraits::Trait::ViewKind); - traits.set(ShadowNodeTraits::Trait::FormsStackingContext); - traits.set(ShadowNodeTraits::Trait::FormsView); - return traits; - } - Transform getTransform() const override { - auto layoutMetrics = BaseShadowNode::getLayoutMetrics(); - return BaseShadowNode::getConcreteProps().resolveTransform(layoutMetrics); - } - bool canBeTouchTarget() const override { - auto pointerEvents = - BaseShadowNode::getConcreteProps().ViewProps::pointerEvents; - return pointerEvents == PointerEventsMode::Auto || - pointerEvents == PointerEventsMode::BoxOnly; - } - bool canChildrenBeTouchTarget() const override { - auto pointerEvents = - BaseShadowNode::getConcreteProps().ViewProps::pointerEvents; - return pointerEvents == PointerEventsMode::Auto || - pointerEvents == PointerEventsMode::BoxNone; +inline void parseProcessedBoxShadow( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + react_native_expect(value.hasType>()); + if (!value.hasType>()) { + result = {}; + return; } -}; -} // namespace facebook::react - -/// @src {packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceComponentDescriptor.h}: -namespace facebook::react { -using LayoutConformanceComponentDescriptor = - ConcreteComponentDescriptor; -} - -/// @src {packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceProps.h}: -namespace facebook::react { -struct LayoutConformanceProps final : public YogaStylableProps { - LayoutConformance mode{LayoutConformance::Strict}; - LayoutConformanceProps() = default; - LayoutConformanceProps( - const PropsParserContext& context, - const LayoutConformanceProps& sourceProps, - const RawProps& rawProps) - : YogaStylableProps(context, sourceProps, rawProps), - mode{convertRawProp( - context, - rawProps, - "mode", - mode, - LayoutConformance::Strict)} {} -}; -} // namespace facebook::react - -/// @src {packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceShadowNode.h}: -namespace facebook::react { -constexpr const char LayoutConformanceShadowNodeComponentName[] = - "LayoutConformance"; -class LayoutConformanceShadowNode final - : public ConcreteShadowNode< - LayoutConformanceShadowNodeComponentName, - YogaLayoutableShadowNode, - LayoutConformanceProps> { - public: - using ConcreteShadowNode::ConcreteShadowNode; -}; -} // namespace facebook::react - -/// @src {packages/react-native/ReactCommon/react/renderer/components/view/PointerEvent.h}: -namespace facebook::react { + std::vector boxShadows{}; + auto rawBoxShadows = static_cast>(value); + for (const auto& rawBoxShadow : rawBoxShadows) { + bool isMap = + rawBoxShadow.hasType>(); + react_native_expect(isMap); + if (!isMap) { + result = {}; + return; + } + auto rawBoxShadowMap = + static_cast>(rawBoxShadow); + BoxShadow boxShadow{}; + auto offsetX = rawBoxShadowMap.find("offsetX"); + react_native_expect(offsetX != rawBoxShadowMap.end()); + if (offsetX == rawBoxShadowMap.end()) { + result = {}; + return; + } + react_native_expect(offsetX->second.hasType()); + if (!offsetX->second.hasType()) { + result = {}; + return; + } + boxShadow.offsetX = (Float)offsetX->second; + auto offsetY = rawBoxShadowMap.find("offsetY"); + react_native_expect(offsetY != rawBoxShadowMap.end()); + if (offsetY == rawBoxShadowMap.end()) { + result = {}; + return; + } + react_native_expect(offsetY->second.hasType()); + if (!offsetY->second.hasType()) { + result = {}; + return; + } + boxShadow.offsetY = (Float)offsetY->second; + auto blurRadius = rawBoxShadowMap.find("blurRadius"); + if (blurRadius != rawBoxShadowMap.end()) { + react_native_expect(blurRadius->second.hasType()); + if (!blurRadius->second.hasType()) { + result = {}; + return; + } + boxShadow.blurRadius = (Float)blurRadius->second; + } + auto spreadDistance = rawBoxShadowMap.find("spreadDistance"); + if (spreadDistance != rawBoxShadowMap.end()) { + react_native_expect(spreadDistance->second.hasType()); + if (!spreadDistance->second.hasType()) { + result = {}; + return; + } + boxShadow.spreadDistance = (Float)spreadDistance->second; + } + auto inset = rawBoxShadowMap.find("inset"); + if (inset != rawBoxShadowMap.end()) { + react_native_expect(inset->second.hasType()); + if (!inset->second.hasType()) { + result = {}; + return; + } + boxShadow.inset = (bool)inset->second; + } + auto color = rawBoxShadowMap.find("color"); + if (color != rawBoxShadowMap.end()) { + fromRawValue( + context.contextContainer, + context.surfaceId, + color->second, + boxShadow.color); + } + boxShadows.push_back(boxShadow); + } + result = boxShadows; +} +inline std::optional fromCSSShadow(const CSSShadow& cssShadow) { + if (cssShadow.offsetX.unit != CSSLengthUnit::Px || + cssShadow.offsetY.unit != CSSLengthUnit::Px || + cssShadow.blurRadius.unit != CSSLengthUnit::Px || + cssShadow.spreadDistance.unit != CSSLengthUnit::Px) { + return {}; + } + return BoxShadow{ + .offsetX = cssShadow.offsetX.value, + .offsetY = cssShadow.offsetY.value, + .blurRadius = cssShadow.blurRadius.value, + .spreadDistance = cssShadow.spreadDistance.value, + .color = fromCSSColor(cssShadow.color), + .inset = cssShadow.inset, + }; +} +inline void parseUnprocessedBoxShadowString( + std::string&& value, + std::vector& result) { + auto boxShadowList = parseCSSProperty((std::string)value); + if (!std::holds_alternative(boxShadowList)) { + result = {}; + return; + } + for (const auto& cssShadow : std::get(boxShadowList)) { + if (auto boxShadow = fromCSSShadow(cssShadow)) { + result.push_back(*boxShadow); + } else { + result = {}; + return; + } + } +} +inline std::optional parseBoxShadowRawValue( + const PropsParserContext& context, + const RawValue& value) { + if (!value.hasType>()) { + return {}; + } + auto boxShadow = std::unordered_map(value); + auto rawOffsetX = boxShadow.find("offsetX"); + if (rawOffsetX == boxShadow.end()) { + return {}; + } + auto offsetX = coerceLength(rawOffsetX->second); + if (!offsetX.has_value()) { + return {}; + } + auto rawOffsetY = boxShadow.find("offsetY"); + if (rawOffsetY == boxShadow.end()) { + return {}; + } + auto offsetY = coerceLength(rawOffsetY->second); + if (!offsetY.has_value()) { + return {}; + } + Float blurRadius = 0; + auto rawBlurRadius = boxShadow.find("blurRadius"); + if (rawBlurRadius != boxShadow.end()) { + if (auto blurRadiusValue = coerceLength(rawBlurRadius->second)) { + if (*blurRadiusValue < 0) { + return {}; + } + blurRadius = *blurRadiusValue; + } else { + return {}; + } + } + Float spreadDistance = 0; + auto rawSpreadDistance = boxShadow.find("spreadDistance"); + if (rawSpreadDistance != boxShadow.end()) { + if (auto spreadDistanceValue = coerceLength(rawSpreadDistance->second)) { + spreadDistance = *spreadDistanceValue; + } else { + return {}; + } + } + bool inset = false; + auto rawInset = boxShadow.find("inset"); + if (rawInset != boxShadow.end()) { + if (rawInset->second.hasType()) { + inset = (bool)rawInset->second; + } else { + return {}; + } + } + SharedColor color; + auto rawColor = boxShadow.find("color"); + if (rawColor != boxShadow.end()) { + color = coerceColor(rawColor->second, context); + if (!color) { + return {}; + } + } + return BoxShadow{ + .offsetX = *offsetX, + .offsetY = *offsetY, + .blurRadius = blurRadius, + .spreadDistance = spreadDistance, + .color = color, + .inset = inset}; +} +inline void parseUnprocessedBoxShadowList( + const PropsParserContext& context, + std::vector&& value, + std::vector& result) { + for (const auto& rawValue : value) { + if (auto boxShadow = parseBoxShadowRawValue(context, rawValue)) { + result.push_back(*boxShadow); + } else { + result = {}; + return; + } + } +} +inline void parseUnprocessedBoxShadow( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + if (value.hasType()) { + parseUnprocessedBoxShadowString((std::string)value, result); + } else if (value.hasType>()) { + parseUnprocessedBoxShadowList( + context, (std::vector)value, result); + } else { + result = {}; + } +} +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + if (ReactNativeFeatureFlags::enableNativeCSSParsing()) { + parseUnprocessedBoxShadow(context, value, result); + } else { + parseProcessedBoxShadow(context, value, result); + } +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/CSSConversions.h}: +namespace facebook::react { +inline SharedColor fromCSSColor(const CSSColor& cssColor) { + return hostPlatformColorFromRGBA( + cssColor.r, cssColor.g, cssColor.b, cssColor.a); +} +inline std::optional coerceAmount(const RawValue& value) { + if (value.hasType()) { + return (Float)value; + } + if (value.hasType()) { + auto cssVal = + parseCSSProperty((std::string)value); + if (std::holds_alternative(cssVal)) { + return std::get(cssVal).value; + } else if (std::holds_alternative(cssVal)) { + return std::get(cssVal).value / 100.0f; + } + } + return {}; +} +inline std::optional coerceAngle(const RawValue& value) { + if (value.hasType()) { + return (Float)value; + } + if (value.hasType()) { + auto cssVal = parseCSSProperty((std::string)value); + if (std::holds_alternative(cssVal)) { + return std::get(cssVal).degrees; + } + } + return {}; +} +inline SharedColor coerceColor( + const RawValue& value, + const PropsParserContext& context) { + if (value.hasType()) { + auto cssColor = parseCSSProperty((std::string)value); + if (!std::holds_alternative(cssColor)) { + return {}; + } + return fromCSSColor(std::get(cssColor)); + } + SharedColor color; + fromRawValue(context.contextContainer, context.surfaceId, value, color); + return color; +} +inline std::optional coerceLength(const RawValue& value) { + if (value.hasType()) { + return (Float)value; + } + if (value.hasType()) { + auto len = parseCSSProperty((std::string)value); + if (!std::holds_alternative(len)) { + return {}; + } + auto cssLen = std::get(len); + if (cssLen.unit != CSSLengthUnit::Px) { + return {}; + } + return cssLen.value; + } + return {}; +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/ConcreteViewShadowNode.h}: +namespace facebook::react { +template < + const char* concreteComponentName, + typename ViewPropsT = ViewProps, + typename ViewEventEmitterT = ViewEventEmitter, + typename StateDataT = StateData> + requires(std::is_base_of_v) +class ConcreteViewShadowNode : public ConcreteShadowNode< + concreteComponentName, + YogaLayoutableShadowNode, + ViewPropsT, + ViewEventEmitterT, + StateDataT> { + static_assert( + std::is_base_of::value, + "ViewPropsT must be a descendant of ViewProps"); + static_assert( + std::is_base_of::value, + "ViewPropsT must be a descendant of YogaStylableProps"); + static_assert( + std::is_base_of::value, + "ViewPropsT must be a descendant of AccessibilityProps"); + + public: + using BaseShadowNode = ConcreteShadowNode< + concreteComponentName, + YogaLayoutableShadowNode, + ViewPropsT, + ViewEventEmitterT, + StateDataT>; + ConcreteViewShadowNode( + const ShadowNodeFragment& fragment, + const ShadowNodeFamily::Shared& family, + ShadowNodeTraits traits) + : BaseShadowNode(fragment, family, traits) { + initialize(); + } + ConcreteViewShadowNode( + const ShadowNode& sourceShadowNode, + const ShadowNodeFragment& fragment) + : BaseShadowNode(sourceShadowNode, fragment) { + initialize(); + } + using ConcreteViewProps = ViewPropsT; + using BaseShadowNode::BaseShadowNode; + static ShadowNodeTraits BaseTraits() { + auto traits = BaseShadowNode::BaseTraits(); + traits.set(ShadowNodeTraits::Trait::ViewKind); + traits.set(ShadowNodeTraits::Trait::FormsStackingContext); + traits.set(ShadowNodeTraits::Trait::FormsView); + return traits; + } + Transform getTransform() const override { + auto layoutMetrics = BaseShadowNode::getLayoutMetrics(); + return BaseShadowNode::getConcreteProps().resolveTransform(layoutMetrics); + } + bool canBeTouchTarget() const override { + auto pointerEvents = + BaseShadowNode::getConcreteProps().ViewProps::pointerEvents; + return pointerEvents == PointerEventsMode::Auto || + pointerEvents == PointerEventsMode::BoxOnly; + } + bool canChildrenBeTouchTarget() const override { + auto pointerEvents = + BaseShadowNode::getConcreteProps().ViewProps::pointerEvents; + return pointerEvents == PointerEventsMode::Auto || + pointerEvents == PointerEventsMode::BoxNone; + } +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/FilterPropsConversions.h}: +namespace facebook::react { +inline void parseProcessedFilter( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + react_native_expect(value.hasType>()); + if (!value.hasType>()) { + result = {}; + return; + } + std::vector filter{}; + auto rawFilter = static_cast>(value); + for (const auto& rawFilterPrimitive : rawFilter) { + bool isMap = + rawFilterPrimitive.hasType>(); + react_native_expect(isMap); + if (!isMap) { + result = {}; + return; + } + auto rawFilterFunction = + static_cast>( + rawFilterPrimitive); + FilterFunction filterFunction{}; + try { + filterFunction.type = + filterTypeFromString(rawFilterFunction.begin()->first); + if (filterFunction.type == FilterType::DropShadow) { + auto rawDropShadow = + static_cast>( + rawFilterFunction.begin()->second); + DropShadowParams dropShadowParams{}; + auto offsetX = rawDropShadow.find("offsetX"); + react_native_expect(offsetX != rawDropShadow.end()); + if (offsetX == rawDropShadow.end()) { + result = {}; + return; + } + react_native_expect(offsetX->second.hasType()); + if (!offsetX->second.hasType()) { + result = {}; + return; + } + dropShadowParams.offsetX = (Float)offsetX->second; + auto offsetY = rawDropShadow.find("offsetY"); + react_native_expect(offsetY != rawDropShadow.end()); + if (offsetY == rawDropShadow.end()) { + result = {}; + return; + } + react_native_expect(offsetY->second.hasType()); + if (!offsetY->second.hasType()) { + result = {}; + return; + } + dropShadowParams.offsetY = (Float)offsetY->second; + auto standardDeviation = rawDropShadow.find("standardDeviation"); + if (standardDeviation != rawDropShadow.end()) { + react_native_expect(standardDeviation->second.hasType()); + if (!standardDeviation->second.hasType()) { + result = {}; + return; + } + dropShadowParams.standardDeviation = (Float)standardDeviation->second; + } + auto color = rawDropShadow.find("color"); + if (color != rawDropShadow.end()) { + fromRawValue( + context.contextContainer, + context.surfaceId, + color->second, + dropShadowParams.color); + } + filterFunction.parameters = dropShadowParams; + } else { + filterFunction.parameters = (float)rawFilterFunction.begin()->second; + } + filter.push_back(std::move(filterFunction)); + } catch (const std::exception& e) { + LOG(ERROR) << "Could not parse FilterFunction: " << e.what(); + result = {}; + return; + } + } + result = filter; +} +inline FilterType filterTypeFromVariant( + const CSSFilterFunctionVariant& filter) { + return std::visit( + [](auto&& filter) -> FilterType { + using FilterT = std::decay_t; + if constexpr (std::is_same_v) { + return FilterType::Blur; + } + if constexpr (std::is_same_v) { + return FilterType::Brightness; + } + if constexpr (std::is_same_v) { + return FilterType::Contrast; + } + if constexpr (std::is_same_v) { + return FilterType::DropShadow; + } + if constexpr (std::is_same_v) { + return FilterType::Grayscale; + } + if constexpr (std::is_same_v) { + return FilterType::HueRotate; + } + if constexpr (std::is_same_v) { + return FilterType::Invert; + } + if constexpr (std::is_same_v) { + return FilterType::Opacity; + } + if constexpr (std::is_same_v) { + return FilterType::Saturate; + } + if constexpr (std::is_same_v) { + return FilterType::Sepia; + } + }, + filter); +} +inline std::optional fromCSSFilter( + const CSSFilterFunctionVariant& cssFilter) { + return std::visit( + [&](auto&& filter) -> std::optional { + using FilterT = std::decay_t; + if constexpr (std::is_same_v) { + if (filter.amount.unit != CSSLengthUnit::Px) { + return {}; + } + return FilterFunction{ + .type = filterTypeFromVariant(cssFilter), + .parameters = filter.amount.value, + }; + } + if constexpr (std::is_same_v) { + if (filter.offsetX.unit != CSSLengthUnit::Px || + filter.offsetY.unit != CSSLengthUnit::Px || + filter.standardDeviation.unit != CSSLengthUnit::Px) { + return {}; + } + return FilterFunction{ + .type = FilterType::DropShadow, + .parameters = DropShadowParams{ + .offsetX = filter.offsetX.value, + .offsetY = filter.offsetY.value, + .standardDeviation = filter.standardDeviation.value, + .color = fromCSSColor(filter.color), + }}; + } + if constexpr ( + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) { + return FilterFunction{ + .type = filterTypeFromVariant(cssFilter), + .parameters = filter.amount, + }; + } + if constexpr (std::is_same_v) { + return FilterFunction{ + .type = filterTypeFromVariant(cssFilter), + .parameters = filter.degrees, + }; + } + }, + cssFilter); +} +inline void parseUnprocessedFilterString( + std::string&& value, + std::vector& result) { + auto filterList = parseCSSProperty((std::string)value); + if (!std::holds_alternative(filterList)) { + result = {}; + return; + } + for (const auto& cssFilter : std::get(filterList)) { + if (auto filter = fromCSSFilter(cssFilter)) { + result.push_back(*filter); + } else { + result = {}; + return; + } + } +} +inline std::optional parseDropShadow( + const PropsParserContext& context, + const RawValue& value) { + if (value.hasType()) { + auto val = parseCSSProperty( + std::string("drop-shadow(") + (std::string)value + ")"); + if (std::holds_alternative(val)) { + return fromCSSFilter(std::get(val)); + } + return {}; + } + if (!value.hasType>()) { + return {}; + } + auto rawDropShadow = + static_cast>(value); + DropShadowParams dropShadowParams{}; + auto offsetX = rawDropShadow.find("offsetX"); + if (offsetX == rawDropShadow.end()) { + return {}; + } + if (auto parsedOffsetX = coerceLength(offsetX->second)) { + dropShadowParams.offsetX = *parsedOffsetX; + } else { + return {}; + } + auto offsetY = rawDropShadow.find("offsetY"); + if (offsetY == rawDropShadow.end()) { + return {}; + } + if (auto parsedOffsetY = coerceLength(offsetY->second)) { + dropShadowParams.offsetY = *parsedOffsetY; + } else { + return {}; + } + auto standardDeviation = rawDropShadow.find("standardDeviation"); + if (standardDeviation != rawDropShadow.end()) { + if (auto parsedStandardDeviation = + coerceLength(standardDeviation->second)) { + if (*parsedStandardDeviation < 0.0f) { + return {}; + } + dropShadowParams.standardDeviation = *parsedStandardDeviation; + } else { + return {}; + } + } + auto color = rawDropShadow.find("color"); + if (color != rawDropShadow.end()) { + if (auto parsedColor = coerceColor(color->second, context)) { + dropShadowParams.color = *parsedColor; + } else { + return {}; + } + } + return FilterFunction{FilterType::DropShadow, dropShadowParams}; +} +inline std::optional parseFilterRawValue( + const PropsParserContext& context, + const RawValue& value) { + if (!value.hasType>()) { + return {}; + } + auto rawFilter = + static_cast>(value); + if (rawFilter.size() != 1) { + return {}; + } + const auto& filterKey = rawFilter.begin()->first; + if (filterKey == "drop-shadow") { + return parseDropShadow(context, rawFilter.begin()->second); + } else if (filterKey == "blur") { + if (auto length = coerceLength(rawFilter.begin()->second)) { + if (*length < 0.0f) { + return {}; + } + return FilterFunction{FilterType::Blur, *length}; + } + return {}; + } else if (filterKey == "hue-rotate") { + if (auto angle = coerceAngle(rawFilter.begin()->second)) { + return FilterFunction{FilterType::HueRotate, *angle}; + } + return {}; + } else { + if (auto amount = coerceAmount(rawFilter.begin()->second)) { + if (*amount < 0.0f) { + return {}; + } + return FilterFunction{filterTypeFromString(filterKey), *amount}; + } + return {}; + } +} +inline void parseUnprocessedFilterList( + const PropsParserContext& context, + std::vector&& value, + std::vector& result) { + for (const auto& rawValue : value) { + if (auto Filter = parseFilterRawValue(context, rawValue)) { + result.push_back(*Filter); + } else { + result = {}; + return; + } + } +} +inline void parseUnprocessedFilter( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + if (value.hasType()) { + parseUnprocessedFilterString((std::string)value, result); + } else if (value.hasType>()) { + parseUnprocessedFilterList(context, (std::vector)value, result); + } else { + result = {}; + } +} +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + std::vector& result) { + if (ReactNativeFeatureFlags::enableNativeCSSParsing()) { + parseUnprocessedFilter(context, value, result); + } else { + parseProcessedFilter(context, value, result); + } +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceComponentDescriptor.h}: +namespace facebook::react { +using LayoutConformanceComponentDescriptor = + ConcreteComponentDescriptor; +} + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceProps.h}: +namespace facebook::react { +struct LayoutConformanceProps final : public YogaStylableProps { + LayoutConformance mode{LayoutConformance::Strict}; + LayoutConformanceProps() = default; + LayoutConformanceProps( + const PropsParserContext& context, + const LayoutConformanceProps& sourceProps, + const RawProps& rawProps) + : YogaStylableProps(context, sourceProps, rawProps), + mode{convertRawProp( + context, + rawProps, + "mode", + mode, + LayoutConformance::Strict)} {} +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/LayoutConformanceShadowNode.h}: +namespace facebook::react { +constexpr const char LayoutConformanceShadowNodeComponentName[] = + "LayoutConformance"; +class LayoutConformanceShadowNode final + : public ConcreteShadowNode< + LayoutConformanceShadowNodeComponentName, + YogaLayoutableShadowNode, + LayoutConformanceProps> { + public: + using ConcreteShadowNode::ConcreteShadowNode; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/PointerEvent.h}: +namespace facebook::react { struct PointerEvent : public EventPayload { int pointerId; Float pressure; @@ -21059,6 +23615,9 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode { YogaLayoutableShadowNode( const ShadowNode& sourceShadowNode, const ShadowNodeFragment& fragment); + void completeClone( + const ShadowNode& sourceShadowNode, + const ShadowNodeFragment& fragment) override; void enableMeasurement(); void appendChild(const ShadowNode::Shared& child) override; void replaceChild( @@ -21070,7 +23629,6 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode { void setSize(Size size) const; void setPadding(RectangleEdges padding) const; void setPositionType(YGPositionType positionType) const; - void cleanLayout() override; void dirtyLayout() override; bool getIsLayoutClean() const override; void layoutTree( @@ -21078,9 +23636,11 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode { LayoutConstraints layoutConstraints) override; void layout(LayoutContext layoutContext) override; Rect getContentBounds() const; - static void filterRawProps(RawProps& rawProps); protected: + virtual bool shouldNewRevisionDirtyMeasurement( + const ShadowNode& sourceShadowNode, + const ShadowNodeFragment& fragment) const; yoga::Config yogaConfig_; mutable yoga::Node yogaNode_; }; @@ -22242,19 +24802,15 @@ inline void fromRawValue( result = yoga::StyleSizeLength::ofFitContent(); return; } else { - if (stringValue.back() == '%') { - auto tryValue = folly::tryTo( - std::string_view(stringValue).substr(0, stringValue.length() - 1)); - if (tryValue.hasValue()) { - result = yoga::StyleSizeLength::percent(tryValue.value()); - return; - } - } else { - auto tryValue = folly::tryTo(stringValue); - if (tryValue.hasValue()) { - result = yoga::StyleSizeLength::points(tryValue.value()); - return; - } + auto parsed = parseCSSProperty(stringValue); + if (std::holds_alternative(parsed)) { + result = yoga::StyleSizeLength::percent( + std::get(parsed).value); + return; + } else if (std::holds_alternative(parsed)) { + result = + yoga::StyleSizeLength::points(std::get(parsed).value); + return; } } } @@ -22273,19 +24829,14 @@ inline void fromRawValue( result = yoga::StyleLength::ofAuto(); return; } else { - if (stringValue.back() == '%') { - auto tryValue = folly::tryTo( - std::string_view(stringValue).substr(0, stringValue.length() - 1)); - if (tryValue.hasValue()) { - result = yoga::StyleLength::percent(tryValue.value()); - return; - } - } else { - auto tryValue = folly::tryTo(stringValue); - if (tryValue.hasValue()) { - result = yoga::StyleLength::points(tryValue.value()); - return; - } + auto parsed = parseCSSProperty(stringValue); + if (std::holds_alternative(parsed)) { + result = + yoga::StyleLength::percent(std::get(parsed).value); + return; + } else if (std::holds_alternative(parsed)) { + result = yoga::StyleLength::points(std::get(parsed).value); + return; } } } @@ -22306,48 +24857,37 @@ inline void fromRawValue( result = value.hasType() ? yoga::FloatOptional((float)value) : yoga::FloatOptional(); } -inline Float toRadians( - const RawValue& value, - std::optional defaultValue) { +inline std::optional toRadians(const RawValue& value) { if (value.hasType()) { return (Float)value; } - react_native_expect(value.hasType()); - if (!value.hasType() && defaultValue.has_value()) { - return *defaultValue; + if (!value.hasType()) { + return {}; } - auto stringValue = (std::string)value; - char* suffixStart; - double num = strtod(stringValue.c_str(), &suffixStart); - if (0 == strncmp(suffixStart, "deg", 3)) { - return static_cast(num * M_PI / 180.0f); + auto angle = parseCSSProperty((std::string)value); + if (std::holds_alternative(angle)) { + return std::get(angle).degrees * M_PI / 180.0f; + } + return {}; +} +inline ValueUnit toValueUnit(const RawValue& value) { + if (value.hasType()) { + return ValueUnit((Float)value, UnitType::Point); + } + if (!value.hasType()) { + return {}; } - return static_cast(num); + auto pct = parseCSSProperty((std::string)value); + if (std::holds_alternative(pct)) { + return ValueUnit(std::get(pct).value, UnitType::Percent); + } + return {}; } inline void fromRawValue( const PropsParserContext&, const RawValue& value, ValueUnit& result) { - react_native_expect(value.hasType()); - ValueUnit valueUnit; - if (value.hasType()) { - auto valueFloat = (float)value; - if (std::isfinite(valueFloat)) { - valueUnit = ValueUnit(valueFloat, UnitType::Point); - } else { - valueUnit = ValueUnit(0.0f, UnitType::Undefined); - } - } else if (value.hasType()) { - const auto stringValue = (std::string)value; - if (stringValue.back() == '%') { - auto tryValue = folly::tryTo( - std::string_view(stringValue).substr(0, stringValue.length() - 1)); - if (tryValue.hasValue()) { - valueUnit = ValueUnit(tryValue.value(), UnitType::Percent); - } - } - } - result = valueUnit; + result = toValueUnit(value); } inline void fromRawValue( const PropsParserContext& context, @@ -22362,100 +24902,180 @@ inline void fromRawValue( auto configurations = static_cast>(value); for (const auto& configuration : configurations) { if (!configuration.hasType>()) { - continue; + result = {}; + return; } auto configurationPair = static_cast>(configuration); + if (configurationPair.size() != 1) { + result = {}; + return; + } auto pair = configurationPair.begin(); auto operation = pair->first; auto& parameters = pair->second; auto Zero = ValueUnit(0, UnitType::Point); auto One = ValueUnit(1, UnitType::Point); if (operation == "matrix") { - react_native_expect(parameters.hasType>()); + if (configurations.size() > 1) { + result = {}; + return; + } + if (!parameters.hasType>()) { + result = {}; + return; + } auto numbers = (std::vector)parameters; - react_native_expect(numbers.size() == transformMatrix.matrix.size()); - auto i = 0; + if (numbers.size() != 9 && numbers.size() != 16) { + result = {}; + return; + } + size_t i = 0; for (auto number : numbers) { transformMatrix.matrix[i++] = number; } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Arbitrary, Zero, Zero, Zero}); } else if (operation == "perspective") { + if (!parameters.hasType()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Perspective, ValueUnit((Float)parameters, UnitType::Point), Zero, Zero}); } else if (operation == "rotateX") { + auto radians = toRadians(parameters); + if (!radians.has_value()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Rotate, - ValueUnit(toRadians(parameters, 0.0f), UnitType::Point), + ValueUnit(*radians, UnitType::Point), Zero, Zero}); } else if (operation == "rotateY") { + auto radians = toRadians(parameters); + if (!radians.has_value()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Rotate, Zero, - ValueUnit(toRadians(parameters, 0.0f), UnitType::Point), + ValueUnit(*radians, UnitType::Point), Zero}); } else if (operation == "rotateZ" || operation == "rotate") { + auto radians = toRadians(parameters); + if (!radians.has_value()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Rotate, Zero, Zero, - ValueUnit(toRadians(parameters, 0.0f), UnitType::Point)}); + ValueUnit(*radians, UnitType::Point)}); } else if (operation == "scale") { + if (!parameters.hasType()) { + result = {}; + return; + } auto number = ValueUnit((Float)parameters, UnitType::Point); transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Scale, number, number, number}); } else if (operation == "scaleX") { + if (!parameters.hasType()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Scale, ValueUnit((Float)parameters, UnitType::Point), One, One}); } else if (operation == "scaleY") { + if (!parameters.hasType()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Scale, One, ValueUnit((Float)parameters, UnitType::Point), One}); } else if (operation == "scaleZ") { + if (!parameters.hasType()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Scale, One, One, ValueUnit((Float)parameters, UnitType::Point)}); } else if (operation == "translate") { + if (!parameters.hasType>()) { + result = {}; + return; + } auto numbers = (std::vector)parameters; - ValueUnit valueX; - fromRawValue(context, numbers.at(0), valueX); - ValueUnit valueY; - fromRawValue(context, numbers.at(1), valueY); + if (numbers.size() != 2) { + result = {}; + return; + } + auto valueX = toValueUnit(numbers[0]); + if (!valueX) { + result = {}; + return; + } + auto valueY = toValueUnit(numbers[1]); + if (!valueY) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Translate, valueX, valueY, Zero}); } else if (operation == "translateX") { - ValueUnit valueX; - fromRawValue(context, parameters, valueX); + auto valueX = toValueUnit(parameters); + if (!valueX) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Translate, valueX, Zero, Zero}); } else if (operation == "translateY") { - ValueUnit valueY; - fromRawValue(context, parameters, valueY); + auto valueY = toValueUnit(parameters); + if (!valueY) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Translate, Zero, valueY, Zero}); } else if (operation == "skewX") { + auto radians = toRadians(parameters); + if (!radians.has_value()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Skew, - ValueUnit(toRadians(parameters, 0.0f), UnitType::Point), + ValueUnit(*radians, UnitType::Point), Zero, Zero}); } else if (operation == "skewY") { + auto radians = toRadians(parameters); + if (!radians.has_value()) { + result = {}; + return; + } transformMatrix.operations.push_back(TransformOperation{ TransformOperationType::Skew, Zero, - ValueUnit(toRadians(parameters, 0.0f), UnitType::Point), + ValueUnit(*radians, UnitType::Point), Zero}); } } @@ -22465,17 +25085,29 @@ inline void fromRawValue( const PropsParserContext& context, const RawValue& value, TransformOrigin& result) { - react_native_expect(value.hasType>()); + if (!value.hasType>()) { + result = {}; + return; + } auto origins = (std::vector)value; + if (origins.size() != 3) { + result = {}; + return; + } TransformOrigin transformOrigin; - const size_t maxIndex = 2; - for (size_t i = 0; i < std::min(origins.size(), maxIndex); i++) { - const auto& origin = origins[i]; - fromRawValue(context, origin, transformOrigin.xy[i]); + for (size_t i = 0; i < 2; i++) { + auto origin = toValueUnit(origins[i]); + if (!origin) { + result = {}; + return; + } + transformOrigin.xy[i] = origin; } - if (origins.size() >= 3 && origins[2].hasType()) { - transformOrigin.z = (Float)origins[2]; + if (!origins[2].hasType()) { + result = {}; + return; } + transformOrigin.z = (Float)origins[2]; result = transformOrigin; } inline void fromRawValue( @@ -22507,6 +25139,18 @@ inline void fromRawValue( LOG(ERROR) << "Could not parse PointerEventsMode:" << stringValue; react_native_expect(false); } +inline std::string toString(const PointerEventsMode& value) { + switch (value) { + case PointerEventsMode::Auto: + return "auto"; + case PointerEventsMode::None: + return "none"; + case PointerEventsMode::BoxNone: + return "box-none"; + case PointerEventsMode::BoxOnly: + return "box-only"; + } +} inline void fromRawValue( const PropsParserContext& context, const RawValue& value, @@ -22779,176 +25423,6 @@ inline void fromRawValue( react_native_expect(false); } } -inline void fromRawValue( - const PropsParserContext& context, - const RawValue& value, - std::vector& result) { - react_native_expect(value.hasType>()); - if (!value.hasType>()) { - result = {}; - return; - } - std::vector boxShadows{}; - auto rawBoxShadows = static_cast>(value); - for (const auto& rawBoxShadow : rawBoxShadows) { - bool isMap = - rawBoxShadow.hasType>(); - react_native_expect(isMap); - if (!isMap) { - result = {}; - return; - } - auto rawBoxShadowMap = - static_cast>(rawBoxShadow); - BoxShadow boxShadow{}; - auto offsetX = rawBoxShadowMap.find("offsetX"); - react_native_expect(offsetX != rawBoxShadowMap.end()); - if (offsetX == rawBoxShadowMap.end()) { - result = {}; - return; - } - react_native_expect(offsetX->second.hasType()); - if (!offsetX->second.hasType()) { - result = {}; - return; - } - boxShadow.offsetX = (Float)offsetX->second; - auto offsetY = rawBoxShadowMap.find("offsetY"); - react_native_expect(offsetY != rawBoxShadowMap.end()); - if (offsetY == rawBoxShadowMap.end()) { - result = {}; - return; - } - react_native_expect(offsetY->second.hasType()); - if (!offsetY->second.hasType()) { - result = {}; - return; - } - boxShadow.offsetY = (Float)offsetY->second; - auto blurRadius = rawBoxShadowMap.find("blurRadius"); - if (blurRadius != rawBoxShadowMap.end()) { - react_native_expect(blurRadius->second.hasType()); - if (!blurRadius->second.hasType()) { - result = {}; - return; - } - boxShadow.blurRadius = (Float)blurRadius->second; - } - auto spreadDistance = rawBoxShadowMap.find("spreadDistance"); - if (spreadDistance != rawBoxShadowMap.end()) { - react_native_expect(spreadDistance->second.hasType()); - if (!spreadDistance->second.hasType()) { - result = {}; - return; - } - boxShadow.spreadDistance = (Float)spreadDistance->second; - } - auto inset = rawBoxShadowMap.find("inset"); - if (inset != rawBoxShadowMap.end()) { - react_native_expect(inset->second.hasType()); - if (!inset->second.hasType()) { - result = {}; - return; - } - boxShadow.inset = (bool)inset->second; - } - auto color = rawBoxShadowMap.find("color"); - if (color != rawBoxShadowMap.end()) { - fromRawValue( - context.contextContainer, - context.surfaceId, - color->second, - boxShadow.color); - } - boxShadows.push_back(boxShadow); - } - result = boxShadows; -} -inline void fromRawValue( - const PropsParserContext& context, - const RawValue& value, - std::vector& result) { - react_native_expect(value.hasType>()); - if (!value.hasType>()) { - result = {}; - return; - } - std::vector filter{}; - auto rawFilter = static_cast>(value); - for (const auto& rawFilterPrimitive : rawFilter) { - bool isMap = - rawFilterPrimitive.hasType>(); - react_native_expect(isMap); - if (!isMap) { - result = {}; - return; - } - auto rawFilterFunction = - static_cast>( - rawFilterPrimitive); - FilterFunction filterFunction{}; - try { - filterFunction.type = - filterTypeFromString(rawFilterFunction.begin()->first); - if (filterFunction.type == FilterType::DropShadow) { - auto rawDropShadow = - static_cast>( - rawFilterFunction.begin()->second); - DropShadowParams dropShadowParams{}; - auto offsetX = rawDropShadow.find("offsetX"); - react_native_expect(offsetX != rawDropShadow.end()); - if (offsetX == rawDropShadow.end()) { - result = {}; - return; - } - react_native_expect(offsetX->second.hasType()); - if (!offsetX->second.hasType()) { - result = {}; - return; - } - dropShadowParams.offsetX = (Float)offsetX->second; - auto offsetY = rawDropShadow.find("offsetY"); - react_native_expect(offsetY != rawDropShadow.end()); - if (offsetY == rawDropShadow.end()) { - result = {}; - return; - } - react_native_expect(offsetY->second.hasType()); - if (!offsetY->second.hasType()) { - result = {}; - return; - } - dropShadowParams.offsetY = (Float)offsetY->second; - auto standardDeviation = rawDropShadow.find("standardDeviation"); - if (standardDeviation != rawDropShadow.end()) { - react_native_expect(standardDeviation->second.hasType()); - if (!standardDeviation->second.hasType()) { - result = {}; - return; - } - dropShadowParams.standardDeviation = (Float)standardDeviation->second; - } - auto color = rawDropShadow.find("color"); - if (color != rawDropShadow.end()) { - fromRawValue( - context.contextContainer, - context.surfaceId, - color->second, - dropShadowParams.color); - } - filterFunction.parameters = dropShadowParams; - } else { - filterFunction.parameters = (float)rawFilterFunction.begin()->second; - } - filter.push_back(std::move(filterFunction)); - } catch (const std::exception& e) { - LOG(ERROR) << "Could not parse FilterFunction: " << e.what(); - result = {}; - return; - } - } - result = filter; -} inline void fromRawValue( const PropsParserContext&, const RawValue& value, @@ -22994,7 +25468,41 @@ inline void fromRawValue( continue; } std::string type = (std::string)(typeIt->second); - if (type == "linearGradient") { + std::vector colorStops; + auto colorStopsIt = rawBackgroundImageMap.find("colorStops"); + if (colorStopsIt != rawBackgroundImageMap.end() && + colorStopsIt->second.hasType>()) { + auto rawColorStops = + static_cast>(colorStopsIt->second); + for (const auto& stop : rawColorStops) { + if (stop.hasType>()) { + auto stopMap = + static_cast>(stop); + auto positionIt = stopMap.find("position"); + auto colorIt = stopMap.find("color"); + if (positionIt != stopMap.end() && colorIt != stopMap.end()) { + ColorStop colorStop; + if (positionIt->second.hasValue()) { + auto valueUnit = toValueUnit(positionIt->second); + if (!valueUnit) { + result = {}; + return; + } + colorStop.position = valueUnit; + } + if (colorIt->second.hasValue()) { + fromRawValue( + context.contextContainer, + context.surfaceId, + colorIt->second, + colorStop.color); + } + colorStops.push_back(colorStop); + } + } + } + } + if (type == "linear-gradient") { LinearGradient linearGradient; auto directionIt = rawBackgroundImageMap.find("direction"); if (directionIt != rawBackgroundImageMap.end() && @@ -23022,28 +25530,80 @@ inline void fromRawValue( } } } - auto colorStopsIt = rawBackgroundImageMap.find("colorStops"); - if (colorStopsIt != rawBackgroundImageMap.end() && - colorStopsIt->second.hasType>()) { - auto rawColorStops = - static_cast>(colorStopsIt->second); - for (const auto& stop : rawColorStops) { - if (stop.hasType>()) { - auto stopMap = - static_cast>(stop); - auto positionIt = stopMap.find("position"); - auto colorIt = stopMap.find("color"); - if (positionIt != stopMap.end() && colorIt != stopMap.end() && - positionIt->second.hasType()) { - ColorStop colorStop; - colorStop.position = (Float)(positionIt->second); - fromRawValue(context, colorIt->second, colorStop.color); - linearGradient.colorStops.push_back(colorStop); - } + if (!colorStops.empty()) { + linearGradient.colorStops = colorStops; + } + backgroundImage.emplace_back(std::move(linearGradient)); + } else if (type == "radial-gradient") { + RadialGradient radialGradient; + auto shapeIt = rawBackgroundImageMap.find("shape"); + if (shapeIt != rawBackgroundImageMap.end() && + shapeIt->second.hasType()) { + auto shape = (std::string)(shapeIt->second); + radialGradient.shape = shape == "circle" ? RadialGradientShape::Circle + : RadialGradientShape::Ellipse; + } + auto sizeIt = rawBackgroundImageMap.find("size"); + if (sizeIt != rawBackgroundImageMap.end()) { + if (sizeIt->second.hasType()) { + auto sizeStr = (std::string)(sizeIt->second); + if (sizeStr == "closest-side") { + radialGradient.size.value = + RadialGradientSize::SizeKeyword::ClosestSide; + } else if (sizeStr == "farthest-side") { + radialGradient.size.value = + RadialGradientSize::SizeKeyword::FarthestSide; + } else if (sizeStr == "closest-corner") { + radialGradient.size.value = + RadialGradientSize::SizeKeyword::ClosestCorner; + } else if (sizeStr == "farthest-corner") { + radialGradient.size.value = + RadialGradientSize::SizeKeyword::FarthestCorner; + } + } else if (sizeIt->second + .hasType>()) { + auto sizeMap = static_cast>( + sizeIt->second); + auto xIt = sizeMap.find("x"); + auto yIt = sizeMap.find("y"); + if (xIt != sizeMap.end() && yIt != sizeMap.end()) { + RadialGradientSize sizeObj; + sizeObj.value = RadialGradientSize::Dimensions{ + toValueUnit(xIt->second), toValueUnit(yIt->second)}; + radialGradient.size = sizeObj; + } + } + auto positionIt = rawBackgroundImageMap.find("position"); + if (positionIt != rawBackgroundImageMap.end() && + positionIt->second + .hasType>()) { + auto positionMap = + static_cast>( + positionIt->second); + auto topIt = positionMap.find("top"); + auto bottomIt = positionMap.find("bottom"); + auto leftIt = positionMap.find("left"); + auto rightIt = positionMap.find("right"); + if (topIt != positionMap.end()) { + auto topValue = toValueUnit(topIt->second); + radialGradient.position.top = topValue; + } else if (bottomIt != positionMap.end()) { + auto bottomValue = toValueUnit(bottomIt->second); + radialGradient.position.bottom = bottomValue; + } + if (leftIt != positionMap.end()) { + auto leftValue = toValueUnit(leftIt->second); + radialGradient.position.left = leftValue; + } else if (rightIt != positionMap.end()) { + auto rightValue = toValueUnit(rightIt->second); + radialGradient.position.right = rightValue; } } } - backgroundImage.push_back(std::move(linearGradient)); + if (!colorStops.empty()) { + radialGradient.colorStops = colorStops; + } + backgroundImage.emplace_back(std::move(radialGradient)); } } result = backgroundImage; @@ -23146,6 +25706,102 @@ inline std::string toString(const LayoutConformance& value) { return "compatibility"; } } +inline std::string toString(const std::array& m) { + std::string result; + result += "[ " + std::to_string(m[0]) + " " + std::to_string(m[1]) + " " + + std::to_string(m[2]) + " " + std::to_string(m[3]) + " ]\n"; + result += "[ " + std::to_string(m[4]) + " " + std::to_string(m[5]) + " " + + std::to_string(m[6]) + " " + std::to_string(m[7]) + " ]\n"; + result += "[ " + std::to_string(m[8]) + " " + std::to_string(m[9]) + " " + + std::to_string(m[10]) + " " + std::to_string(m[11]) + " ]\n"; + result += "[ " + std::to_string(m[12]) + " " + std::to_string(m[13]) + " " + + std::to_string(m[14]) + " " + std::to_string(m[15]) + " ]"; + return result; +} +inline std::string toString(const Transform& transform) { + std::string result = "["; + bool first = true; + for (const auto& operation : transform.operations) { + if (!first) { + result += ", "; + } + first = false; + switch (operation.type) { + case TransformOperationType::Perspective: { + result += + "{\"perspective\": " + std::to_string(operation.x.value) + "}"; + break; + } + case TransformOperationType::Rotate: { + if (operation.x.value != 0 && operation.y.value == 0 && + operation.z.value == 0) { + result += + R"({"rotateX": ")" + std::to_string(operation.x.value) + "rad\"}"; + } else if ( + operation.x.value == 0 && operation.y.value != 0 && + operation.z.value == 0) { + result += + R"({"rotateY": ")" + std::to_string(operation.y.value) + "rad\"}"; + } else if ( + operation.x.value == 0 && operation.y.value == 0 && + operation.z.value != 0) { + result += + R"({"rotateZ": ")" + std::to_string(operation.z.value) + "rad\"}"; + } + break; + } + case TransformOperationType::Scale: { + if (operation.x.value == operation.y.value && + operation.x.value == operation.z.value) { + result += "{\"scale\": " + std::to_string(operation.x.value) + "}"; + } else if (operation.y.value == 1 && operation.z.value == 1) { + result += "{\"scaleX\": " + std::to_string(operation.x.value) + "}"; + } else if (operation.x.value == 1 && operation.z.value == 1) { + result += "{\"scaleY\": " + std::to_string(operation.y.value) + "}"; + } else if (operation.x.value == 1 && operation.y.value == 1) { + result += "{\"scaleZ\": " + std::to_string(operation.z.value) + "}"; + } + break; + } + case TransformOperationType::Translate: { + if (operation.x.value != 0 && operation.y.value != 0 && + operation.z.value == 0) { + result += "{\"translate\": ["; + result += std::to_string(operation.x.value) + ", " + + std::to_string(operation.y.value); + result += "]}"; + } else if (operation.x.value != 0 && operation.y.value == 0) { + result += + "{\"translateX\": " + std::to_string(operation.x.value) + "}"; + } else if (operation.x.value == 0 && operation.y.value != 0) { + result += + "{\"translateY\": " + std::to_string(operation.y.value) + "}"; + } + break; + } + case TransformOperationType::Skew: { + if (operation.x.value != 0 && operation.y.value == 0) { + result += + R"({"skewX": ")" + std::to_string(operation.x.value) + "rad\"}"; + } else if (operation.x.value == 0 && operation.y.value != 0) { + result += + R"({"skewY": ")" + std::to_string(operation.y.value) + "rad\"}"; + } + break; + } + case TransformOperationType::Arbitrary: { + result += "{\"matrix\": " + toString(transform.matrix) + "}"; + break; + } + case TransformOperationType::Identity: { + result += "{\"identity\": true}"; + break; + } + } + } + result += "]"; + return result; +} } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformTouch.h}: @@ -23177,6 +25833,7 @@ class HostPlatformViewProps : public BaseViewProps { bool hasTVPreferredFocus{false}; bool needsOffscreenAlphaCompositing{false}; bool renderToHardwareTextureAndroid{false}; + bool screenReaderFocusable{false}; bool getProbablyMoreHorizontalThanVertical_DEPRECATED() const; }; } // namespace facebook::react @@ -23191,7 +25848,11 @@ inline bool formsView(const ViewProps& viewProps) { viewProps.nativeForeground.has_value() || viewProps.focusable || viewProps.hasTVPreferredFocus || viewProps.needsOffscreenAlphaCompositing || - viewProps.renderToHardwareTextureAndroid; + viewProps.renderToHardwareTextureAndroid || + viewProps.screenReaderFocusable; +} +inline bool isKeyboardFocusable(const ViewProps& viewProps) { + return (viewProps.focusable || viewProps.hasTVPreferredFocus); } } // namespace facebook::react::HostPlatformViewTraitsInitializer @@ -23282,10 +25943,22 @@ static inline void fromRawValue( /// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewEventEmitter.h} /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/cxx/react/renderer/components/view/HostPlatformViewProps.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewProps.h} +namespace facebook::react { +using HostPlatformViewProps = BaseViewProps; +} /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/cxx/react/renderer/components/view/HostPlatformViewTraitsInitializer.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewTraitsInitializer.h} +namespace facebook::react::HostPlatformViewTraitsInitializer { +inline bool formsStackingContext(const ViewProps& props) { + return false; +} +inline bool formsView(const ViewProps& props) { + return false; +} +inline bool isKeyboardFocusable(const ViewProps&) { + return false; +} +} // namespace facebook::react::HostPlatformViewTraitsInitializer /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformTouch.h}: namespace facebook::react { @@ -23311,7 +25984,7 @@ inline static void setTouchPayloadOnObject( object.setProperty(runtime, "screenY", touch.screenPoint.y); object.setProperty(runtime, "identifier", touch.identifier); object.setProperty(runtime, "target", touch.target); - object.setProperty(runtime, "timestamp", touch.pointerTimestamp); + object.setProperty(runtime, "timestamp", touch.timestamp); object.setProperty(runtime, "force", touch.force); object.setProperty(runtime, "button", touch.button); object.setProperty(runtime, "altKey", touch.altKey); @@ -23322,13 +25995,227 @@ inline static void setTouchPayloadOnObject( } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEventEmitter.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewEventEmitter.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/KeyEvent.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/MouseEvent.h} + +namespace facebook::react { +class HostPlatformViewEventEmitter : public BaseViewEventEmitter { + public: + using BaseViewEventEmitter::BaseViewEventEmitter; + void onKeyDown(const KeyEvent& keyEvent) const; + void onKeyUp(const KeyEvent& keyEvent) const; + void onMouseEnter(const MouseEvent& mouseEvent) const; + void onMouseLeave(const MouseEvent& mouseEvent) const; + void onDoubleClick(const MouseEvent& mouseEvent) const; + void onDragEnter(const DragEvent& dragEvent) const; + void onDragLeave(const DragEvent& dragEvent) const; + void onDrop(const DragEvent& dragEvent) const; + static jsi::Value dataTransferPayload( + jsi::Runtime& runtime, + const std::vector& dataTransferItems); + void onFocus() const; + void onBlur() const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEvents.h}: +namespace facebook::react { +struct HostPlatformViewEvents { + std::bitset<32> bits{}; + enum class Offset : std::size_t { + KeyDown = 1, + KeyUp = 2, + MouseEnter = 3, + MouseLeave = 4, + DoubleClick = 5, + }; + constexpr bool operator[](const Offset offset) const { + return bits[static_cast(offset)]; + } + std::bitset<32>::reference operator[](const Offset offset) { + return bits[static_cast(offset)]; + } +}; +inline static bool operator==( + const HostPlatformViewEvents& lhs, + const HostPlatformViewEvents& rhs) { + return lhs.bits == rhs.bits; +} +inline static bool operator!=( + const HostPlatformViewEvents& lhs, + const HostPlatformViewEvents& rhs) { + return lhs.bits != rhs.bits; +} +static inline HostPlatformViewEvents convertRawProp( + const PropsParserContext& context, + const RawProps& rawProps, + const HostPlatformViewEvents& sourceValue, + const HostPlatformViewEvents& defaultValue) { + HostPlatformViewEvents result{}; + using Offset = HostPlatformViewEvents::Offset; + result[Offset::KeyDown] = convertRawProp( + context, + rawProps, + "onKeyDown", + sourceValue[Offset::KeyDown], + defaultValue[Offset::KeyDown]); + result[Offset::KeyUp] = convertRawProp( + context, + rawProps, + "onKeyUp", + sourceValue[Offset::KeyUp], + defaultValue[Offset::KeyUp]); + result[Offset::MouseEnter] = convertRawProp( + context, + rawProps, + "onMouseEnter", + sourceValue[Offset::MouseEnter], + defaultValue[Offset::MouseEnter]); + result[Offset::MouseLeave] = convertRawProp( + context, + rawProps, + "onMouseLeave", + sourceValue[Offset::MouseLeave], + defaultValue[Offset::MouseLeave]); + result[Offset::DoubleClick] = convertRawProp( + context, + rawProps, + "onDoubleClick", + sourceValue[Offset::DoubleClick], + defaultValue[Offset::DoubleClick]); + return result; +} +} // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewProps.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/cxx/react/renderer/components/view/HostPlatformViewProps.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewEvents.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/KeyEvent.h} + +namespace facebook::react { +class HostPlatformViewProps : public BaseViewProps { + public: + HostPlatformViewProps() = default; + HostPlatformViewProps( + const PropsParserContext& context, + const HostPlatformViewProps& sourceProps, + const RawProps& rawProps); + void setProp( + const PropsParserContext& context, + RawPropsPropNameHash hash, + const char* propName, + const RawValue& value); + HostPlatformViewEvents hostPlatformEvents{}; + bool enableFocusRing{true}; + bool focusable{false}; + std::vector draggedTypes{}; + std::optional tooltip{}; + std::optional> validKeysDown{}; + std::optional> validKeysUp{}; +}; +} // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/HostPlatformViewTraitsInitializer.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/components/view/platform/cxx/react/renderer/components/view/HostPlatformViewTraitsInitializer.h} +namespace facebook::react::HostPlatformViewTraitsInitializer { +inline bool formsStackingContext(const ViewProps& props) { + constexpr decltype(HostPlatformViewEvents::bits) mouseEventMask = { + (1 << (int)HostPlatformViewEvents::Offset::MouseEnter) | + (1 << (int)HostPlatformViewEvents::Offset::MouseLeave) | + (1 << (int)HostPlatformViewEvents::Offset::DoubleClick)}; + return (props.hostPlatformEvents.bits & mouseEventMask).any() || + props.tooltip || + (props.validKeysDown.has_value() && !props.validKeysDown->empty()) || + (props.validKeysUp.has_value() && !props.validKeysUp->empty()); +} +inline bool formsView(const ViewProps& props) { + return props.focusable; +} +inline bool isKeyboardFocusable(const ViewProps& props) { + return props.focusable; +} +} // namespace facebook::react::HostPlatformViewTraitsInitializer + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/KeyEvent.h}: +namespace facebook::react { +struct HandledKey { + std::string key{}; + std::optional altKey{}; + std::optional ctrlKey{}; + std::optional shiftKey{}; + std::optional metaKey{}; +}; +inline static bool operator==(const HandledKey& lhs, const HandledKey& rhs) { + return lhs.key == rhs.key && lhs.altKey == rhs.altKey && + lhs.ctrlKey == rhs.ctrlKey && lhs.shiftKey == rhs.shiftKey && + lhs.metaKey == rhs.metaKey; +} +struct KeyEvent { + std::string key{}; + bool altKey{false}; + bool ctrlKey{false}; + bool shiftKey{false}; + bool metaKey{false}; + bool capsLockKey{false}; + bool numericPadKey{false}; + bool helpKey{false}; + bool functionKey{false}; +}; +inline static bool operator==(const KeyEvent& lhs, const HandledKey& rhs) { + return lhs.key == rhs.key && + (!rhs.altKey.has_value() || lhs.altKey == *rhs.altKey) && + (!rhs.ctrlKey.has_value() || lhs.ctrlKey == *rhs.ctrlKey) && + (!rhs.shiftKey.has_value() || lhs.shiftKey == *rhs.shiftKey) && + (!rhs.metaKey.has_value() || lhs.metaKey == *rhs.metaKey); +} +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + HandledKey& result) { + if (value.hasType>()) { + auto map = static_cast>(value); + for (const auto& pair : map) { + if (pair.first == "key") { + result.key = static_cast(pair.second); + } else if (pair.first == "altKey") { + result.altKey = static_cast(pair.second); + } else if (pair.first == "ctrlKey") { + result.ctrlKey = static_cast(pair.second); + } else if (pair.first == "shiftKey") { + result.shiftKey = static_cast(pair.second); + } else if (pair.first == "metaKey") { + result.metaKey = static_cast(pair.second); + } + } + } else if (value.hasType()) { + result.key = (std::string)value; + } +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/macos/react/renderer/components/view/MouseEvent.h}: +namespace facebook::react { +struct MouseEvent { + Float clientX{0}; + Float clientY{0}; + Float screenX{0}; + Float screenY{0}; + bool altKey{false}; + bool ctrlKey{false}; + bool shiftKey{false}; + bool metaKey{false}; +}; +struct DataTransferItem { + std::string name{}; + std::string kind{}; + std::string type{}; + std::string uri{}; + std::optional size{}; + std::optional width{}; + std::optional height{}; +}; +struct DragEvent : MouseEvent { + std::vector dataTransferItems; +}; +} // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/windows/third-party/react/renderer/components/view/HostPlatformTouch.h}: namespace facebook::react { @@ -23417,6 +26304,9 @@ inline bool formsStackingContext(const ViewProps& viewProps) { inline bool formsView(const ViewProps& viewProps) { return viewProps.focusable; } +inline bool isKeyboardFocusable(const ViewProps& viewProps) { + return viewProps.focusable; +} } // namespace facebook::react::HostPlatformViewTraitsInitializer /// @src {packages/react-native/ReactCommon/react/renderer/components/view/platform/windows/third-party/react/renderer/components/view/KeyEvent.h}: @@ -24096,12 +26986,24 @@ static inline ViewEvents convertRawProp( "onPointerOver", sourceValue[Offset::PointerOver], defaultValue[Offset::PointerOver]); + result[Offset::PointerOverCapture] = convertRawProp( + context, + rawProps, + "onPointerOverCapture", + sourceValue[Offset::PointerOverCapture], + defaultValue[Offset::PointerOverCapture]); result[Offset::PointerOut] = convertRawProp( context, rawProps, "onPointerOut", sourceValue[Offset::PointerOut], defaultValue[Offset::PointerOut]); + result[Offset::PointerOutCapture] = convertRawProp( + context, + rawProps, + "onPointerOutCapture", + sourceValue[Offset::PointerOutCapture], + defaultValue[Offset::PointerOutCapture]); result[Offset::Click] = convertRawProp( context, rawProps, @@ -24298,7 +27200,7 @@ class ComponentDescriptor { virtual std::shared_ptr createShadowNode( const ShadowNodeFragment& fragment, const ShadowNodeFamily::Shared& family) const = 0; - virtual ShadowNode::Unshared cloneShadowNode( + virtual std::shared_ptr cloneShadowNode( const ShadowNode& sourceShadowNode, const ShadowNodeFragment& fragment) const = 0; virtual void appendChild( @@ -24374,10 +27276,11 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { adopt(*shadowNode); return shadowNode; } - ShadowNode::Unshared cloneShadowNode( + std::shared_ptr cloneShadowNode( const ShadowNode& sourceShadowNode, const ShadowNodeFragment& fragment) const override { auto shadowNode = std::make_shared(sourceShadowNode, fragment); + shadowNode->completeClone(sourceShadowNode, fragment); sourceShadowNode.transferRuntimeShadowNodeReference(shadowNode, fragment); adopt(*shadowNode); return shadowNode; @@ -24401,8 +27304,8 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { ShadowNodeT::filterRawProps(rawProps); } rawProps.parse(rawPropsParser_); + auto shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); if (ReactNativeFeatureFlags::enableCppPropsIteratorSetter()) { - auto shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); const auto& dynamic = static_cast(rawProps); for (const auto& pair : dynamic.items()) { const auto& name = pair.first.getString(); @@ -24412,10 +27315,8 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { name.c_str(), RawValue(pair.second)); } - return shadowNodeProps; - } else { - return ShadowNodeT::Props(context, rawProps, props); } + return shadowNodeProps; }; virtual State::Shared createInitialState( const Props::Shared& props, @@ -24445,8 +27346,10 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { std::make_shared( fragment.instanceHandle, fragment.surfaceId), eventDispatcher_); - return std::make_shared( - fragment, std::move(eventEmitter), eventDispatcher_, *this); + auto family = std::make_shared( + fragment, eventEmitter, eventDispatcher_, *this); + eventEmitter->setShadowNodeFamily(family); + return family; } protected: @@ -24476,8 +27379,7 @@ template < typename BaseShadowNodeT, typename PropsT, typename EventEmitterT = EventEmitter, - typename StateDataT = StateData, - bool usesMapBufferForStateData = false> + typename StateDataT = StateData> class ConcreteShadowNode : public BaseShadowNodeT { static_assert( std::is_base_of::value, @@ -24498,7 +27400,7 @@ class ConcreteShadowNode : public BaseShadowNodeT { using ConcreteEventEmitter = EventEmitterT; using SharedConcreteEventEmitter = std::shared_ptr; using SharedConcreteShadowNode = std::shared_ptr; - using ConcreteState = ConcreteState; + using ConcreteState = ConcreteState; using ConcreteStateData = StateDataT; static ComponentName Name() { return ComponentName(concreteComponentName); @@ -24535,6 +27437,11 @@ class ConcreteShadowNode : public BaseShadowNodeT { BaseShadowNodeT::props_ && "Props must not be `nullptr`."); return static_cast(*props_); } + const std::shared_ptr& getConcreteSharedProps() const { + react_native_assert( + BaseShadowNodeT::props_ && "Props must not be `nullptr`."); + return std::static_pointer_cast(props_); + } const ConcreteEventEmitter& getConcreteEventEmitter() const { return static_cast( *BaseShadowNodeT::getEventEmitter()); @@ -24553,18 +27460,16 @@ class ConcreteShadowNode : public BaseShadowNodeT { /// @src {packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h}: namespace facebook::react { -template +template class ConcreteState : public State { public: using Shared = std::shared_ptr; using Data = DataT; using SharedData = std::shared_ptr; - explicit ConcreteState(const SharedData& data, const State& previousState) - : State(data, previousState) {} - explicit ConcreteState( - const SharedData& data, - const ShadowNodeFamily::Shared& family) - : State(data, family) {} + explicit ConcreteState(SharedData data, const State& previousState) + : State(std::move(data), previousState) {} + explicit ConcreteState(SharedData data, ShadowNodeFamily::Weak family) + : State(std::move(data), std::move(family)) {} ~ConcreteState() override = default; const Data& getData() const { return *static_cast(data_.get()); @@ -24590,6 +27495,17 @@ class ConcreteState : public State { }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/core/DynamicEventPayload.h}: +namespace facebook::react { +struct DynamicEventPayload : public EventPayload { + explicit DynamicEventPayload(folly::dynamic&& payload); + jsi::Value asJSIValue(jsi::Runtime& runtime) const override; + EventPayloadType getType() const override; + std::optional extractValue( + const std::vector& path) const override; +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.h}: namespace facebook::react { enum class NullValueStrategy { Override, Ignore }; @@ -24625,10 +27541,12 @@ class EventBeat { virtual void request() const; virtual void requestSynchronous() const; void setBeatCallback(BeatCallback beatCallback); + void unstable_setInduceCallback(std::function callback); protected: void induce() const; BeatCallback beatCallback_; + std::function induceCallback_; std::shared_ptr ownerBox_; mutable std::atomic isEventBeatRequested_{false}; }; @@ -24671,6 +27589,8 @@ class EventEmitter { EventDispatcher::Weak eventDispatcher); virtual ~EventEmitter() = default; void setEnabled(bool enabled) const; + void setShadowNodeFamily( + std::weak_ptr shadowNodeFamily) const; const SharedEventTarget& getEventTarget() const; template void experimental_flushSync(Lambda syncFunc) const { @@ -24688,14 +27608,13 @@ class EventEmitter { RawEvent::Category category = RawEvent::Category::Unspecified) const; void dispatchEvent( std::string type, - const folly::dynamic& payload, + folly::dynamic&& payload, RawEvent::Category category = RawEvent::Category::Unspecified) const; void dispatchEvent( std::string type, SharedEventPayload payload, RawEvent::Category category = RawEvent::Category::Unspecified) const; - void dispatchUniqueEvent(std::string type, const folly::dynamic& payload) - const; + void dispatchUniqueEvent(std::string type, folly::dynamic&& payload) const; void dispatchUniqueEvent( std::string type, const ValueFactory& payloadFactory = @@ -24727,8 +27646,7 @@ class EventLogger { virtual EventTag onEventStart( std::string_view name, SharedEventTarget target, - DOMHighResTimeStamp eventStartTimeStamp = - DOM_HIGH_RES_TIME_STAMP_UNSET) = 0; + std::optional eventStartTimeStamp = std::nullopt) = 0; virtual void onEventProcessingStart(EventTag tag) = 0; virtual void onEventProcessingEnd(EventTag tag) = 0; }; @@ -24745,6 +27663,10 @@ struct EventPayload { EventPayload& operator=(EventPayload&&) = default; virtual jsi::Value asJSIValue(jsi::Runtime& runtime) const = 0; virtual EventPayloadType getType() const = 0; + virtual std::optional extractValue( + const std::vector&) const { + return std::nullopt; + } }; using SharedEventPayload = std::shared_ptr; } // namespace facebook::react @@ -24922,6 +27844,17 @@ struct LayoutMetrics { frame.size.width - contentInsets.left - contentInsets.right, frame.size.height - contentInsets.top - contentInsets.bottom}}; } + Rect getOverflowInsetFrame() const { + return Rect{ + Point{ + frame.origin.x + std::min(Float{0}, overflowInset.left), + frame.origin.y + std::min(Float{0}, overflowInset.top)}, + Size{ + frame.size.width - std::min(Float{0}, overflowInset.left) + + -std::min(Float{0}, overflowInset.right), + frame.size.height - std::min(Float{0}, overflowInset.top) + + -std::min(Float{0}, overflowInset.bottom)}}; + } Rect getPaddingFrame() const { return Rect{ Point{borderWidth.left, borderWidth.top}, @@ -24986,6 +27919,10 @@ class LayoutableShadowNode : public ShadowNode { bool enableOverflowClipping{false}; }; using UnsharedList = std::vector; + static LayoutMetrics computeLayoutMetricsFromRoot( + const ShadowNodeFamily& descendantNodeFamily, + const LayoutableShadowNode& rootNode, + LayoutInspectingPolicy policy); static LayoutMetrics computeRelativeLayoutMetrics( const ShadowNodeFamily& descendantNodeFamily, const LayoutableShadowNode& ancestorNode, @@ -25010,7 +27947,6 @@ class LayoutableShadowNode : public ShadowNode { static ShadowNode::Shared findNodeAtPoint( const ShadowNode::Shared& node, Point point); - virtual void cleanLayout() = 0; virtual void dirtyLayout() = 0; virtual bool getIsLayoutClean() const = 0; virtual Float baseline(const LayoutContext& layoutContext, Size size) const; @@ -25078,19 +28014,24 @@ struct RawEvent { ContinuousEnd = 1, Unspecified = 2, Discrete = 3, - Continuous = 4 + Continuous = 4, + Idle = 5, }; RawEvent( std::string type, SharedEventPayload eventPayload, SharedEventTarget eventTarget, - Category category = Category::Unspecified); + std::weak_ptr shadowNodeFamily, + Category category = Category::Unspecified, + bool isUnique = false); std::string type; SharedEventPayload eventPayload; SharedEventTarget eventTarget; + std::weak_ptr shadowNodeFamily; Category category; EventTag loggingTag{0}; - DOMHighResTimeStamp eventStartTimeStamp{DOM_HIGH_RES_TIME_STAMP_UNSET}; + bool isUnique{false}; + std::optional eventStartTimeStamp = std::nullopt; }; } // namespace facebook::react @@ -25099,31 +28040,29 @@ namespace facebook::react { class RawProps final { public: enum class Mode { Empty, JSI, Dynamic }; - RawProps(); + RawProps() : mode_(Mode::Empty) {} RawProps(jsi::Runtime& runtime, const jsi::Value& value) noexcept; explicit RawProps(const RawProps& rawProps) noexcept; - RawProps& operator=(const RawProps& other) noexcept; RawProps(RawProps&& other) noexcept = default; - RawProps& operator=(RawProps&& other) noexcept = default; + RawProps& operator=(const RawProps& other) noexcept = delete; + RawProps& operator=(RawProps&& other) noexcept = delete; explicit RawProps(folly::dynamic dynamic) noexcept; void parse(const RawPropsParser& parser) noexcept; explicit operator folly::dynamic() const; folly::dynamic toDynamic( const std::function& filterObjectKeys = nullptr) const; - void filterYogaStylePropsInDynamicConversion() noexcept; bool isEmpty() const noexcept; const RawValue* at(const char* name, const char* prefix, const char* suffix) const noexcept; }; - mutable Mode mode_; + Mode mode_; jsi::Runtime* runtime_{}; jsi::Value value_; folly::dynamic dynamic_; mutable int keyIndexCursor_{0}; mutable std::vector keyIndexToValueIndex_; mutable std::vector values_; - bool ignoreYogaStyleProps_{false}; }; template concept RawPropsFilterable = requires(RawProps& rawProps) { @@ -25371,6 +28310,7 @@ enum class ReactEventPriority { Default, Discrete, Continuous, + Idle, }; static constexpr std::underlying_type::type serialize( ReactEventPriority reactEventPriority) { @@ -25416,10 +28356,12 @@ class ShadowNode : public Sealable, public jsi::NativeState { public: using Shared = std::shared_ptr; - using Weak = std::weak_ptr; - using Unshared = std::shared_ptr; + using Weak [[deprecated("Use std::weak_ptr instead")]] = + std::weak_ptr; + using Unshared [[deprecated("Use std::shared_ptr instead")]] = + std::shared_ptr; using ListOfShared = std::vector; - using ListOfWeak = std::vector; + using ListOfWeak = std::vector>; using SharedListOfShared = std::shared_ptr; using UnsharedListOfShared = std::shared_ptr; using UnsharedListOfWeak = std::shared_ptr; @@ -25441,11 +28383,19 @@ class ShadowNode : public Sealable, ShadowNode(const ShadowNode& shadowNode) noexcept = delete; ShadowNode& operator=(const ShadowNode& other) noexcept = delete; virtual ~ShadowNode() override = default; - Unshared clone(const ShadowNodeFragment& fragment) const; - Unshared cloneTree( + std::shared_ptr clone(const ShadowNodeFragment& fragment) const; + std::shared_ptr cloneTree( const ShadowNodeFamily& shadowNodeFamily, - const std::function& callback) - const; + const std::function( + const ShadowNode& oldShadowNode)>& callback) const; + std::shared_ptr cloneMultiple( + const std::unordered_set& familiesToUpdate, + const std::function( + const ShadowNode& oldShadowNode, + const ShadowNodeFragment& fragment)>& callback) const; + virtual void completeClone( + const ShadowNode& sourceShadowNode, + const ShadowNodeFragment& fragment) {} ComponentName getComponentName() const; ComponentHandle getComponentHandle() const; ShadowNodeTraits getTraits() const; @@ -25462,6 +28412,7 @@ class ShadowNode : public Sealable, int getOrderIndex() const; void sealRecursive() const; const ShadowNodeFamily& getFamily() const; + ShadowNodeFamily::Shared getFamilyShared() const; virtual void appendChild(const Shared& child); virtual void replaceChild( const ShadowNode& oldChild, @@ -25471,7 +28422,7 @@ class ShadowNode : public Sealable, bool getHasBeenPromoted() const; void setRuntimeShadowNodeReference(const std::shared_ptr& runtimeShadowNodeReference) const; - void transferRuntimeShadowNodeReference( + void updateRuntimeShadowNodeReference( const Shared& destinationShadowNode) const; void transferRuntimeShadowNodeReference( const Shared& destinationShadowNode, @@ -25510,7 +28461,7 @@ struct ShadowNodeFamilyFragment { const SurfaceId surfaceId; const std::shared_ptr instanceHandle; }; -class ShadowNodeFamily final { +class ShadowNodeFamily final : public jsi::NativeState { public: using Shared = std::shared_ptr; using Weak = std::weak_ptr; @@ -25536,11 +28487,13 @@ class ShadowNodeFamily final { void dispatchRawState(StateUpdate&& stateUpdate) const; mutable std::unique_ptr nativeProps_DEPRECATED; Tag getTag() const; + jsi::Value getInstanceHandle(jsi::Runtime& runtime) const; + InstanceHandle::Shared getInstanceHandle() const; + void setInstanceHandle(InstanceHandle::Shared& instanceHandle) const; ~ShadowNodeFamily(); }; mutable bool hasParent_{false}; mutable bool hasBeenMounted_{false}; - const bool isDeletionOfUnmountedViewsEnabled_; }; } // namespace facebook::react @@ -25566,15 +28519,17 @@ class ShadowNodeTraits { ViewKind = 1 << 0, RootNodeKind = 1 << 1, Hidden = 1 << 2, - DirtyYogaNode = 1 << 3, - LeafYogaNode = 1 << 4, - MeasurableYogaNode = 1 << 5, - FormsStackingContext = 1 << 6, - FormsView = 1 << 7, - ChildrenAreShared = 1 << 8, - ChildrenFormStackingContext = 1 << 9, - BaselineYogaNode = 1 << 10, - ForceFlattenView = 1 << 11, + LeafYogaNode = 1 << 3, + MeasurableYogaNode = 1 << 4, + FormsStackingContext = 1 << 5, + FormsView = 1 << 6, + ChildrenAreShared = 1 << 7, + ChildrenFormStackingContext = 1 << 8, + BaselineYogaNode = 1 << 9, + ForceFlattenView = 1 << 10, + KeyboardFocusable = 1 << 11, + Unstable_uncullableView = 1 << 12, + Unstable_uncullableTrace = 1 << 13, }; inline void set(Trait trait) { traits_ = ShadowNodeTraits::Trait(traits_ | trait); @@ -25601,9 +28556,7 @@ class State { protected: explicit State(StateData::Shared data, const State& previousState); - explicit State( - StateData::Shared data, - const ShadowNodeFamily::Shared& family); + explicit State(StateData::Shared data, ShadowNodeFamily::Weak family); public: virtual ~State() = default; @@ -25728,11 +28681,16 @@ inline void fromRawValue( } inline std::string toString(const SharedColor& value) { ColorComponents components = colorComponentsFromColor(value); - auto ratio = 255.f; - return "rgba(" + folly::to(round(components.red * ratio)) + - ", " + folly::to(round(components.green * ratio)) + ", " + - folly::to(round(components.blue * ratio)) + ", " + - folly::to(round(components.alpha * ratio)) + ")"; + std::array buffer{}; + std::snprintf( + buffer.data(), + buffer.size(), + "rgba(%.0f, %.0f, %.0f, %.0f)", + components.red * 255.f, + components.green * 255.f, + components.blue * 255.f, + components.alpha * 255.f); + return buffer.data(); } inline void fromRawValue( const PropsParserContext& context, @@ -25876,29 +28834,6 @@ inline void fromRawValue( result = {0, 0, 0, 0}; LOG(ERROR) << "Unsupported CornerInsets type"; } -inline std::string toString(const Point& point) { - return "{" + folly::to(point.x) + ", " + - folly::to(point.y) + "}"; -} -inline std::string toString(const Size& size) { - return "{" + folly::to(size.width) + ", " + - folly::to(size.height) + "}"; -} -inline std::string toString(const Rect& rect) { - return "{" + toString(rect.origin) + ", " + toString(rect.size) + "}"; -} -inline std::string toString(const EdgeInsets& edgeInsets) { - return "{" + folly::to(edgeInsets.left) + ", " + - folly::to(edgeInsets.top) + ", " + - folly::to(edgeInsets.right) + ", " + - folly::to(edgeInsets.bottom) + "}"; -} -inline std::string toString(const CornerInsets& cornerInsets) { - return "{" + folly::to(cornerInsets.topLeft) + ", " + - folly::to(cornerInsets.topRight) + ", " + - folly::to(cornerInsets.bottomLeft) + ", " + - folly::to(cornerInsets.bottomRight) + "}"; -} } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/core/propsConversions.h}: @@ -26046,6 +28981,27 @@ class TestComponentDescriptor }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSAngle.h}: +namespace facebook::react { +struct CSSAngle { + float degrees{}; + constexpr bool operator==(const CSSAngle& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + if (token.type() == CSSTokenType::Dimension) { + if (auto unit = parseCSSAngleUnit(token.unit())) { + return CSSAngle{canonicalize(token.numericValue(), *unit)}; + } + } + return {}; + } +}; +static_assert(CSSDataType); +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/css/CSSAngleUnit.h}: namespace facebook::react { enum class CSSAngleUnit : uint8_t { @@ -26084,460 +29040,828 @@ constexpr float canonicalize(float value, CSSAngleUnit unit) { } } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSColorUtils.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSColor.h}: namespace facebook::react { -template -constexpr std::optional parseCSSNamedColor(std::string_view name) { - switch (fnv1aLowercase(name)) { - case fnv1a("aliceblue"): - return CSSValueT::color(240, 248, 255, 255); - case fnv1a("antiquewhite"): - return CSSValueT::color(250, 235, 215, 255); - case fnv1a("aqua"): - return CSSValueT::color(0, 255, 255, 255); - case fnv1a("aquamarine"): - return CSSValueT::color(127, 255, 212, 255); - case fnv1a("azure"): - return CSSValueT::color(240, 255, 255, 255); - case fnv1a("beige"): - return CSSValueT::color(245, 245, 220, 255); - case fnv1a("bisque"): - return CSSValueT::color(255, 228, 196, 255); - case fnv1a("black"): - return CSSValueT::color(0, 0, 0, 255); - case fnv1a("blanchedalmond"): - return CSSValueT::color(255, 235, 205, 255); - case fnv1a("blue"): - return CSSValueT::color(0, 0, 255, 255); - case fnv1a("blueviolet"): - return CSSValueT::color(138, 43, 226, 255); - case fnv1a("brown"): - return CSSValueT::color(165, 42, 42, 255); - case fnv1a("burlywood"): - return CSSValueT::color(222, 184, 135, 255); - case fnv1a("cadetblue"): - return CSSValueT::color(95, 158, 160, 255); - case fnv1a("chartreuse"): - return CSSValueT::color(127, 255, 0, 255); - case fnv1a("chocolate"): - return CSSValueT::color(210, 105, 30, 255); - case fnv1a("coral"): - return CSSValueT::color(255, 127, 80, 255); - case fnv1a("cornflowerblue"): - return CSSValueT::color(100, 149, 237, 255); - case fnv1a("cornsilk"): - return CSSValueT::color(255, 248, 220, 255); - case fnv1a("crimson"): - return CSSValueT::color(220, 20, 60, 255); - case fnv1a("cyan"): - return CSSValueT::color(0, 255, 255, 255); - case fnv1a("darkblue"): - return CSSValueT::color(0, 0, 139, 255); - case fnv1a("darkcyan"): - return CSSValueT::color(0, 139, 139, 255); - case fnv1a("darkgoldenrod"): - return CSSValueT::color(184, 134, 11, 255); - case fnv1a("darkgray"): - return CSSValueT::color(169, 169, 169, 255); - case fnv1a("darkgreen"): - return CSSValueT::color(0, 100, 0, 255); - case fnv1a("darkgrey"): - return CSSValueT::color(169, 169, 169, 255); - case fnv1a("darkkhaki"): - return CSSValueT::color(189, 183, 107, 255); - case fnv1a("darkmagenta"): - return CSSValueT::color(139, 0, 139, 255); - case fnv1a("darkolivegreen"): - return CSSValueT::color(85, 107, 47, 255); - case fnv1a("darkorange"): - return CSSValueT::color(255, 140, 0, 255); - case fnv1a("darkorchid"): - return CSSValueT::color(153, 50, 204, 255); - case fnv1a("darkred"): - return CSSValueT::color(139, 0, 0, 255); - case fnv1a("darksalmon"): - return CSSValueT::color(233, 150, 122, 255); - case fnv1a("darkseagreen"): - return CSSValueT::color(143, 188, 143, 255); - case fnv1a("darkslateblue"): - return CSSValueT::color(72, 61, 139, 255); - case fnv1a("darkslategray"): - return CSSValueT::color(47, 79, 79, 255); - case fnv1a("darkslategrey"): - return CSSValueT::color(47, 79, 79, 255); - case fnv1a("darkturquoise"): - return CSSValueT::color(0, 206, 209, 255); - case fnv1a("darkviolet"): - return CSSValueT::color(148, 0, 211, 255); - case fnv1a("deeppink"): - return CSSValueT::color(255, 20, 147, 255); - case fnv1a("deepskyblue"): - return CSSValueT::color(0, 191, 255, 255); - case fnv1a("dimgray"): - return CSSValueT::color(105, 105, 105, 255); - case fnv1a("dimgrey"): - return CSSValueT::color(105, 105, 105, 255); - case fnv1a("dodgerblue"): - return CSSValueT::color(30, 144, 255, 255); - case fnv1a("firebrick"): - return CSSValueT::color(178, 34, 34, 255); - case fnv1a("floralwhite"): - return CSSValueT::color(255, 250, 240, 255); - case fnv1a("forestgreen"): - return CSSValueT::color(34, 139, 34, 255); - case fnv1a("fuchsia"): - return CSSValueT::color(255, 0, 255, 255); - case fnv1a("gainsboro"): - return CSSValueT::color(220, 220, 220, 255); - case fnv1a("ghostwhite"): - return CSSValueT::color(248, 248, 255, 255); - case fnv1a("gold"): - return CSSValueT::color(255, 215, 0, 255); - case fnv1a("goldenrod"): - return CSSValueT::color(218, 165, 32, 255); - case fnv1a("gray"): - return CSSValueT::color(128, 128, 128, 255); - case fnv1a("green"): - return CSSValueT::color(0, 128, 0, 255); - case fnv1a("greenyellow"): - return CSSValueT::color(173, 255, 47, 255); - case fnv1a("grey"): - return CSSValueT::color(128, 128, 128, 255); - case fnv1a("honeydew"): - return CSSValueT::color(240, 255, 240, 255); - case fnv1a("hotpink"): - return CSSValueT::color(255, 105, 180, 255); - case fnv1a("indianred"): - return CSSValueT::color(205, 92, 92, 255); - case fnv1a("indigo"): - return CSSValueT::color(75, 0, 130, 255); - case fnv1a("ivory"): - return CSSValueT::color(255, 255, 240, 255); - case fnv1a("khaki"): - return CSSValueT::color(240, 230, 140, 255); - case fnv1a("lavender"): - return CSSValueT::color(230, 230, 250, 255); - case fnv1a("lavenderblush"): - return CSSValueT::color(255, 240, 245, 255); - case fnv1a("lawngreen"): - return CSSValueT::color(124, 252, 0, 255); - case fnv1a("lemonchiffon"): - return CSSValueT::color(255, 250, 205, 255); - case fnv1a("lightblue"): - return CSSValueT::color(173, 216, 230, 255); - case fnv1a("lightcoral"): - return CSSValueT::color(240, 128, 128, 255); - case fnv1a("lightcyan"): - return CSSValueT::color(224, 255, 255, 255); - case fnv1a("lightgoldenrodyellow"): - return CSSValueT::color(250, 250, 210, 255); - case fnv1a("lightgray"): - return CSSValueT::color(211, 211, 211, 255); - case fnv1a("lightgreen"): - return CSSValueT::color(144, 238, 144, 255); - case fnv1a("lightgrey"): - return CSSValueT::color(211, 211, 211, 255); - case fnv1a("lightpink"): - return CSSValueT::color(255, 182, 193, 255); - case fnv1a("lightsalmon"): - return CSSValueT::color(255, 160, 122, 255); - case fnv1a("lightseagreen"): - return CSSValueT::color(32, 178, 170, 255); - case fnv1a("lightskyblue"): - return CSSValueT::color(135, 206, 250, 255); - case fnv1a("lightslategray"): - return CSSValueT::color(119, 136, 153, 255); - case fnv1a("lightslategrey"): - return CSSValueT::color(119, 136, 153, 255); - case fnv1a("lightsteelblue"): - return CSSValueT::color(176, 196, 222, 255); - case fnv1a("lightyellow"): - return CSSValueT::color(255, 255, 224, 255); - case fnv1a("lime"): - return CSSValueT::color(0, 255, 0, 255); - case fnv1a("limegreen"): - return CSSValueT::color(50, 205, 50, 255); - case fnv1a("linen"): - return CSSValueT::color(250, 240, 230, 255); - case fnv1a("magenta"): - return CSSValueT::color(255, 0, 255, 255); - case fnv1a("maroon"): - return CSSValueT::color(128, 0, 0, 255); - case fnv1a("mediumaquamarine"): - return CSSValueT::color(102, 205, 170, 255); - case fnv1a("mediumblue"): - return CSSValueT::color(0, 0, 205, 255); - case fnv1a("mediumorchid"): - return CSSValueT::color(186, 85, 211, 255); - case fnv1a("mediumpurple"): - return CSSValueT::color(147, 112, 219, 255); - case fnv1a("mediumseagreen"): - return CSSValueT::color(60, 179, 113, 255); - case fnv1a("mediumslateblue"): - return CSSValueT::color(123, 104, 238, 255); - case fnv1a("mediumspringgreen"): - return CSSValueT::color(0, 250, 154, 255); - case fnv1a("mediumturquoise"): - return CSSValueT::color(72, 209, 204, 255); - case fnv1a("mediumvioletred"): - return CSSValueT::color(199, 21, 133, 255); - case fnv1a("midnightblue"): - return CSSValueT::color(25, 25, 112, 255); - case fnv1a("mintcream"): - return CSSValueT::color(245, 255, 250, 255); - case fnv1a("mistyrose"): - return CSSValueT::color(255, 228, 225, 255); - case fnv1a("moccasin"): - return CSSValueT::color(255, 228, 181, 255); - case fnv1a("navajowhite"): - return CSSValueT::color(255, 222, 173, 255); - case fnv1a("navy"): - return CSSValueT::color(0, 0, 128, 255); - case fnv1a("oldlace"): - return CSSValueT::color(253, 245, 230, 255); - case fnv1a("olive"): - return CSSValueT::color(128, 128, 0, 255); - case fnv1a("olivedrab"): - return CSSValueT::color(107, 142, 35, 255); - case fnv1a("orange"): - return CSSValueT::color(255, 165, 0, 255); - case fnv1a("orangered"): - return CSSValueT::color(255, 69, 0, 255); - case fnv1a("orchid"): - return CSSValueT::color(218, 112, 214, 255); - case fnv1a("palegoldenrod"): - return CSSValueT::color(238, 232, 170, 255); - case fnv1a("palegreen"): - return CSSValueT::color(152, 251, 152, 255); - case fnv1a("paleturquoise"): - return CSSValueT::color(175, 238, 238, 255); - case fnv1a("palevioletred"): - return CSSValueT::color(219, 112, 147, 255); - case fnv1a("papayawhip"): - return CSSValueT::color(255, 239, 213, 255); - case fnv1a("peachpuff"): - return CSSValueT::color(255, 218, 185, 255); - case fnv1a("peru"): - return CSSValueT::color(205, 133, 63, 255); - case fnv1a("pink"): - return CSSValueT::color(255, 192, 203, 255); - case fnv1a("plum"): - return CSSValueT::color(221, 160, 221, 255); - case fnv1a("powderblue"): - return CSSValueT::color(176, 224, 230, 255); - case fnv1a("purple"): - return CSSValueT::color(128, 0, 128, 255); - case fnv1a("rebeccapurple"): - return CSSValueT::color(102, 51, 153, 255); - case fnv1a("red"): - return CSSValueT::color(255, 0, 0, 255); - case fnv1a("rosybrown"): - return CSSValueT::color(188, 143, 143, 255); - case fnv1a("royalblue"): - return CSSValueT::color(65, 105, 225, 255); - case fnv1a("saddlebrown"): - return CSSValueT::color(139, 69, 19, 255); - case fnv1a("salmon"): - return CSSValueT::color(250, 128, 114, 255); - case fnv1a("sandybrown"): - return CSSValueT::color(244, 164, 96, 255); - case fnv1a("seagreen"): - return CSSValueT::color(46, 139, 87, 255); - case fnv1a("seashell"): - return CSSValueT::color(255, 245, 238, 255); - case fnv1a("sienna"): - return CSSValueT::color(160, 82, 45, 255); - case fnv1a("silver"): - return CSSValueT::color(192, 192, 192, 255); - case fnv1a("skyblue"): - return CSSValueT::color(135, 206, 235, 255); - case fnv1a("slateblue"): - return CSSValueT::color(106, 90, 205, 255); - case fnv1a("slategray"): - return CSSValueT::color(112, 128, 144, 255); - case fnv1a("slategrey"): - return CSSValueT::color(112, 128, 144, 255); - case fnv1a("snow"): - return CSSValueT::color(255, 250, 250, 255); - case fnv1a("springgreen"): - return CSSValueT::color(0, 255, 127, 255); - case fnv1a("steelblue"): - return CSSValueT::color(70, 130, 180, 255); - case fnv1a("tan"): - return CSSValueT::color(210, 180, 140, 255); - case fnv1a("teal"): - return CSSValueT::color(0, 128, 128, 255); - case fnv1a("thistle"): - return CSSValueT::color(216, 191, 216, 255); - case fnv1a("tomato"): - return CSSValueT::color(255, 99, 71, 255); - case fnv1a("turquoise"): - return CSSValueT::color(64, 224, 208, 255); - case fnv1a("violet"): - return CSSValueT::color(238, 130, 238, 255); - case fnv1a("wheat"): - return CSSValueT::color(245, 222, 179, 255); - case fnv1a("white"): - return CSSValueT::color(255, 255, 255, 255); - case fnv1a("whitesmoke"): - return CSSValueT::color(245, 245, 245, 255); - case fnv1a("yellow"): - return CSSValueT::color(255, 255, 0, 255); - case fnv1a("yellowgreen"): - return CSSValueT::color(154, 205, 50, 255); - default: - return std::nullopt; +struct CSSColor { + uint8_t r{}; + uint8_t g{}; + uint8_t b{}; + uint8_t a{}; + constexpr bool operator==(const CSSColor& rhs) const = default; + static constexpr CSSColor black() { + return {0, 0, 0, 255}; + } +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + switch (token.type()) { + case CSSTokenType::Ident: + return parseCSSNamedColor(token.stringValue()); + case CSSTokenType::Hash: + return parseCSSHexColor(token.stringValue()); + default: + return {}; + } + } + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + return parseCSSColorFunction(func.name, parser); } -} -enum class HexColorType { - Long, - Short, }; -constexpr char toLower(char c) { - if (c >= 'A' && c <= 'Z') { - return static_cast(c + 32); +static_assert(CSSDataType); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSColorFunction.h}: +namespace facebook::react { +namespace detail { +constexpr uint8_t clamp255Component(float f) { + auto i = static_cast(f); + auto ceiled = f > i ? i + 1 : i; + return static_cast(std::clamp(ceiled, 0, 255)); +} +constexpr std::optional normalizeNumberComponent( + const std::variant& component) { + if (std::holds_alternative(component)) { + return std::get(component).value; } - return c; + return {}; } -constexpr uint8_t hexToNumeric(std::string_view hex, HexColorType hexType) { - int result = 0; - for (char c : hex) { - int value = 0; - if (c >= '0' && c <= '9') { - value = c - '0'; - } else { - value = toLower(c) - 'a' + 10; +constexpr uint8_t clampAlpha(std::optional alpha) { + return alpha.has_value() ? clamp255Component(*alpha * 255.0f) + : static_cast(255u); +} +inline float normalizeHue(float hue) { + auto rem = std::remainder(hue, 360.0f); + return (rem < 0 ? rem + 360 : rem) / 360.0f; +} +inline std::optional normalizeHueComponent( + const std::variant& component) { + if (std::holds_alternative(component)) { + return normalizeHue(std::get(component).value); + } else if (std::holds_alternative(component)) { + return normalizeHue(std::get(component).degrees); + } + return {}; +} +constexpr float hueToRgb(float p, float q, float t) { + if (t < 0.0f) { + t += 1.0f; + } + if (t > 1.0f) { + t -= 1.0f; + } + if (t < 1.0f / 6.0f) { + return p + (q - p) * 6 * t; + } + if (t < 1.0f / 2.0f) { + return q; + } + if (t < 2.0f / 3.0f) { + return p + (q - p) * (2.0f / 3.0f - t) * 6.0f; + } + return p; +} +inline std::tuple +hslToRgb(float h, float s, float l) { + s = std::clamp(s / 100.0f, 0.0f, 1.0f); + l = std::clamp(l / 100.0f, 0.0f, 1.0f); + auto q = l < 0.5f ? l * (1.0f + s) : l + s - l * s; + auto p = 2.0f * l - q; + auto r = hueToRgb(p, q, h + 1.0f / 3.0f); + auto g = hueToRgb(p, q, h); + auto b = hueToRgb(p, q, h - 1.0f / 3.0f); + return { + static_cast(std::round(r * 255.0f)), + static_cast(std::round(g * 255.0f)), + static_cast(std::round(b * 255.0f)), + }; +} +inline std::tuple +hwbToRgb(float h, float w, float b) { + w = std::clamp(w / 100.0f, 0.0f, 1.0f); + b = std::clamp(b / 100.0f, 0.0f, 1.0f); + if (w + b >= 1.0f) { + auto gray = w / (w + b); + return { + static_cast(std::round(gray * 255.0f)), + static_cast(std::round(gray * 255.0f)), + static_cast(std::round(gray * 255.0f)), + }; + } + auto red = hueToRgb(0.0f, 1.0f, h + 1.0f / 3.0f) * (1.0f - w - b) + w; + auto green = hueToRgb(0.0f, 1.0f, h) * (1.0f - w - b) + w; + auto blue = hueToRgb(0.0f, 1.0f, h - 1.0f / 3.0f) * (1.0f - w - b) + w; + return { + static_cast(std::round(red * 255.0f)), + static_cast(std::round(green * 255.0f)), + static_cast(std::round(blue * 255.0f)), + }; +} +template + requires( + (std::is_same_v || + std::is_same_v) && + ...) +constexpr std::optional normalizeComponent( + const std::variant& component, + float baseValue) { + if constexpr (traits::containsType()) { + if (std::holds_alternative(component)) { + return std::get(component).value / 100.0f * baseValue; } - result *= 16; - result += value; } - if (hexType == HexColorType::Short) { - return result * 16 + result; + if constexpr (traits::containsType()) { + if (std::holds_alternative(component)) { + return std::get(component).value; + } + } + return {}; +} +template +constexpr bool isLegacyColorFunction(CSSSyntaxParser& parser) { + auto lookahead = parser; + auto next = parseNextCSSValue(lookahead); + if (std::holds_alternative(next)) { + return false; + } + return lookahead.consumeComponentValue( + CSSDelimiter::OptionalWhitespace, [](CSSPreservedToken token) { + return token.type() == CSSTokenType::Comma; + }); +} +template +constexpr std::optional parseLegacyRgbFunction( + CSSSyntaxParser& parser) { + auto rawRed = parseNextCSSValue(parser); + bool usesNumber = std::holds_alternative(rawRed); + auto red = normalizeComponent(rawRed, 255.0f); + if (!red.has_value()) { + return {}; + } + auto green = usesNumber + ? normalizeNumberComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma)) + : normalizeComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma), + 255.0f); + if (!green.has_value()) { + return {}; + } + auto blue = usesNumber + ? normalizeNumberComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma)) + : normalizeComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma), + 255.0f); + if (!blue.has_value()) { + return {}; + } + auto alpha = normalizeComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma), + 1.0f); + return CSSColor{ + .r = clamp255Component(*red), + .g = clamp255Component(*green), + .b = clamp255Component(*blue), + .a = clampAlpha(alpha), + }; +} +template +constexpr std::optional parseModernRgbFunction( + CSSSyntaxParser& parser) { + auto red = normalizeComponent( + parseNextCSSValue(parser), 255.0f); + if (!red.has_value()) { + return {}; + } + auto green = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::Whitespace), + 255.0f); + if (!green.has_value()) { + return {}; + } + auto blue = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::Whitespace), + 255.0f); + if (!blue.has_value()) { + return {}; + } + auto alpha = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::SolidusOrWhitespace), + 1.0f); + return CSSColor{ + .r = clamp255Component(*red), + .g = clamp255Component(*green), + .b = clamp255Component(*blue), + .a = clampAlpha(alpha), + }; +} +template +constexpr std::optional parseRgbFunction(CSSSyntaxParser& parser) { + if (isLegacyColorFunction(parser)) { + return parseLegacyRgbFunction(parser); } else { - return result; + return parseModernRgbFunction(parser); } } -constexpr bool isHexDigit(char c) { - return (c >= '0' && c <= '9') || (toLower(c) >= 'a' && toLower(c) <= 'f'); +template +inline std::optional parseLegacyHslFunction(CSSSyntaxParser& parser) { + auto h = + normalizeHueComponent(parseNextCSSValue(parser)); + if (!h.has_value()) { + return {}; + } + auto s = normalizeComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma), 100.0f); + if (!s.has_value()) { + return {}; + } + auto l = normalizeComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma), 100.0f); + if (!l.has_value()) { + return {}; + } + auto a = normalizeComponent( + parseNextCSSValue(parser, CSSDelimiter::Comma), + 1.0f); + auto [r, g, b] = hslToRgb(*h, *s, *l); + return CSSColor{ + .r = r, + .g = g, + .b = b, + .a = clampAlpha(a), + }; } -constexpr bool isValidHexColor(std::string_view hex) { - if (hex.size() != 3 && hex.size() != 4 && hex.size() != 6 && - hex.size() != 8) { - return false; +template +inline std::optional parseModernHslFunction(CSSSyntaxParser& parser) { + auto h = + normalizeHueComponent(parseNextCSSValue(parser)); + if (!h.has_value()) { + return {}; } - for (auto c : hex) { - if (!isHexDigit(c)) { - return false; - } + auto s = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::Whitespace), + 100.0f); + if (!s.has_value()) { + return {}; } - return true; + auto l = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::Whitespace), + 100.0f); + if (!l.has_value()) { + return {}; + } + auto a = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::SolidusOrWhitespace), + 1.0f); + auto [r, g, b] = hslToRgb(*h, *s, *l); + return CSSColor{ + .r = r, + .g = g, + .b = b, + .a = clampAlpha(a), + }; } -}; // namespace facebook::react - -/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSDeclaredStyle.h}: -namespace facebook::react { -namespace detail { -constexpr CSSProp kFirstCSSProp = static_cast(0); -template -constexpr size_t maxSizeofDeclaredValue() { - if constexpr (to_underlying(Prop) < kCSSPropCount - 1) { - return std::max( - sizeof(CSSDeclaredValue), - maxSizeofDeclaredValue( - to_underlying(Prop) + 1)>()); +template +inline std::optional parseHslFunction(CSSSyntaxParser& parser) { + if (isLegacyColorFunction(parser)) { + return parseLegacyHslFunction(parser); } else { - return sizeof(CSSDeclaredValue); + return parseModernHslFunction(parser); + } +} +template +inline std::optional parseHwbFunction(CSSSyntaxParser& parser) { + auto h = + normalizeHueComponent(parseNextCSSValue(parser)); + if (!h.has_value()) { + return {}; + } + auto w = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::Whitespace), + 100.0f); + if (!w.has_value()) { + return {}; } + auto b = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::Whitespace), + 100.0f); + if (!b.has_value()) { + return {}; + } + auto a = normalizeComponent( + parseNextCSSValue( + parser, CSSDelimiter::SolidusOrWhitespace), + 1.0f); + auto [red, green, blue] = hwbToRgb(*h, *w, *b); + return CSSColor{ + .r = red, + .g = green, + .b = blue, + .a = clampAlpha(a), + }; } } // namespace detail -class CSSDeclaredStyle { - public: - template - void set(const CSSDeclaredValue& value) { - using DeclaredValueT = std::remove_cvref_t>; - static_assert(sizeof(value) <= sizeof(PropMapping::value)); - static_assert(std::is_trivially_destructible_v); - if (specifiedProperties_.test(to_underlying(Prop))) { - auto it = std::lower_bound( - properties_.begin(), properties_.end(), PropMapping{Prop, {}}); - react_native_assert(it->prop == Prop); - std::construct_at( - reinterpret_cast(it->value.data()), value); - } else { - auto it = std::upper_bound( - properties_.begin(), properties_.end(), PropMapping{Prop, {}}); - it = properties_.insert(it, {Prop, {}}); - std::construct_at( - reinterpret_cast(it->value.data()), value); - specifiedProperties_.set(to_underlying(Prop)); - } - } - template - bool set(std::string_view value) { - auto cssProp = parseCSSProp(value); - set(cssProp); - return cssProp.hasValue(); - } - bool set(std::string_view prop, std::string_view value) { - return setPropIfHashMatches(fnv1a(prop), value); - } - template - CSSDeclaredValue get() const { - if (specifiedProperties_.test(to_underlying(Prop))) { - auto it = std::lower_bound( - properties_.begin(), properties_.end(), PropMapping{Prop, {}}); - react_native_assert(it->prop == Prop); - CSSDeclaredValue value{*std::launder( - reinterpret_cast*>(it->value.data()))}; - if (value) { - return value; - } - } - if constexpr (sizeof...(ShorthandsT) == 0) { +template +constexpr std::optional parseCSSColorFunction( + std::string_view colorFunction, + CSSSyntaxParser& parser) { + switch (fnv1aLowercase(colorFunction)) { + case fnv1a("rgb"): + case fnv1a("rgba"): + return detail::parseRgbFunction(parser); + break; + case fnv1a("hsl"): + case fnv1a("hsla"): + return detail::parseHslFunction(parser); + break; + case fnv1a("hwb"): + return detail::parseHwbFunction(parser); + break; + default: return {}; - } else { - return get(); - } - } - bool operator==(const CSSDeclaredStyle& rhs) const = default; -}; - template - constexpr bool setPropIfHashMatches( - size_t propNameHash, - std::string_view value) { - constexpr std::string_view currentPropName = - CSSPropDefinition::kName; - constexpr size_t currentHash = fnv1a(currentPropName); - if (currentHash == propNameHash) { - return set(value); - } else if constexpr (to_underlying(CurrentProp) < kCSSPropCount - 1) { - return setPropIfHashMatches( - to_underlying(CurrentProp) + 1)>(propNameHash, value); - } else { - return false; - } } - std::vector properties_; - std::bitset specifiedProperties_; -}; + return {}; +} } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSKeywords.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSCompoundDataType.h}: namespace facebook::react { -enum class CSSKeyword : uint8_t { - Absolute, - Auto, - Baseline, - Block, - Center, - Clip, - Column, - ColumnReverse, - Content, - Contents, - Dashed, - Dotted, - Double, +namespace detail { +struct CSSCompoundDataTypeMarker {}; +} // namespace detail +template +struct CSSCompoundDataType : public detail::CSSCompoundDataTypeMarker {}; +template +concept CSSValidCompoundDataType = + std::is_base_of_v; +template +concept CSSMaybeCompoundDataType = + CSSDataType || CSSValidCompoundDataType; +namespace detail { +template +template < + CSSDataType... AlllowedTypes1T, + CSSDataType... AlllowedTypes2T, + CSSMaybeCompoundDataType... RestT> +struct merge_data_types< + CSSCompoundDataType, + CSSCompoundDataType, + RestT...> { + using type = typename merge_data_types< + CSSCompoundDataType, + RestT...>::type; +}; +template < + CSSDataType AlllowedType1T, + CSSDataType... AlllowedTypes2T, + CSSMaybeCompoundDataType... RestT> +struct merge_data_types< + AlllowedType1T, + CSSCompoundDataType, + RestT...> { + using type = typename merge_data_types< + CSSCompoundDataType, + RestT...>::type; +}; +template < + CSSDataType AlllowedType2T, + CSSDataType... AlllowedTypes1T, + CSSMaybeCompoundDataType... RestT> +struct merge_data_types< + CSSCompoundDataType, + AlllowedType2T, + RestT...> { + using type = typename merge_data_types< + CSSCompoundDataType, + RestT...>::type; +}; +template < + CSSDataType AlllowedType1T, + CSSDataType AlllowedType2T, + CSSMaybeCompoundDataType... RestT> +struct merge_data_types { + using type = typename merge_data_types< + CSSCompoundDataType, + RestT...>::type; +}; +template +struct merge_data_types> { + using type = CSSCompoundDataType; +}; +template +struct merge_data_types { + using type = CSSCompoundDataType; +}; +template +template +struct merge_variant, RestT...> { + using type = std::variant; +}; +} // namespace detail +template +using CSSMergedDataTypes = typename detail::merge_data_types::type; +template +using CSSVariantWithTypes = + typename detail::merge_variant::type; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSDataType.h}: +namespace facebook::react { +template +struct CSSDataTypeParser {}; +template +concept CSSFunctionBlockSink = + requires(const CSSFunctionBlock& func, CSSSyntaxParser& parser) { + { T::consumeFunctionBlock(func, parser) } -> std::convertible_to; + }; +template +concept CSSSimpleBlockSink = + requires(const CSSSimpleBlock& block, CSSSyntaxParser& parser) { + { T::consumeSimpleBlock(block, parser) } -> std::convertible_to; + }; +template +concept CSSPreservedTokenSink = requires(const CSSPreservedToken& token) { + { T::consumePreservedToken(token) } -> std::convertible_to; +}; +template +concept CSSParserSink = requires(CSSSyntaxParser& parser) { + { T::consume(parser) } -> std::convertible_to; +}; +template +concept CSSValidDataTypeParser = + ((CSSFunctionBlockSink || CSSSimpleBlockSink || + CSSPreservedTokenSink) && + !CSSParserSink) || + CSSParserSink; +template +concept CSSDataType = + CSSValidDataTypeParser, std::optional> && + std::equality_comparable; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSFilter.h}: +namespace facebook::react { +namespace detail { +template + requires(std::is_same_v) +struct CSSFilterSimpleAmountParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, Name)) { + return {}; + } + auto amount = parseNextCSSValue(parser); + if (std::holds_alternative(amount)) { + if (std::get(amount).value < 0.0f) { + return {}; + } + return DataT{std::get(amount).value}; + } else if (std::holds_alternative(amount)) { + if (std::get(amount).value < 0.0f) { + return {}; + } + return DataT{std::get(amount).value / 100.0f}; + } else { + return DataT{}; + } + } +}; +} // namespace detail +struct CSSBlurFilter { + CSSLength amount{}; + constexpr bool operator==(const CSSBlurFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "blur")) { + return {}; + } + auto len = parseNextCSSValue(parser); + return CSSBlurFilter{ + std::holds_alternative(len) ? std::get(len) + : CSSLength{}}; + } +}; +static_assert(CSSDataType); +struct CSSBrightnessFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSBrightnessFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail:: + CSSFilterSimpleAmountParser {}; +static_assert(CSSDataType); +struct CSSContrastFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSContrastFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail:: + CSSFilterSimpleAmountParser {}; +static_assert(CSSDataType); +struct CSSDropShadowFilter { + CSSLength offsetX{}; + CSSLength offsetY{}; + CSSLength standardDeviation{}; + CSSColor color{}; + constexpr bool operator==(const CSSDropShadowFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "drop-shadow")) { + return {}; + } + std::optional color{}; + std::optional> lengths{}; + auto firstVal = parseNextCSSValue(parser); + if (std::holds_alternative(firstVal)) { + return {}; + } + if (std::holds_alternative(firstVal)) { + color = std::get(firstVal); + } else { + lengths = parseLengths(std::get(firstVal), parser); + if (!lengths.has_value()) { + return {}; + } + } + auto secondVal = parseNextCSSValue( + parser, CSSDelimiter::Whitespace); + if (std::holds_alternative(secondVal)) { + if (color.has_value()) { + return {}; + } + color = std::get(secondVal); + } else if (std::holds_alternative(secondVal)) { + if (lengths.has_value()) { + return {}; + } + lengths = parseLengths(std::get(secondVal), parser); + } + if (!lengths.has_value()) { + return {}; + } + return CSSDropShadowFilter{ + .offsetX = (*lengths)[0], + .offsetY = (*lengths)[1], + .standardDeviation = (*lengths)[2], + .color = color.value_or(CSSColor::black()), + }; + } +}; + } + auto standardDeviation = + parseNextCSSValue(parser, CSSDelimiter::Whitespace); + if (std::holds_alternative(standardDeviation) && + std::get(standardDeviation).value < 0.0f) { + return {}; + } + return std::array{ + offsetX, + std::get(offsetY), + std::holds_alternative(standardDeviation) + ? std::get(standardDeviation) + : CSSLength{}}; + } +}; +static_assert(CSSDataType); +struct CSSGrayscaleFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSGrayscaleFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail:: + CSSFilterSimpleAmountParser {}; +static_assert(CSSDataType); +struct CSSHueRotateFilter { + float degrees{}; + constexpr bool operator==(const CSSHueRotateFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "hue-rotate")) { + return {}; + } + auto angle = parseNextCSSValue(parser); + return CSSHueRotateFilter{ + std::holds_alternative(angle) + ? std::get(angle).degrees + : 0.0f}; + } +}; +static_assert(CSSDataType); +struct CSSInvertFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSInvertFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSFilterSimpleAmountParser {}; +static_assert(CSSDataType); +struct CSSOpacityFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSOpacityFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSFilterSimpleAmountParser { +}; +static_assert(CSSDataType); +struct CSSSaturateFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSSaturateFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail:: + CSSFilterSimpleAmountParser {}; +static_assert(CSSDataType); +struct CSSSepiaFilter { + float amount{1.0f}; + constexpr bool operator==(const CSSSepiaFilter& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSFilterSimpleAmountParser {}; +static_assert(CSSDataType); +using CSSFilterFunction = CSSCompoundDataType< + CSSBlurFilter, + CSSBrightnessFilter, + CSSContrastFilter, + CSSDropShadowFilter, + CSSGrayscaleFilter, + CSSHueRotateFilter, + CSSInvertFilter, + CSSOpacityFilter, + CSSSaturateFilter, + CSSSepiaFilter>; +using CSSFilterFunctionVariant = CSSVariantWithTypes; +using CSSFilterList = CSSWhitespaceSeparatedList; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSFontVariant.h}: +namespace facebook::react { +enum class CSSFontVariant : std::underlying_type_t { + SmallCaps = to_underlying(CSSKeyword::SmallCaps), + OldstyleNums = to_underlying(CSSKeyword::OldstyleNums), + LiningNums = to_underlying(CSSKeyword::LiningNums), + TabularNums = to_underlying(CSSKeyword::TabularNums), + CommonLigatures = to_underlying(CSSKeyword::CommonLigatures), + NoCommonLigatures = to_underlying(CSSKeyword::NoCommonLigatures), + DiscretionaryLigatures = to_underlying(CSSKeyword::DiscretionaryLigatures), + NoDiscretionaryLigatures = + to_underlying(CSSKeyword::NoDiscretionaryLigatures), + HistoricalLigatures = to_underlying(CSSKeyword::HistoricalLigatures), + NoHistoricalLigatures = to_underlying(CSSKeyword::NoHistoricalLigatures), + Contextual = to_underlying(CSSKeyword::Contextual), + NoContextual = to_underlying(CSSKeyword::NoContextual), + ProportionalNums = to_underlying(CSSKeyword::ProportionalNums), + StylisticOne = to_underlying(CSSKeyword::StylisticOne), + StylisticTwo = to_underlying(CSSKeyword::StylisticTwo), + StylisticThree = to_underlying(CSSKeyword::StylisticThree), + StylisticFour = to_underlying(CSSKeyword::StylisticFour), + StylisticFive = to_underlying(CSSKeyword::StylisticFive), + StylisticSix = to_underlying(CSSKeyword::StylisticSix), + StylisticSeven = to_underlying(CSSKeyword::StylisticSeven), + StylisticEight = to_underlying(CSSKeyword::StylisticEight), + StylisticNine = to_underlying(CSSKeyword::StylisticNine), + StylisticTen = to_underlying(CSSKeyword::StylisticTen), + StylisticEleven = to_underlying(CSSKeyword::StylisticEleven), + StylisticTwelve = to_underlying(CSSKeyword::StylisticTwelve), + StylisticThirteen = to_underlying(CSSKeyword::StylisticThirteen), + StylisticFourteen = to_underlying(CSSKeyword::StylisticFourteen), + StylisticFifteen = to_underlying(CSSKeyword::StylisticFifteen), + StylisticSixteen = to_underlying(CSSKeyword::StylisticSixteen), + StylisticSeventeen = to_underlying(CSSKeyword::StylisticSeventeen), + StylisticEighteen = to_underlying(CSSKeyword::StylisticEighteen), + StylisticNineteen = to_underlying(CSSKeyword::StylisticNineteen), + StylisticTwenty = to_underlying(CSSKeyword::StylisticTwenty), +}; +static_assert(CSSDataType); +using CSSFontVariantList = CSSWhitespaceSeparatedList; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSHexColor.h}: +namespace facebook::react { +namespace detail { +enum class HexColorType { + Long, + Short, +}; +constexpr uint8_t hexToNumeric(std::string_view hex, HexColorType hexType) { + int result = 0; + for (char c : hex) { + int value = 0; + if (c >= '0' && c <= '9') { + value = c - '0'; + } else { + value = toLower(c) - 'a' + 10; + } + result *= 16; + result += value; + } + if (hexType == HexColorType::Short) { + return result * 16 + result; + } else { + return result; + } +} +constexpr bool isHexDigit(char c) { + return (c >= '0' && c <= '9') || (toLower(c) >= 'a' && toLower(c) <= 'f'); +} +constexpr bool isValidHexColor(std::string_view hex) { + if (hex.size() != 3 && hex.size() != 4 && hex.size() != 6 && + hex.size() != 8) { + return false; + } + for (auto c : hex) { + if (!isHexDigit(c)) { + return false; + } + } + return true; +} +} // namespace detail +template +constexpr std::optional parseCSSHexColor( + std::string_view hexColorValue) { + if (detail::isValidHexColor(hexColorValue)) { + if (hexColorValue.length() == 3) { + return CSSColor{ + hexToNumeric(hexColorValue.substr(0, 1), detail::HexColorType::Short), + hexToNumeric(hexColorValue.substr(1, 1), detail::HexColorType::Short), + hexToNumeric(hexColorValue.substr(2, 1), detail::HexColorType::Short), + 255u}; + } else if (hexColorValue.length() == 4) { + return CSSColor{ + hexToNumeric(hexColorValue.substr(0, 1), detail::HexColorType::Short), + hexToNumeric(hexColorValue.substr(1, 1), detail::HexColorType::Short), + hexToNumeric(hexColorValue.substr(2, 1), detail::HexColorType::Short), + hexToNumeric( + hexColorValue.substr(3, 1), detail::HexColorType::Short)}; + } else if (hexColorValue.length() == 6) { + return CSSColor{ + hexToNumeric(hexColorValue.substr(0, 2), detail::HexColorType::Long), + hexToNumeric(hexColorValue.substr(2, 2), detail::HexColorType::Long), + hexToNumeric(hexColorValue.substr(4, 2), detail::HexColorType::Long), + 255u}; + } else if (hexColorValue.length() == 8) { + return CSSColor{ + hexToNumeric(hexColorValue.substr(0, 2), detail::HexColorType::Long), + hexToNumeric(hexColorValue.substr(2, 2), detail::HexColorType::Long), + hexToNumeric(hexColorValue.substr(4, 2), detail::HexColorType::Long), + hexToNumeric(hexColorValue.substr(6, 2), detail::HexColorType::Long)}; + } + } + return {}; +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSKeyword.h}: +namespace facebook::react { +enum class CSSKeyword : uint8_t { + Absolute, + Auto, + Baseline, + Block, + Bottom, + Center, + Clip, + Column, + ColumnReverse, + CommonLigatures, + Content, + Contents, + Contextual, + Dashed, + DiscretionaryLigatures, + Dotted, + Double, End, Fixed, Flex, @@ -26546,6 +29870,7 @@ enum class CSSKeyword : uint8_t { Grid, Groove, Hidden, + HistoricalLigatures, Inherit, Initial, Inline, @@ -26553,20 +29878,30 @@ enum class CSSKeyword : uint8_t { InlineFlex, InlineGrid, Inset, + Left, + LiningNums, Ltr, MaxContent, Medium, MinContent, + NoCommonLigatures, + NoContextual, + NoDiscretionaryLigatures, + NoHistoricalLigatures, None, Normal, NoWrap, + OldstyleNums, Outset, + ProportionalNums, Relative, Ridge, + Right, Row, RowReverse, Rtl, Scroll, + SmallCaps, Solid, SpaceAround, SpaceBetween, @@ -26575,8 +29910,30 @@ enum class CSSKeyword : uint8_t { Static, Sticky, Stretch, + StylisticEight, + StylisticEighteen, + StylisticEleven, + StylisticFifteen, + StylisticFive, + StylisticFour, + StylisticFourteen, + StylisticNine, + StylisticNineteen, + StylisticOne, + StylisticSeven, + StylisticSeventeen, + StylisticSix, + StylisticSixteen, + StylisticTen, + StylisticThirteen, + StylisticThree, + StylisticTwelve, + StylisticTwenty, + StylisticTwo, + TabularNums, Thick, Thin, + Top, Unset, Visible, Wrap, @@ -26586,517 +29943,1116 @@ template concept CSSKeywordSet = std::is_enum_v && std::is_same_v, std::underlying_type_t>; -constexpr bool operator==(CSSKeywordSet auto a, CSSKeyword b) { - return to_underlying(a) == to_underlying(b); -} enum class CSSWideKeyword : std::underlying_type_t { Inherit = to_underlying(CSSKeyword::Inherit), Initial = to_underlying(CSSKeyword::Initial), Unset = to_underlying(CSSKeyword::Unset), }; -namespace detail { +namespace detail::css::keywords { template concept hasAbsolute = (CSSKeywordSet && requires() { T::Absolute; }); -} // namespace detail -namespace detail { +constexpr std::string_view Absolute{"absolute"}; +static_assert(hasAbsolute); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasAuto = (CSSKeywordSet && requires() { T::Auto; }); -} // namespace detail -namespace detail { +constexpr std::string_view Auto{"auto"}; +static_assert(hasAuto); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasBaseline = (CSSKeywordSet && requires() { T::Baseline; }); -} // namespace detail -namespace detail { +constexpr std::string_view Baseline{"baseline"}; +static_assert(hasBaseline); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasBlock = (CSSKeywordSet && requires() { T::Block; }); -} // namespace detail -namespace detail { +constexpr std::string_view Block{"block"}; +static_assert(hasBlock); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasBottom = (CSSKeywordSet && requires() { T::Bottom; }); +constexpr std::string_view Bottom{"bottom"}; +static_assert(hasBottom); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasCenter = (CSSKeywordSet && requires() { T::Center; }); -} // namespace detail -namespace detail { +constexpr std::string_view Center{"center"}; +static_assert(hasCenter); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasClip = (CSSKeywordSet && requires() { T::Clip; }); -} // namespace detail -namespace detail { +constexpr std::string_view Clip{"clip"}; +static_assert(hasClip); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasColumn = (CSSKeywordSet && requires() { T::Column; }); -} // namespace detail -namespace detail { +constexpr std::string_view Column{"column"}; +static_assert(hasColumn); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasColumnReverse = (CSSKeywordSet && requires() { T::ColumnReverse; }); -} // namespace detail -namespace detail { +constexpr std::string_view ColumnReverse{"column-reverse"}; +static_assert(hasColumnReverse); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasCommonLigatures = + (CSSKeywordSet && requires() { T::CommonLigatures; }); +constexpr std::string_view CommonLigatures{"common-ligatures"}; +static_assert(hasCommonLigatures); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasContent = (CSSKeywordSet && requires() { T::Content; }); -} // namespace detail -namespace detail { +constexpr std::string_view Content{"content"}; +static_assert(hasContent); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasContents = (CSSKeywordSet && requires() { T::Contents; }); -} // namespace detail -namespace detail { +constexpr std::string_view Contents{"contents"}; +static_assert(hasContents); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasContextual = (CSSKeywordSet && requires() { T::Contextual; }); +constexpr std::string_view Contextual{"contextual"}; +static_assert(hasContextual); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasDashed = (CSSKeywordSet && requires() { T::Dashed; }); -} // namespace detail -namespace detail { +constexpr std::string_view Dashed{"dashed"}; +static_assert(hasDashed); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasDiscretionaryLigatures = + (CSSKeywordSet && requires() { T::DiscretionaryLigatures; }); +constexpr std::string_view DiscretionaryLigatures{"discretionary-ligatures"}; +static_assert(hasDiscretionaryLigatures); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasDotted = (CSSKeywordSet && requires() { T::Dotted; }); -} // namespace detail -namespace detail { +constexpr std::string_view Dotted{"dotted"}; +static_assert(hasDotted); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasDouble = (CSSKeywordSet && requires() { T::Double; }); -} // namespace detail -namespace detail { +constexpr std::string_view Double{"double"}; +static_assert(hasDouble); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasEnd = (CSSKeywordSet && requires() { T::End; }); -} // namespace detail -namespace detail { +constexpr std::string_view End{"end"}; +static_assert(hasEnd); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasFixed = (CSSKeywordSet && requires() { T::Fixed; }); -} // namespace detail -namespace detail { +constexpr std::string_view Fixed{"fixed"}; +static_assert(hasFixed); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasFlex = (CSSKeywordSet && requires() { T::Flex; }); -} // namespace detail -namespace detail { +constexpr std::string_view Flex{"flex"}; +static_assert(hasFlex); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasFlexEnd = (CSSKeywordSet && requires() { T::FlexEnd; }); -} // namespace detail -namespace detail { +constexpr std::string_view FlexEnd{"flex-end"}; +static_assert(hasFlexEnd); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasFlexStart = (CSSKeywordSet && requires() { T::FlexStart; }); -} // namespace detail -namespace detail { +constexpr std::string_view FlexStart{"flex-start"}; +static_assert(hasFlexStart); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasGrid = (CSSKeywordSet && requires() { T::Grid; }); -} // namespace detail -namespace detail { +constexpr std::string_view Grid{"grid"}; +static_assert(hasGrid); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasGroove = (CSSKeywordSet && requires() { T::Groove; }); -} // namespace detail -namespace detail { +constexpr std::string_view Groove{"groove"}; +static_assert(hasGroove); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasHidden = (CSSKeywordSet && requires() { T::Hidden; }); -} // namespace detail -namespace detail { +constexpr std::string_view Hidden{"hidden"}; +static_assert(hasHidden); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasHistoricalLigatures = + (CSSKeywordSet && requires() { T::HistoricalLigatures; }); +constexpr std::string_view HistoricalLigatures{"historical-ligatures"}; +static_assert(hasHistoricalLigatures); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInherit = (CSSKeywordSet && requires() { T::Inherit; }); -} // namespace detail -namespace detail { +constexpr std::string_view Inherit{"inherit"}; +static_assert(hasInherit); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInitial = (CSSKeywordSet && requires() { T::Initial; }); -} // namespace detail -namespace detail { +constexpr std::string_view Initial{"initial"}; +static_assert(hasInitial); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInline = (CSSKeywordSet && requires() { T::Inline; }); -} // namespace detail -namespace detail { +constexpr std::string_view Inline{"inline"}; +static_assert(hasInline); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInlineBlock = (CSSKeywordSet && requires() { T::InlineBlock; }); -} // namespace detail -namespace detail { +constexpr std::string_view InlineBlock{"inline-block"}; +static_assert(hasInlineBlock); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInlineFlex = (CSSKeywordSet && requires() { T::InlineFlex; }); -} // namespace detail -namespace detail { +constexpr std::string_view InlineFlex{"inline-flex"}; +static_assert(hasInlineFlex); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInlineGrid = (CSSKeywordSet && requires() { T::InlineGrid; }); -} // namespace detail -namespace detail { +constexpr std::string_view InlineGrid{"inline-grid"}; +static_assert(hasInlineGrid); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasInset = (CSSKeywordSet && requires() { T::Inset; }); -} // namespace detail -namespace detail { +constexpr std::string_view Inset{"inset"}; +static_assert(hasInset); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasLeft = (CSSKeywordSet && requires() { T::Left; }); +constexpr std::string_view Left{"left"}; +static_assert(hasLeft); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasLiningNums = (CSSKeywordSet && requires() { T::LiningNums; }); +constexpr std::string_view LiningNums{"lining-nums"}; +static_assert(hasLiningNums); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasLtr = (CSSKeywordSet && requires() { T::Ltr; }); -} // namespace detail -namespace detail { +constexpr std::string_view Ltr{"ltr"}; +static_assert(hasLtr); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasMaxContent = (CSSKeywordSet && requires() { T::MaxContent; }); -} // namespace detail -namespace detail { +constexpr std::string_view MaxContent{"max-content"}; +static_assert(hasMaxContent); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasMedium = (CSSKeywordSet && requires() { T::Medium; }); -} // namespace detail -namespace detail { +constexpr std::string_view Medium{"medium"}; +static_assert(hasMedium); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasMinContent = (CSSKeywordSet && requires() { T::MinContent; }); -} // namespace detail -namespace detail { +constexpr std::string_view MinContent{"min-content"}; +static_assert(hasMinContent); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasNoCommonLigatures = + (CSSKeywordSet && requires() { T::NoCommonLigatures; }); +constexpr std::string_view NoCommonLigatures{"no-common-ligatures"}; +static_assert(hasNoCommonLigatures); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasNoContextual = (CSSKeywordSet && requires() { T::NoContextual; }); +constexpr std::string_view NoContextual{"no-contextual"}; +static_assert(hasNoContextual); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasNoDiscretionaryLigatures = + (CSSKeywordSet && requires() { T::NoDiscretionaryLigatures; }); +constexpr std::string_view NoDiscretionaryLigatures{ + "no-discretionary-ligatures"}; +static_assert(hasNoDiscretionaryLigatures); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasNoHistoricalLigatures = + (CSSKeywordSet && requires() { T::NoHistoricalLigatures; }); +constexpr std::string_view NoHistoricalLigatures{"no-historical-ligatures"}; +static_assert(hasNoHistoricalLigatures); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasNone = (CSSKeywordSet && requires() { T::None; }); -} // namespace detail -namespace detail { +constexpr std::string_view None{"none"}; +static_assert(hasNone); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasNormal = (CSSKeywordSet && requires() { T::Normal; }); -} // namespace detail -namespace detail { +constexpr std::string_view Normal{"normal"}; +static_assert(hasNormal); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasNoWrap = (CSSKeywordSet && requires() { T::NoWrap; }); -} // namespace detail -namespace detail { +constexpr std::string_view NoWrap{"nowrap"}; +static_assert(hasNoWrap); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasOldstyleNums = (CSSKeywordSet && requires() { T::OldstyleNums; }); +constexpr std::string_view OldstyleNums{"oldstyle-nums"}; +static_assert(hasOldstyleNums); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasOutset = (CSSKeywordSet && requires() { T::Outset; }); -} // namespace detail -namespace detail { +constexpr std::string_view Outset{"outset"}; +static_assert(hasOutset); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasProportionalNums = + (CSSKeywordSet && requires() { T::ProportionalNums; }); +constexpr std::string_view ProportionalNums{"proportional-nums"}; +static_assert(hasProportionalNums); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasRelative = (CSSKeywordSet && requires() { T::Relative; }); -} // namespace detail -namespace detail { +constexpr std::string_view Relative{"relative"}; +static_assert(hasRelative); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasRidge = (CSSKeywordSet && requires() { T::Ridge; }); -} // namespace detail -namespace detail { +constexpr std::string_view Ridge{"ridge"}; +static_assert(hasRidge); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasRight = (CSSKeywordSet && requires() { T::Right; }); +constexpr std::string_view Right{"right"}; +static_assert(hasRight); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasRow = (CSSKeywordSet && requires() { T::Row; }); -} // namespace detail -namespace detail { +constexpr std::string_view Row{"row"}; +static_assert(hasRow); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasRowReverse = (CSSKeywordSet && requires() { T::RowReverse; }); -} // namespace detail -namespace detail { +constexpr std::string_view RowReverse{"row-reverse"}; +static_assert(hasRowReverse); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasRtl = (CSSKeywordSet && requires() { T::Rtl; }); -} // namespace detail -namespace detail { +constexpr std::string_view Rtl{"rtl"}; +static_assert(hasRtl); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasScroll = (CSSKeywordSet && requires() { T::Scroll; }); -} // namespace detail -namespace detail { +constexpr std::string_view Scroll{"scroll"}; +static_assert(hasScroll); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasSmallCaps = (CSSKeywordSet && requires() { T::SmallCaps; }); +constexpr std::string_view SmallCaps{"small-caps"}; +static_assert(hasSmallCaps); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasSolid = (CSSKeywordSet && requires() { T::Solid; }); -} // namespace detail -namespace detail { +constexpr std::string_view Solid{"solid"}; +static_assert(hasSolid); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasSpaceAround = (CSSKeywordSet && requires() { T::SpaceAround; }); -} // namespace detail -namespace detail { +constexpr std::string_view SpaceAround{"space-around"}; +static_assert(hasSpaceAround); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasSpaceBetween = (CSSKeywordSet && requires() { T::SpaceBetween; }); -} // namespace detail -namespace detail { +constexpr std::string_view SpaceBetween{"space-between"}; +static_assert(hasSpaceBetween); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasSpaceEvenly = (CSSKeywordSet && requires() { T::SpaceEvenly; }); -} // namespace detail -namespace detail { +constexpr std::string_view SpaceEvenly{"space-evenly"}; +static_assert(hasSpaceEvenly); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasStart = (CSSKeywordSet && requires() { T::Start; }); -} // namespace detail -namespace detail { +constexpr std::string_view Start{"start"}; +static_assert(hasStart); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasStatic = (CSSKeywordSet && requires() { T::Static; }); -} // namespace detail -namespace detail { +constexpr std::string_view Static{"static"}; +static_assert(hasStatic); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasSticky = (CSSKeywordSet && requires() { T::Sticky; }); -} // namespace detail -namespace detail { +constexpr std::string_view Sticky{"sticky"}; +static_assert(hasSticky); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasStretch = (CSSKeywordSet && requires() { T::Stretch; }); -} // namespace detail -namespace detail { +constexpr std::string_view Stretch{"stretch"}; +static_assert(hasStretch); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticEight = + (CSSKeywordSet && requires() { T::StylisticEight; }); +constexpr std::string_view StylisticEight{"stylistic-eight"}; +static_assert(hasStylisticEight); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticEighteen = + (CSSKeywordSet && requires() { T::StylisticEighteen; }); +constexpr std::string_view StylisticEighteen{"stylistic-eighteen"}; +static_assert(hasStylisticEighteen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticEleven = + (CSSKeywordSet && requires() { T::StylisticEleven; }); +constexpr std::string_view StylisticEleven{"stylistic-eleven"}; +static_assert(hasStylisticEleven); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticFifteen = + (CSSKeywordSet && requires() { T::StylisticFifteen; }); +constexpr std::string_view StylisticFifteen{"stylistic-fifteen"}; +static_assert(hasStylisticFifteen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticFive = + (CSSKeywordSet && requires() { T::StylisticFive; }); +constexpr std::string_view StylisticFive{"stylistic-five"}; +static_assert(hasStylisticFive); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticFour = + (CSSKeywordSet && requires() { T::StylisticFour; }); +constexpr std::string_view StylisticFour{"stylistic-four"}; +static_assert(hasStylisticFour); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticFourteen = + (CSSKeywordSet && requires() { T::StylisticFourteen; }); +constexpr std::string_view StylisticFourteen{"stylistic-fourteen"}; +static_assert(hasStylisticFourteen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticNine = + (CSSKeywordSet && requires() { T::StylisticNine; }); +constexpr std::string_view StylisticNine{"stylistic-nine"}; +static_assert(hasStylisticNine); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticNineteen = + (CSSKeywordSet && requires() { T::StylisticNineteen; }); +constexpr std::string_view StylisticNineteen{"stylistic-nineteen"}; +static_assert(hasStylisticNineteen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticOne = (CSSKeywordSet && requires() { T::StylisticOne; }); +constexpr std::string_view StylisticOne{"stylistic-one"}; +static_assert(hasStylisticOne); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticSeven = + (CSSKeywordSet && requires() { T::StylisticSeven; }); +constexpr std::string_view StylisticSeven{"stylistic-seven"}; +static_assert(hasStylisticSeven); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticSeventeen = + (CSSKeywordSet && requires() { T::StylisticSeventeen; }); +constexpr std::string_view StylisticSeventeen{"stylistic-seventeen"}; +static_assert(hasStylisticSeventeen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticSix = (CSSKeywordSet && requires() { T::StylisticSix; }); +constexpr std::string_view StylisticSix{"stylistic-six"}; +static_assert(hasStylisticSix); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticSixteen = + (CSSKeywordSet && requires() { T::StylisticSixteen; }); +constexpr std::string_view StylisticSixteen{"stylistic-sixteen"}; +static_assert(hasStylisticSixteen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticTen = (CSSKeywordSet && requires() { T::StylisticTen; }); +constexpr std::string_view StylisticTen{"stylistic-ten"}; +static_assert(hasStylisticTen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticThirteen = + (CSSKeywordSet && requires() { T::StylisticThirteen; }); +constexpr std::string_view StylisticThirteen{"stylistic-thirteen"}; +static_assert(hasStylisticThirteen); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticThree = + (CSSKeywordSet && requires() { T::StylisticThree; }); +constexpr std::string_view StylisticThree{"stylistic-three"}; +static_assert(hasStylisticThree); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticTwelve = + (CSSKeywordSet && requires() { T::StylisticTwelve; }); +constexpr std::string_view StylisticTwelve{"stylistic-twelve"}; +static_assert(hasStylisticTwelve); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticTwenty = + (CSSKeywordSet && requires() { T::StylisticTwenty; }); +constexpr std::string_view StylisticTwenty{"stylistic-twenty"}; +static_assert(hasStylisticTwenty); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasStylisticTwo = (CSSKeywordSet && requires() { T::StylisticTwo; }); +constexpr std::string_view StylisticTwo{"stylistic-two"}; +static_assert(hasStylisticTwo); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasTabularNums = (CSSKeywordSet && requires() { T::TabularNums; }); +constexpr std::string_view TabularNums{"tabular-nums"}; +static_assert(hasTabularNums); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasThick = (CSSKeywordSet && requires() { T::Thick; }); -} // namespace detail -namespace detail { +constexpr std::string_view Thick{"thick"}; +static_assert(hasThick); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasThin = (CSSKeywordSet && requires() { T::Thin; }); -} // namespace detail -namespace detail { +constexpr std::string_view Thin{"thin"}; +static_assert(hasThin); +} // namespace detail::css::keywords +namespace detail::css::keywords { +template +concept hasTop = (CSSKeywordSet && requires() { T::Top; }); +constexpr std::string_view Top{"top"}; +static_assert(hasTop); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasUnset = (CSSKeywordSet && requires() { T::Unset; }); -} // namespace detail -namespace detail { +constexpr std::string_view Unset{"unset"}; +static_assert(hasUnset); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasVisible = (CSSKeywordSet && requires() { T::Visible; }); -} // namespace detail -namespace detail { +constexpr std::string_view Visible{"visible"}; +static_assert(hasVisible); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasWrap = (CSSKeywordSet && requires() { T::Wrap; }); -} // namespace detail -namespace detail { +constexpr std::string_view Wrap{"wrap"}; +static_assert(hasWrap); +} // namespace detail::css::keywords +namespace detail::css::keywords { template concept hasWrapReverse = (CSSKeywordSet && requires() { T::WrapReverse; }); -} // namespace detail +constexpr std::string_view WrapReverse{"wrap-reverse"}; +static_assert(hasWrapReverse); +} // namespace detail::css::keywords template constexpr std::optional parseCSSKeyword(std::string_view ident) { switch (fnv1aLowercase(ident)) { - case fnv1a("absolute"): - if constexpr (detail::hasAbsolute) { + case fnv1a(detail::css::keywords::Absolute): + if constexpr (detail::css::keywords::hasAbsolute) { return KeywordT::Absolute; } break; - case fnv1a("auto"): - if constexpr (detail::hasAuto) { + case fnv1a(detail::css::keywords::Auto): + if constexpr (detail::css::keywords::hasAuto) { return KeywordT::Auto; } break; - case fnv1a("baseline"): - if constexpr (detail::hasBaseline) { + case fnv1a(detail::css::keywords::Baseline): + if constexpr (detail::css::keywords::hasBaseline) { return KeywordT::Baseline; } break; - case fnv1a("block"): - if constexpr (detail::hasBlock) { + case fnv1a(detail::css::keywords::Block): + if constexpr (detail::css::keywords::hasBlock) { return KeywordT::Block; } break; - case fnv1a("center"): - if constexpr (detail::hasCenter) { + case fnv1a(detail::css::keywords::Bottom): + if constexpr (detail::css::keywords::hasBottom) { + return KeywordT::Bottom; + } + break; + case fnv1a(detail::css::keywords::Center): + if constexpr (detail::css::keywords::hasCenter) { return KeywordT::Center; } break; - case fnv1a("clip"): - if constexpr (detail::hasClip) { + case fnv1a(detail::css::keywords::Clip): + if constexpr (detail::css::keywords::hasClip) { return KeywordT::Clip; } break; - case fnv1a("column"): - if constexpr (detail::hasColumn) { + case fnv1a(detail::css::keywords::Column): + if constexpr (detail::css::keywords::hasColumn) { return KeywordT::Column; } break; - case fnv1a("column-reverse"): - if constexpr (detail::hasColumnReverse) { + case fnv1a(detail::css::keywords::ColumnReverse): + if constexpr (detail::css::keywords::hasColumnReverse) { return KeywordT::ColumnReverse; } break; - case fnv1a("content"): - if constexpr (detail::hasContent) { + case fnv1a(detail::css::keywords::CommonLigatures): + if constexpr (detail::css::keywords::hasCommonLigatures) { + return KeywordT::CommonLigatures; + } + break; + case fnv1a(detail::css::keywords::Content): + if constexpr (detail::css::keywords::hasContent) { return KeywordT::Content; } break; - case fnv1a("contents"): - if constexpr (detail::hasContents) { + case fnv1a(detail::css::keywords::Contents): + if constexpr (detail::css::keywords::hasContents) { return KeywordT::Contents; } break; - case fnv1a("dashed"): - if constexpr (detail::hasDashed) { + case fnv1a(detail::css::keywords::Contextual): + if constexpr (detail::css::keywords::hasContextual) { + return KeywordT::Contextual; + } + break; + case fnv1a(detail::css::keywords::Dashed): + if constexpr (detail::css::keywords::hasDashed) { return KeywordT::Dashed; } break; - case fnv1a("dotted"): - if constexpr (detail::hasDotted) { + case fnv1a(detail::css::keywords::DiscretionaryLigatures): + if constexpr (detail::css::keywords::hasDiscretionaryLigatures< + KeywordT>) { + return KeywordT::DiscretionaryLigatures; + } + break; + case fnv1a(detail::css::keywords::Dotted): + if constexpr (detail::css::keywords::hasDotted) { return KeywordT::Dotted; } break; - case fnv1a("double"): - if constexpr (detail::hasDouble) { + case fnv1a(detail::css::keywords::Double): + if constexpr (detail::css::keywords::hasDouble) { return KeywordT::Double; } break; - case fnv1a("end"): - if constexpr (detail::hasEnd) { + case fnv1a(detail::css::keywords::End): + if constexpr (detail::css::keywords::hasEnd) { return KeywordT::End; } break; - case fnv1a("fixed"): - if constexpr (detail::hasFixed) { + case fnv1a(detail::css::keywords::Fixed): + if constexpr (detail::css::keywords::hasFixed) { return KeywordT::Fixed; } - case fnv1a("flex"): - if constexpr (detail::hasFlex) { + break; + case fnv1a(detail::css::keywords::Flex): + if constexpr (detail::css::keywords::hasFlex) { return KeywordT::Flex; } break; - case fnv1a("flex-end"): - if constexpr (detail::hasFlexEnd) { + case fnv1a(detail::css::keywords::FlexEnd): + if constexpr (detail::css::keywords::hasFlexEnd) { return KeywordT::FlexEnd; } break; - case fnv1a("flex-start"): - if constexpr (detail::hasFlexStart) { + case fnv1a(detail::css::keywords::FlexStart): + if constexpr (detail::css::keywords::hasFlexStart) { return KeywordT::FlexStart; } break; - case fnv1a("grid"): - if constexpr (detail::hasGrid) { + case fnv1a(detail::css::keywords::Grid): + if constexpr (detail::css::keywords::hasGrid) { return KeywordT::Grid; } break; - case fnv1a("groove"): - if constexpr (detail::hasGroove) { + case fnv1a(detail::css::keywords::Groove): + if constexpr (detail::css::keywords::hasGroove) { return KeywordT::Groove; } break; - case fnv1a("hidden"): - if constexpr (detail::hasHidden) { + case fnv1a(detail::css::keywords::Hidden): + if constexpr (detail::css::keywords::hasHidden) { return KeywordT::Hidden; } break; - case fnv1a("inherit"): - if constexpr (detail::hasInherit) { + case fnv1a(detail::css::keywords::HistoricalLigatures): + if constexpr (detail::css::keywords::hasHistoricalLigatures) { + return KeywordT::HistoricalLigatures; + } + break; + case fnv1a(detail::css::keywords::Inherit): + if constexpr (detail::css::keywords::hasInherit) { return KeywordT::Inherit; } break; - case fnv1a("inline"): - if constexpr (detail::hasInline) { + case fnv1a(detail::css::keywords::Initial): + if constexpr (detail::css::keywords::hasInitial) { + return KeywordT::Initial; + } + break; + case fnv1a(detail::css::keywords::Inline): + if constexpr (detail::css::keywords::hasInline) { return KeywordT::Inline; } break; - case fnv1a("inline-block"): - if constexpr (detail::hasInlineBlock) { + case fnv1a(detail::css::keywords::InlineBlock): + if constexpr (detail::css::keywords::hasInlineBlock) { return KeywordT::InlineBlock; } break; - case fnv1a("inline-flex"): - if constexpr (detail::hasInlineFlex) { + case fnv1a(detail::css::keywords::InlineFlex): + if constexpr (detail::css::keywords::hasInlineFlex) { return KeywordT::InlineFlex; } break; - case fnv1a("inline-grid"): - if constexpr (detail::hasInlineGrid) { + case fnv1a(detail::css::keywords::InlineGrid): + if constexpr (detail::css::keywords::hasInlineGrid) { return KeywordT::InlineGrid; } break; - case fnv1a("ltr"): - if constexpr (detail::hasLtr) { + case fnv1a(detail::css::keywords::Inset): + if constexpr (detail::css::keywords::hasInset) { + return KeywordT::Inset; + } + break; + case fnv1a(detail::css::keywords::Left): + if constexpr (detail::css::keywords::hasLeft) { + return KeywordT::Left; + } + break; + case fnv1a(detail::css::keywords::LiningNums): + if constexpr (detail::css::keywords::hasLiningNums) { + return KeywordT::LiningNums; + } + break; + case fnv1a(detail::css::keywords::Ltr): + if constexpr (detail::css::keywords::hasLtr) { return KeywordT::Ltr; } break; - case fnv1a("max-content"): - if constexpr (detail::hasMaxContent) { + case fnv1a(detail::css::keywords::MaxContent): + if constexpr (detail::css::keywords::hasMaxContent) { return KeywordT::MaxContent; } break; - case fnv1a("medium"): - if constexpr (detail::hasMedium) { + case fnv1a(detail::css::keywords::Medium): + if constexpr (detail::css::keywords::hasMedium) { return KeywordT::Medium; } break; - case fnv1a("min-content"): - if constexpr (detail::hasMinContent) { + case fnv1a(detail::css::keywords::MinContent): + if constexpr (detail::css::keywords::hasMinContent) { return KeywordT::MinContent; } break; - case fnv1a("none"): - if constexpr (detail::hasNone) { + case fnv1a(detail::css::keywords::NoCommonLigatures): + if constexpr (detail::css::keywords::hasNoCommonLigatures) { + return KeywordT::NoCommonLigatures; + } + break; + case fnv1a(detail::css::keywords::NoContextual): + if constexpr (detail::css::keywords::hasNoContextual) { + return KeywordT::NoContextual; + } + break; + case fnv1a(detail::css::keywords::NoDiscretionaryLigatures): + if constexpr (detail::css::keywords::hasNoDiscretionaryLigatures< + KeywordT>) { + return KeywordT::NoDiscretionaryLigatures; + } + break; + case fnv1a(detail::css::keywords::NoHistoricalLigatures): + if constexpr (detail::css::keywords::hasNoHistoricalLigatures) { + return KeywordT::NoHistoricalLigatures; + } + break; + case fnv1a(detail::css::keywords::None): + if constexpr (detail::css::keywords::hasNone) { return KeywordT::None; } break; - case fnv1a("normal"): - if constexpr (detail::hasNormal) { + case fnv1a(detail::css::keywords::Normal): + if constexpr (detail::css::keywords::hasNormal) { return KeywordT::Normal; } break; - case fnv1a("nowrap"): - if constexpr (detail::hasNoWrap) { + case fnv1a(detail::css::keywords::NoWrap): + if constexpr (detail::css::keywords::hasNoWrap) { return KeywordT::NoWrap; } break; - case fnv1a("outset"): - if constexpr (detail::hasOutset) { + case fnv1a(detail::css::keywords::OldstyleNums): + if constexpr (detail::css::keywords::hasOldstyleNums) { + return KeywordT::OldstyleNums; + } + break; + case fnv1a(detail::css::keywords::Outset): + if constexpr (detail::css::keywords::hasOutset) { return KeywordT::Outset; } break; - case fnv1a("relative"): - if constexpr (detail::hasRelative) { + case fnv1a(detail::css::keywords::ProportionalNums): + if constexpr (detail::css::keywords::hasProportionalNums) { + return KeywordT::ProportionalNums; + } + break; + case fnv1a(detail::css::keywords::Relative): + if constexpr (detail::css::keywords::hasRelative) { return KeywordT::Relative; } break; - case fnv1a("ridge"): - if constexpr (detail::hasRidge) { + case fnv1a(detail::css::keywords::Ridge): + if constexpr (detail::css::keywords::hasRidge) { return KeywordT::Ridge; } break; - case fnv1a("row"): - if constexpr (detail::hasRow) { + case fnv1a(detail::css::keywords::Right): + if constexpr (detail::css::keywords::hasRight) { + return KeywordT::Right; + } + break; + case fnv1a(detail::css::keywords::Row): + if constexpr (detail::css::keywords::hasRow) { return KeywordT::Row; } break; - case fnv1a("row-reverse"): - if constexpr (detail::hasRowReverse) { + case fnv1a(detail::css::keywords::RowReverse): + if constexpr (detail::css::keywords::hasRowReverse) { return KeywordT::RowReverse; } break; - case fnv1a("rtl"): - if constexpr (detail::hasRtl) { + case fnv1a(detail::css::keywords::Rtl): + if constexpr (detail::css::keywords::hasRtl) { return KeywordT::Rtl; } break; - case fnv1a("space-between"): - if constexpr (detail::hasSpaceBetween) { - return KeywordT::SpaceBetween; + case fnv1a(detail::css::keywords::Scroll): + if constexpr (detail::css::keywords::hasScroll) { + return KeywordT::Scroll; } break; - case fnv1a("space-around"): - if constexpr (detail::hasSpaceAround) { - return KeywordT::SpaceAround; + case fnv1a(detail::css::keywords::SmallCaps): + if constexpr (detail::css::keywords::hasSmallCaps) { + return KeywordT::SmallCaps; } break; - case fnv1a("space-evenly"): - if constexpr (detail::hasSpaceEvenly) { - return KeywordT::SpaceEvenly; + case fnv1a(detail::css::keywords::Solid): + if constexpr (detail::css::keywords::hasSolid) { + return KeywordT::Solid; } break; - case fnv1a("scroll"): - if constexpr (detail::hasScroll) { - return KeywordT::Scroll; + case fnv1a(detail::css::keywords::SpaceAround): + if constexpr (detail::css::keywords::hasSpaceAround) { + return KeywordT::SpaceAround; } break; - case fnv1a("solid"): - if constexpr (detail::hasSolid) { - return KeywordT::Solid; + case fnv1a(detail::css::keywords::SpaceBetween): + if constexpr (detail::css::keywords::hasSpaceBetween) { + return KeywordT::SpaceBetween; + } + break; + case fnv1a(detail::css::keywords::SpaceEvenly): + if constexpr (detail::css::keywords::hasSpaceEvenly) { + return KeywordT::SpaceEvenly; } break; - case fnv1a("start"): - if constexpr (detail::hasStart) { + case fnv1a(detail::css::keywords::Start): + if constexpr (detail::css::keywords::hasStart) { return KeywordT::Start; } - case fnv1a("static"): - if constexpr (detail::hasStatic) { + break; + case fnv1a(detail::css::keywords::Static): + if constexpr (detail::css::keywords::hasStatic) { return KeywordT::Static; } break; - case fnv1a("sticky"): - if constexpr (detail::hasSticky) { + case fnv1a(detail::css::keywords::Sticky): + if constexpr (detail::css::keywords::hasSticky) { return KeywordT::Sticky; } break; - case fnv1a("stretch"): - if constexpr (detail::hasStretch) { + case fnv1a(detail::css::keywords::Stretch): + if constexpr (detail::css::keywords::hasStretch) { return KeywordT::Stretch; } break; - case fnv1a("thick"): - if constexpr (detail::hasThick) { + case fnv1a(detail::css::keywords::StylisticEight): + if constexpr (detail::css::keywords::hasStylisticEight) { + return KeywordT::StylisticEight; + } + break; + case fnv1a(detail::css::keywords::StylisticEighteen): + if constexpr (detail::css::keywords::hasStylisticEighteen) { + return KeywordT::StylisticEighteen; + } + break; + case fnv1a(detail::css::keywords::StylisticEleven): + if constexpr (detail::css::keywords::hasStylisticEleven) { + return KeywordT::StylisticEleven; + } + break; + case fnv1a(detail::css::keywords::StylisticFifteen): + if constexpr (detail::css::keywords::hasStylisticFifteen) { + return KeywordT::StylisticFifteen; + } + break; + case fnv1a(detail::css::keywords::StylisticFive): + if constexpr (detail::css::keywords::hasStylisticFive) { + return KeywordT::StylisticFive; + } + break; + case fnv1a(detail::css::keywords::StylisticFour): + if constexpr (detail::css::keywords::hasStylisticFour) { + return KeywordT::StylisticFour; + } + break; + case fnv1a(detail::css::keywords::StylisticFourteen): + if constexpr (detail::css::keywords::hasStylisticFourteen) { + return KeywordT::StylisticFourteen; + } + break; + case fnv1a(detail::css::keywords::StylisticNine): + if constexpr (detail::css::keywords::hasStylisticNine) { + return KeywordT::StylisticNine; + } + break; + case fnv1a(detail::css::keywords::StylisticNineteen): + if constexpr (detail::css::keywords::hasStylisticNineteen) { + return KeywordT::StylisticNineteen; + } + break; + case fnv1a(detail::css::keywords::StylisticOne): + if constexpr (detail::css::keywords::hasStylisticOne) { + return KeywordT::StylisticOne; + } + break; + case fnv1a(detail::css::keywords::StylisticSeven): + if constexpr (detail::css::keywords::hasStylisticSeven) { + return KeywordT::StylisticSeven; + } + break; + case fnv1a(detail::css::keywords::StylisticSeventeen): + if constexpr (detail::css::keywords::hasStylisticSeventeen) { + return KeywordT::StylisticSeventeen; + } + break; + case fnv1a(detail::css::keywords::StylisticSix): + if constexpr (detail::css::keywords::hasStylisticSix) { + return KeywordT::StylisticSix; + } + break; + case fnv1a(detail::css::keywords::StylisticSixteen): + if constexpr (detail::css::keywords::hasStylisticSixteen) { + return KeywordT::StylisticSixteen; + } + break; + case fnv1a(detail::css::keywords::StylisticTen): + if constexpr (detail::css::keywords::hasStylisticTen) { + return KeywordT::StylisticTen; + } + break; + case fnv1a(detail::css::keywords::StylisticThirteen): + if constexpr (detail::css::keywords::hasStylisticThirteen) { + return KeywordT::StylisticThirteen; + } + break; + case fnv1a(detail::css::keywords::StylisticThree): + if constexpr (detail::css::keywords::hasStylisticThree) { + return KeywordT::StylisticThree; + } + break; + case fnv1a(detail::css::keywords::StylisticTwelve): + if constexpr (detail::css::keywords::hasStylisticTwelve) { + return KeywordT::StylisticTwelve; + } + break; + case fnv1a(detail::css::keywords::StylisticTwenty): + if constexpr (detail::css::keywords::hasStylisticTwenty) { + return KeywordT::StylisticTwenty; + } + break; + case fnv1a(detail::css::keywords::StylisticTwo): + if constexpr (detail::css::keywords::hasStylisticTwo) { + return KeywordT::StylisticTwo; + } + break; + case fnv1a(detail::css::keywords::TabularNums): + if constexpr (detail::css::keywords::hasTabularNums) { + return KeywordT::TabularNums; + } + break; + case fnv1a(detail::css::keywords::Thick): + if constexpr (detail::css::keywords::hasThick) { return KeywordT::Thick; } break; - case fnv1a("thin"): - if constexpr (detail::hasThin) { + case fnv1a(detail::css::keywords::Thin): + if constexpr (detail::css::keywords::hasThin) { return KeywordT::Thin; } break; - case fnv1a("unset"): - if constexpr (detail::hasUnset) { + case fnv1a(detail::css::keywords::Top): + if constexpr (detail::css::keywords::hasTop) { + return KeywordT::Top; + } + break; + case fnv1a(detail::css::keywords::Unset): + if constexpr (detail::css::keywords::hasUnset) { return KeywordT::Unset; } break; - case fnv1a("visible"): - if constexpr (detail::hasVisible) { + case fnv1a(detail::css::keywords::Visible): + if constexpr (detail::css::keywords::hasVisible) { return KeywordT::Visible; } break; - case fnv1a("wrap"): - if constexpr (detail::hasWrap) { + case fnv1a(detail::css::keywords::Wrap): + if constexpr (detail::css::keywords::hasWrap) { return KeywordT::Wrap; } break; - case fnv1a("wrap-reverse"): - if constexpr (detail::hasWrapReverse) { + case fnv1a(detail::css::keywords::WrapReverse): + if constexpr (detail::css::keywords::hasWrapReverse) { return KeywordT::WrapReverse; } break; - default: - break; } return std::nullopt; } +template +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + if (token.type() == CSSTokenType::Ident) { + return parseCSSKeyword(token.stringValue()); + } + return {}; + } +}; +static_assert(CSSDataType); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSLength.h}: +namespace facebook::react { +struct CSSLength { + float value{}; + CSSLengthUnit unit{CSSLengthUnit::Px}; + constexpr bool operator==(const CSSLength& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + switch (token.type()) { + case CSSTokenType::Dimension: + if (auto unit = parseCSSLengthUnit(token.unit())) { + return CSSLength{token.numericValue(), *unit}; + } + break; + case CSSTokenType::Number: + if (token.numericValue() == 0) { + return CSSLength{token.numericValue(), CSSLengthUnit::Px}; + } + break; + default: + break; + } + return {}; + } +}; +static_assert(CSSDataType); } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSLengthPercentage.h}: +namespace facebook::react { +using CSSLengthPercentage = CSSCompoundDataType; +} + /// @src {packages/react-native/ReactCommon/react/renderer/css/CSSLengthUnit.h}: namespace facebook::react { enum class CSSLengthUnit : uint8_t { @@ -27239,961 +31195,526 @@ constexpr std::optional parseCSSLengthUnit( } } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSProperties.h}: -namespace facebook::react { -enum class CSSProp { - AlignContent, - AlignItems, - AlignSelf, - AspectRatio, - BorderBlockEndStyle, - BorderBlockEndWidth, - BorderBlockStartStyle, - BorderBlockStartWidth, - BorderBlockStyle, - BorderBlockWidth, - BorderBottomLeftRadius, - BorderBottomRightRadius, - BorderBottomStyle, - BorderBottomWidth, - BorderEndEndRadius, - BorderEndStartRadius, - BorderEndWidth, - BorderHorizontalWidth, - BorderInlineEndStyle, - BorderInlineEndWidth, - BorderInlineStartStyle, - BorderInlineStartWidth, - BorderInlineStyle, - BorderInlineWidth, - BorderLeftStyle, - BorderLeftWidth, - BorderRadius, - BorderRightStyle, - BorderRightWidth, - BorderStartEndRadius, - BorderStartStartRadius, - BorderStartWidth, - BorderStyle, - BorderTopLeftRadius, - BorderTopRightRadius, - BorderTopStyle, - BorderTopWidth, - BorderVerticalWidth, - BorderWidth, - Bottom, - ColumnGap, - Direction, - Display, - End, - Flex, - FlexBasis, - FlexDirection, - FlexGrow, - FlexShrink, - FlexWrap, - Gap, - Height, - Inset, - InsetBlock, - InsetBlockEnd, - InsetBlockStart, - InsetInline, - InsetInlineEnd, - InsetInlineStart, - JustifyContent, - Left, - Margin, - MarginBlock, - MarginBlockEnd, - MarginBlockStart, - MarginBottom, - MarginEnd, - MarginHorizontal, - MarginInline, - MarginInlineEnd, - MarginInlineStart, - MarginLeft, - MarginRight, - MarginStart, - MarginTop, - MarginVertical, - MaxHeight, - MaxWidth, - MinHeight, - MinWidth, - Opacity, - Overflow, - Padding, - PaddingBlock, - PaddingBlockEnd, - PaddingBlockStart, - PaddingBottom, - PaddingEnd, - PaddingHorizontal, - PaddingInline, - PaddingInlineEnd, - PaddingInlineStart, - PaddingLeft, - PaddingRight, - PaddingStart, - PaddingTop, - PaddingVertical, - Position, - Right, - RowGap, - Start, - Top, - Width, -}; -constexpr auto kCSSPropCount = to_underlying(CSSProp::Width) + 1; -template -struct CSSPropDefinition {}; -template -using CSSDeclaredValue = typename CSSPropDefinition

::DeclaredValue; -template -using CSSSpecifiedValue = typename CSSPropDefinition

::SpecifiedValue; -template -using CSSComputedValue = typename CSSPropDefinition

::ComputedValue; -enum class CSSFlavor { - W3C, - ReactNative, -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "alignContent"; - enum class Keyword : std::underlying_type_t { - Center = to_underlying(CSSKeyword::Center), - FlexEnd = to_underlying(CSSKeyword::FlexEnd), - FlexStart = to_underlying(CSSKeyword::FlexStart), - SpaceAround = to_underlying(CSSKeyword::SpaceAround), - SpaceBetween = to_underlying(CSSKeyword::SpaceBetween), - SpaceEvenly = to_underlying(CSSKeyword::SpaceEvenly), - Stretch = to_underlying(CSSKeyword::Stretch), - Start = to_underlying(CSSKeyword::Start), - End = to_underlying(CSSKeyword::End), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C - ? DeclaredValue::keyword(Keyword::Stretch) - : DeclaredValue::keyword(Keyword::FlexStart); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "alignItems"; - enum class Keyword : std::underlying_type_t { - Baseline = to_underlying(CSSKeyword::Baseline), - Center = to_underlying(CSSKeyword::Center), - FlexEnd = to_underlying(CSSKeyword::FlexEnd), - FlexStart = to_underlying(CSSKeyword::FlexStart), - Stretch = to_underlying(CSSKeyword::Stretch), - Start = to_underlying(CSSKeyword::Start), - End = to_underlying(CSSKeyword::End), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Stretch); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "alignSelf"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - Baseline = to_underlying(CSSKeyword::Baseline), - Center = to_underlying(CSSKeyword::Center), - FlexEnd = to_underlying(CSSKeyword::FlexEnd), - FlexStart = to_underlying(CSSKeyword::FlexStart), - Stretch = to_underlying(CSSKeyword::Stretch), - Start = to_underlying(CSSKeyword::Start), - End = to_underlying(CSSKeyword::End), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Auto); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "aspectRatio"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Auto); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "borderRadius"; - using DeclaredValue = - CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::length(0.0f, CSSLengthUnit::Px); - } -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderTopLeftRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderTopRightRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBottomLeftRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBottomRightRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderStartStartRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderStartEndRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderEndStartRadius"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderEndEndRadius"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "borderStyle"; - enum class Keyword : std::underlying_type_t { - None = to_underlying(CSSKeyword::None), - Hidden = to_underlying(CSSKeyword::Hidden), - Dotted = to_underlying(CSSKeyword::Dotted), - Dashed = to_underlying(CSSKeyword::Dashed), - Solid = to_underlying(CSSKeyword::Solid), - Double = to_underlying(CSSKeyword::Double), - Groove = to_underlying(CSSKeyword::Groove), - Ridge = to_underlying(CSSKeyword::Ridge), - Inset = to_underlying(CSSKeyword::Inset), - Outset = to_underlying(CSSKeyword::Outset), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::None) - : DeclaredValue::keyword(Keyword::Solid); +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSList.h}: +namespace facebook::react { +template +template +struct CSSList : public std::vector {}; +template +struct CSSList + : public std::vector> {}; +template +struct CSSDataTypeParser> { + static inline auto consume(CSSSyntaxParser& parser) + -> std::optional> { + CSSList result; + for (auto nextValue = parseNextCSSValue(parser); + !std::holds_alternative(nextValue); + nextValue = parseNextCSSValue(parser, Delim)) { + std::visit( + [&](auto&& v) { + if constexpr (!std::is_same_v< + std::remove_cvref_t, + std::monostate>) { + result.push_back(std::forward(v)); + } + }, + nextValue); + } + if (result.empty()) { + return {}; + } + return result; } }; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBlockEndStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBlockStartStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBlockStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBottomStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderInlineEndStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderInlineStartStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderInlineStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderLeftStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderRightStyle"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderTopStyle"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "borderWidth"; - enum class Keyword : std::underlying_type_t { - Thin = to_underlying(CSSKeyword::Thin), - Medium = to_underlying(CSSKeyword::Medium), - Thick = to_underlying(CSSKeyword::Thick), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C - ? DeclaredValue::keyword(Keyword::Medium) - : DeclaredValue::length(0.0f, CSSLengthUnit::Px); - } -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBlockEndWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBlockStartWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBlockWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderBottomWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderEndWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderHorizontalWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderInlineEndWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderInlineStartWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderInlineWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderLeftWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderRightWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderStartWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderTopWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "borderVerticalWidth"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "direction"; - enum class Keyword : std::underlying_type_t { - Ltr = to_underlying(CSSKeyword::Ltr), - Rtl = to_underlying(CSSKeyword::Rtl), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return true; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Ltr); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "display"; - enum class Keyword : std::underlying_type_t { - None = to_underlying(CSSKeyword::None), - Contents = to_underlying(CSSKeyword::Contents), - Inline = to_underlying(CSSKeyword::Inline), - Block = to_underlying(CSSKeyword::Block), - InlineBlock = to_underlying(CSSKeyword::InlineBlock), - Flex = to_underlying(CSSKeyword::Flex), - InlineFlex = to_underlying(CSSKeyword::InlineFlex), - Grid = to_underlying(CSSKeyword::Grid), - InlineGrid = to_underlying(CSSKeyword::InlineGrid), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::Inline) - : DeclaredValue::keyword(Keyword::Flex); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "flex"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - None = to_underlying(CSSKeyword::None), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::number(0.0f); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "flexBasis"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - Content = to_underlying(CSSKeyword::Content), - }; - using DeclaredValue = - CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Auto); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "flexDirection"; - enum class Keyword : std::underlying_type_t { - Row = to_underlying(CSSKeyword::Row), - RowReverse = to_underlying(CSSKeyword::RowReverse), - Column = to_underlying(CSSKeyword::Column), - ColumnReverse = to_underlying(CSSKeyword::ColumnReverse), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::Row) - : DeclaredValue::keyword(Keyword::Column); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "flexGrow"; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::number(0.0f); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "flexShrink"; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C ? DeclaredValue::number(1.0f) - : DeclaredValue::number(0.0f); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "flexWrap"; - enum class Keyword : std::underlying_type_t { - NoWrap = to_underlying(CSSKeyword::NoWrap), - Wrap = to_underlying(CSSKeyword::Wrap), - WrapReverse = to_underlying(CSSKeyword::WrapReverse), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::NoWrap); - } -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "gap"; - enum class Keyword : std::underlying_type_t { - Normal = to_underlying(CSSKeyword::Normal), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Normal); +template +using CSSCommaSeparatedList = CSSList; +template +using CSSWhitespaceSeparatedList = + CSSList; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSNamedColor.h}: +namespace facebook::react { +template +constexpr std::optional parseCSSNamedColor(std::string_view name) { + switch (fnv1aLowercase(name)) { + case fnv1a("aliceblue"): + return CSSColor{240, 248, 255, 255}; + case fnv1a("antiquewhite"): + return CSSColor{250, 235, 215, 255}; + case fnv1a("aqua"): + return CSSColor{0, 255, 255, 255}; + case fnv1a("aquamarine"): + return CSSColor{127, 255, 212, 255}; + case fnv1a("azure"): + return CSSColor{240, 255, 255, 255}; + case fnv1a("beige"): + return CSSColor{245, 245, 220, 255}; + case fnv1a("bisque"): + return CSSColor{255, 228, 196, 255}; + case fnv1a("black"): + return CSSColor{0, 0, 0, 255}; + case fnv1a("blanchedalmond"): + return CSSColor{255, 235, 205, 255}; + case fnv1a("blue"): + return CSSColor{0, 0, 255, 255}; + case fnv1a("blueviolet"): + return CSSColor{138, 43, 226, 255}; + case fnv1a("brown"): + return CSSColor{165, 42, 42, 255}; + case fnv1a("burlywood"): + return CSSColor{222, 184, 135, 255}; + case fnv1a("cadetblue"): + return CSSColor{95, 158, 160, 255}; + case fnv1a("chartreuse"): + return CSSColor{127, 255, 0, 255}; + case fnv1a("chocolate"): + return CSSColor{210, 105, 30, 255}; + case fnv1a("coral"): + return CSSColor{255, 127, 80, 255}; + case fnv1a("cornflowerblue"): + return CSSColor{100, 149, 237, 255}; + case fnv1a("cornsilk"): + return CSSColor{255, 248, 220, 255}; + case fnv1a("crimson"): + return CSSColor{220, 20, 60, 255}; + case fnv1a("cyan"): + return CSSColor{0, 255, 255, 255}; + case fnv1a("darkblue"): + return CSSColor{0, 0, 139, 255}; + case fnv1a("darkcyan"): + return CSSColor{0, 139, 139, 255}; + case fnv1a("darkgoldenrod"): + return CSSColor{184, 134, 11, 255}; + case fnv1a("darkgray"): + return CSSColor{169, 169, 169, 255}; + case fnv1a("darkgreen"): + return CSSColor{0, 100, 0, 255}; + case fnv1a("darkgrey"): + return CSSColor{169, 169, 169, 255}; + case fnv1a("darkkhaki"): + return CSSColor{189, 183, 107, 255}; + case fnv1a("darkmagenta"): + return CSSColor{139, 0, 139, 255}; + case fnv1a("darkolivegreen"): + return CSSColor{85, 107, 47, 255}; + case fnv1a("darkorange"): + return CSSColor{255, 140, 0, 255}; + case fnv1a("darkorchid"): + return CSSColor{153, 50, 204, 255}; + case fnv1a("darkred"): + return CSSColor{139, 0, 0, 255}; + case fnv1a("darksalmon"): + return CSSColor{233, 150, 122, 255}; + case fnv1a("darkseagreen"): + return CSSColor{143, 188, 143, 255}; + case fnv1a("darkslateblue"): + return CSSColor{72, 61, 139, 255}; + case fnv1a("darkslategray"): + return CSSColor{47, 79, 79, 255}; + case fnv1a("darkslategrey"): + return CSSColor{47, 79, 79, 255}; + case fnv1a("darkturquoise"): + return CSSColor{0, 206, 209, 255}; + case fnv1a("darkviolet"): + return CSSColor{148, 0, 211, 255}; + case fnv1a("deeppink"): + return CSSColor{255, 20, 147, 255}; + case fnv1a("deepskyblue"): + return CSSColor{0, 191, 255, 255}; + case fnv1a("dimgray"): + return CSSColor{105, 105, 105, 255}; + case fnv1a("dimgrey"): + return CSSColor{105, 105, 105, 255}; + case fnv1a("dodgerblue"): + return CSSColor{30, 144, 255, 255}; + case fnv1a("firebrick"): + return CSSColor{178, 34, 34, 255}; + case fnv1a("floralwhite"): + return CSSColor{255, 250, 240, 255}; + case fnv1a("forestgreen"): + return CSSColor{34, 139, 34, 255}; + case fnv1a("fuchsia"): + return CSSColor{255, 0, 255, 255}; + case fnv1a("gainsboro"): + return CSSColor{220, 220, 220, 255}; + case fnv1a("ghostwhite"): + return CSSColor{248, 248, 255, 255}; + case fnv1a("gold"): + return CSSColor{255, 215, 0, 255}; + case fnv1a("goldenrod"): + return CSSColor{218, 165, 32, 255}; + case fnv1a("gray"): + return CSSColor{128, 128, 128, 255}; + case fnv1a("green"): + return CSSColor{0, 128, 0, 255}; + case fnv1a("greenyellow"): + return CSSColor{173, 255, 47, 255}; + case fnv1a("grey"): + return CSSColor{128, 128, 128, 255}; + case fnv1a("honeydew"): + return CSSColor{240, 255, 240, 255}; + case fnv1a("hotpink"): + return CSSColor{255, 105, 180, 255}; + case fnv1a("indianred"): + return CSSColor{205, 92, 92, 255}; + case fnv1a("indigo"): + return CSSColor{75, 0, 130, 255}; + case fnv1a("ivory"): + return CSSColor{255, 255, 240, 255}; + case fnv1a("khaki"): + return CSSColor{240, 230, 140, 255}; + case fnv1a("lavender"): + return CSSColor{230, 230, 250, 255}; + case fnv1a("lavenderblush"): + return CSSColor{255, 240, 245, 255}; + case fnv1a("lawngreen"): + return CSSColor{124, 252, 0, 255}; + case fnv1a("lemonchiffon"): + return CSSColor{255, 250, 205, 255}; + case fnv1a("lightblue"): + return CSSColor{173, 216, 230, 255}; + case fnv1a("lightcoral"): + return CSSColor{240, 128, 128, 255}; + case fnv1a("lightcyan"): + return CSSColor{224, 255, 255, 255}; + case fnv1a("lightgoldenrodyellow"): + return CSSColor{250, 250, 210, 255}; + case fnv1a("lightgray"): + return CSSColor{211, 211, 211, 255}; + case fnv1a("lightgreen"): + return CSSColor{144, 238, 144, 255}; + case fnv1a("lightgrey"): + return CSSColor{211, 211, 211, 255}; + case fnv1a("lightpink"): + return CSSColor{255, 182, 193, 255}; + case fnv1a("lightsalmon"): + return CSSColor{255, 160, 122, 255}; + case fnv1a("lightseagreen"): + return CSSColor{32, 178, 170, 255}; + case fnv1a("lightskyblue"): + return CSSColor{135, 206, 250, 255}; + case fnv1a("lightslategray"): + return CSSColor{119, 136, 153, 255}; + case fnv1a("lightslategrey"): + return CSSColor{119, 136, 153, 255}; + case fnv1a("lightsteelblue"): + return CSSColor{176, 196, 222, 255}; + case fnv1a("lightyellow"): + return CSSColor{255, 255, 224, 255}; + case fnv1a("lime"): + return CSSColor{0, 255, 0, 255}; + case fnv1a("limegreen"): + return CSSColor{50, 205, 50, 255}; + case fnv1a("linen"): + return CSSColor{250, 240, 230, 255}; + case fnv1a("magenta"): + return CSSColor{255, 0, 255, 255}; + case fnv1a("maroon"): + return CSSColor{128, 0, 0, 255}; + case fnv1a("mediumaquamarine"): + return CSSColor{102, 205, 170, 255}; + case fnv1a("mediumblue"): + return CSSColor{0, 0, 205, 255}; + case fnv1a("mediumorchid"): + return CSSColor{186, 85, 211, 255}; + case fnv1a("mediumpurple"): + return CSSColor{147, 112, 219, 255}; + case fnv1a("mediumseagreen"): + return CSSColor{60, 179, 113, 255}; + case fnv1a("mediumslateblue"): + return CSSColor{123, 104, 238, 255}; + case fnv1a("mediumspringgreen"): + return CSSColor{0, 250, 154, 255}; + case fnv1a("mediumturquoise"): + return CSSColor{72, 209, 204, 255}; + case fnv1a("mediumvioletred"): + return CSSColor{199, 21, 133, 255}; + case fnv1a("midnightblue"): + return CSSColor{25, 25, 112, 255}; + case fnv1a("mintcream"): + return CSSColor{245, 255, 250, 255}; + case fnv1a("mistyrose"): + return CSSColor{255, 228, 225, 255}; + case fnv1a("moccasin"): + return CSSColor{255, 228, 181, 255}; + case fnv1a("navajowhite"): + return CSSColor{255, 222, 173, 255}; + case fnv1a("navy"): + return CSSColor{0, 0, 128, 255}; + case fnv1a("oldlace"): + return CSSColor{253, 245, 230, 255}; + case fnv1a("olive"): + return CSSColor{128, 128, 0, 255}; + case fnv1a("olivedrab"): + return CSSColor{107, 142, 35, 255}; + case fnv1a("orange"): + return CSSColor{255, 165, 0, 255}; + case fnv1a("orangered"): + return CSSColor{255, 69, 0, 255}; + case fnv1a("orchid"): + return CSSColor{218, 112, 214, 255}; + case fnv1a("palegoldenrod"): + return CSSColor{238, 232, 170, 255}; + case fnv1a("palegreen"): + return CSSColor{152, 251, 152, 255}; + case fnv1a("paleturquoise"): + return CSSColor{175, 238, 238, 255}; + case fnv1a("palevioletred"): + return CSSColor{219, 112, 147, 255}; + case fnv1a("papayawhip"): + return CSSColor{255, 239, 213, 255}; + case fnv1a("peachpuff"): + return CSSColor{255, 218, 185, 255}; + case fnv1a("peru"): + return CSSColor{205, 133, 63, 255}; + case fnv1a("pink"): + return CSSColor{255, 192, 203, 255}; + case fnv1a("plum"): + return CSSColor{221, 160, 221, 255}; + case fnv1a("powderblue"): + return CSSColor{176, 224, 230, 255}; + case fnv1a("purple"): + return CSSColor{128, 0, 128, 255}; + case fnv1a("rebeccapurple"): + return CSSColor{102, 51, 153, 255}; + case fnv1a("red"): + return CSSColor{255, 0, 0, 255}; + case fnv1a("rosybrown"): + return CSSColor{188, 143, 143, 255}; + case fnv1a("royalblue"): + return CSSColor{65, 105, 225, 255}; + case fnv1a("saddlebrown"): + return CSSColor{139, 69, 19, 255}; + case fnv1a("salmon"): + return CSSColor{250, 128, 114, 255}; + case fnv1a("sandybrown"): + return CSSColor{244, 164, 96, 255}; + case fnv1a("seagreen"): + return CSSColor{46, 139, 87, 255}; + case fnv1a("seashell"): + return CSSColor{255, 245, 238, 255}; + case fnv1a("sienna"): + return CSSColor{160, 82, 45, 255}; + case fnv1a("silver"): + return CSSColor{192, 192, 192, 255}; + case fnv1a("skyblue"): + return CSSColor{135, 206, 235, 255}; + case fnv1a("slateblue"): + return CSSColor{106, 90, 205, 255}; + case fnv1a("slategray"): + return CSSColor{112, 128, 144, 255}; + case fnv1a("slategrey"): + return CSSColor{112, 128, 144, 255}; + case fnv1a("snow"): + return CSSColor{255, 250, 250, 255}; + case fnv1a("springgreen"): + return CSSColor{0, 255, 127, 255}; + case fnv1a("steelblue"): + return CSSColor{70, 130, 180, 255}; + case fnv1a("tan"): + return CSSColor{210, 180, 140, 255}; + case fnv1a("teal"): + return CSSColor{0, 128, 128, 255}; + case fnv1a("thistle"): + return CSSColor{216, 191, 216, 255}; + case fnv1a("tomato"): + return CSSColor{255, 99, 71, 255}; + case fnv1a("transparent"): + return CSSColor{0, 0, 0, 0}; + case fnv1a("turquoise"): + return CSSColor{64, 224, 208, 255}; + case fnv1a("violet"): + return CSSColor{238, 130, 238, 255}; + case fnv1a("wheat"): + return CSSColor{245, 222, 179, 255}; + case fnv1a("white"): + return CSSColor{255, 255, 255, 255}; + case fnv1a("whitesmoke"): + return CSSColor{245, 245, 245, 255}; + case fnv1a("yellow"): + return CSSColor{255, 255, 0, 255}; + case fnv1a("yellowgreen"): + return CSSColor{154, 205, 50, 255}; + default: + return std::nullopt; } +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSNumber.h}: +namespace facebook::react { +struct CSSNumber { + float value{}; + constexpr bool operator==(const CSSNumber& rhs) const = default; }; template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "columnGap"; -}; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "rowGap"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "height"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - MaxContent = to_underlying(CSSKeyword::MaxContent), - MinContent = to_underlying(CSSKeyword::MinContent), - }; - using DeclaredValue = - CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Auto); +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + if (token.type() == CSSTokenType::Number) { + return CSSNumber{token.numericValue()}; + } + return {}; } }; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "width"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "minWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "minHeight"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "maxWidth"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "maxHeight"; +static_assert(CSSDataType); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSPercentage.h}: +namespace facebook::react { +struct CSSPercentage { + float value{}; + constexpr bool operator==(const CSSPercentage& rhs) const = default; }; template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "inset"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - }; - using DeclaredValue = - CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Auto); +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + if (token.type() == CSSTokenType::Percentage) { + return CSSPercentage{token.numericValue()}; + } + return {}; } }; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "top"; -}; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "right"; -}; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "bottom"; -}; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "left"; -}; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "start"; -}; -template <> -struct CSSPropDefinition : CSSPropDefinition { - constexpr static std::string_view kName = "end"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "insetBlock"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "insetBlockEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "insetBlockStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "insetInline"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "insetInlineEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "insetInlineStart"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "justifyContent"; - enum class Keyword : std::underlying_type_t { - Center = to_underlying(CSSKeyword::Center), - FlexEnd = to_underlying(CSSKeyword::FlexEnd), - FlexStart = to_underlying(CSSKeyword::FlexStart), - SpaceAround = to_underlying(CSSKeyword::SpaceAround), - SpaceBetween = to_underlying(CSSKeyword::SpaceBetween), - SpaceEvenly = to_underlying(CSSKeyword::SpaceEvenly), - Start = to_underlying(CSSKeyword::Start), - End = to_underlying(CSSKeyword::End), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::FlexStart); +static_assert(CSSDataType); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSRatio.h}: +namespace facebook::react { +struct CSSRatio { + float numerator{}; + float denominator{}; + constexpr bool operator==(const CSSRatio& rhs) const = default; + constexpr bool isDegenerate() const { + return numerator == 0.0f || + numerator == std::numeric_limits::infinity() || + denominator == 0.0f || + denominator == std::numeric_limits::infinity(); } }; template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "margin"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - }; - using DeclaredValue = - CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::length(0.0f, CSSLengthUnit::Px); +struct CSSDataTypeParser { + static constexpr auto consume(CSSSyntaxParser& parser) + -> std::optional { + auto numerator = parseNextCSSValue(parser); + if (!std::holds_alternative(numerator)) { + return {}; + } + auto numeratorValue = std::get(numerator).value; + if (numeratorValue >= 0) { + auto denominator = + peekNextCSSValue(parser, CSSDelimiter::Solidus); + if (std::holds_alternative(denominator) && + std::get(denominator).value >= 0) { + parseNextCSSValue(parser, CSSDelimiter::Solidus); + return CSSRatio{numeratorValue, std::get(denominator).value}; + } + return CSSRatio{numeratorValue, 1.0f}; + } + return {}; } }; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginBlock"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginBlockEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginBlockStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginBottom"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginHorizontal"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginInline"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginInlineEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginInlineStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginLeft"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginRight"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginTop"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "marginVertical"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "opacity"; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::number(1.0f); - } +static_assert(CSSDataType); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSShadow.h}: +namespace facebook::react { +struct CSSShadow { + CSSLength offsetX{}; + CSSLength offsetY{}; + CSSLength blurRadius{}; + CSSLength spreadDistance{}; + CSSColor color{CSSColor::black()}; + bool inset{false}; + constexpr bool operator==(const CSSShadow& rhs) const = default; }; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "overflow"; - enum class Keyword : std::underlying_type_t { - Auto = to_underlying(CSSKeyword::Auto), - Clip = to_underlying(CSSKeyword::Clip), - Hidden = to_underlying(CSSKeyword::Hidden), - Scroll = to_underlying(CSSKeyword::Scroll), - Visible = to_underlying(CSSKeyword::Visible), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::keyword(Keyword::Visible); - } +enum class CSSInsetShadowKeyword : std::underlying_type_t { + Inset = to_underlying(CSSKeyword::Inset), }; +static_assert(CSSDataType); template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "padding"; - using DeclaredValue = - CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor) { - return DeclaredValue::length(0.0f, CSSLengthUnit::Px); +struct CSSDataTypeParser { + static constexpr auto consume(CSSSyntaxParser& parser) + -> std::optional { + std::optional color{}; + bool inset{false}; + std::optional> + lengths{}; + for (auto nextValue = + parseNextCSSValue( + parser); + !std::holds_alternative(nextValue); + nextValue = + parseNextCSSValue( + parser, CSSDelimiter::Whitespace)) { + if (std::holds_alternative(nextValue)) { + if (lengths.has_value()) { + return {}; + } + lengths = parseRestLengths(std::get(nextValue), parser); + if (!lengths.has_value()) { + return {}; + } + continue; + } + if (std::holds_alternative(nextValue)) { + if (color.has_value()) { + return {}; + } + color = std::get(nextValue); + continue; + } + if (std::holds_alternative(nextValue)) { + if (inset) { + return {}; + } + inset = true; + continue; + } + } + if (!lengths.has_value()) { + return {}; + } + return CSSShadow{ + .offsetX = std::get<0>(*lengths), + .offsetY = std::get<1>(*lengths), + .blurRadius = std::get<2>(*lengths), + .spreadDistance = std::get<3>(*lengths), + .color = color.value_or(CSSColor::black()), + .inset = inset, + }; } }; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingBlock"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingBlockEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingBlockStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingBottom"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingHorizontal"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingInline"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingInlineEnd"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingInlineStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingLeft"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingRight"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingStart"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingTop"; -}; -template <> -struct CSSPropDefinition - : CSSPropDefinition { - constexpr static std::string_view kName = "paddingVertical"; -}; -template <> -struct CSSPropDefinition { - constexpr static std::string_view kName = "position"; - enum class Keyword : std::underlying_type_t { - Static = to_underlying(CSSKeyword::Static), - Relative = to_underlying(CSSKeyword::Relative), - Absolute = to_underlying(CSSKeyword::Absolute), - Fixed = to_underlying(CSSKeyword::Fixed), - Sticky = to_underlying(CSSKeyword::Sticky), - }; - using DeclaredValue = CSSValueVariant; - using SpecifiedValue = CSSValueVariant; - using ComputedValue = CSSValueVariant; - constexpr static bool isInherited() { - return false; - } - constexpr static DeclaredValue initialValue(CSSFlavor flavor) { - return flavor == CSSFlavor::W3C ? DeclaredValue::keyword(Keyword::Static) - : DeclaredValue::keyword(Keyword::Relative); + } + auto blurRadius = + parseNextCSSValue(parser, CSSDelimiter::Whitespace); + if (std::holds_alternative(blurRadius)) { + return std::make_tuple( + offsetX, std::get(offsetY), CSSLength{}, CSSLength{}); + } + if (std::get(blurRadius).value < 0) { + return {}; + } + auto spreadDistance = + parseNextCSSValue(parser, CSSDelimiter::Whitespace); + if (std::holds_alternative(spreadDistance)) { + return std::make_tuple( + offsetX, + std::get(offsetY), + std::get(blurRadius), + CSSLength{}); + } + return std::make_tuple( + offsetX, + std::get(offsetY), + std::get(blurRadius), + std::get(spreadDistance)); } }; +static_assert(CSSDataType); +using CSSShadowList = CSSCommaSeparatedList; } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/css/CSSSyntaxParser.h}: @@ -28205,35 +31726,47 @@ using CSSPreservedToken = CSSToken; struct CSSSimpleBlock { CSSTokenType openBracketType{}; }; +template +concept CSSSyntaxVisitorReturn = + std::is_default_constructible_v && std::equality_comparable; template -concept CSSFunctionVisitor = requires(T visitor, CSSFunctionBlock func) { - { visitor(func) } -> std::convertible_to; -}; +concept CSSFunctionVisitor = CSSSyntaxVisitorReturn && + requires(T visitor, CSSFunctionBlock func, CSSSyntaxParser& blockParser) { + { visitor(func, blockParser) } -> std::convertible_to; + }; template -concept CSSPreservedTokenVisitor = +concept CSSPreservedTokenVisitor = CSSSyntaxVisitorReturn && requires(T visitor, CSSPreservedToken token) { { visitor(token) } -> std::convertible_to; }; template -concept CSSSimpleBlockVisitor = requires(T visitor, CSSSimpleBlock block) { - { visitor(block) } -> std::convertible_to; -}; +concept CSSSimpleBlockVisitor = CSSSyntaxVisitorReturn && + requires(T visitor, CSSSimpleBlock block, CSSSyntaxParser& blockParser) { + { visitor(block, blockParser) } -> std::convertible_to; + }; template -concept CSSComponentValueVisitor = CSSFunctionVisitor || - CSSPreservedTokenVisitor || CSSSimpleBlockVisitor; +concept CSSComponentValueVisitor = CSSSyntaxVisitorReturn && + (CSSFunctionVisitor || CSSPreservedTokenVisitor || + CSSSimpleBlockVisitor); template -concept CSSUniqueComponentValueVisitors = +concept CSSUniqueComponentValueVisitors = CSSSyntaxVisitorReturn && (CSSComponentValueVisitor && ...) && ((CSSFunctionVisitor ? 1 : 0) + ... + 0) <= 1 && ((CSSPreservedTokenVisitor ? 1 : 0) + ... + 0) <= 1 && ((CSSSimpleBlockVisitor ? 1 : 0) + ... + 0) <= 1; -enum class CSSComponentValueDelimiter { - Comma, +enum class CSSDelimiter { Whitespace, + OptionalWhitespace, + Solidus, + SolidusOrWhitespace, + Comma, + CommaOrWhitespace, None, }; class CSSSyntaxParser { - template ... VisitorsT> + template < + CSSSyntaxVisitorReturn ReturnT, + CSSComponentValueVisitor... VisitorsT> friend public: @@ -28243,12 +31776,12 @@ class CSSSyntaxParser { constexpr CSSSyntaxParser(CSSSyntaxParser&&) = default; constexpr CSSSyntaxParser& operator=(const CSSSyntaxParser&) = default; constexpr CSSSyntaxParser& operator=(CSSSyntaxParser&&) = default; - template + template constexpr ReturnT consumeComponentValue( - CSSComponentValueDelimiter delimiter, + CSSDelimiter delimiter, const CSSComponentValueVisitor auto&... visitors) requires(CSSUniqueComponentValueVisitors); - template + template constexpr ReturnT consumeComponentValue( const CSSComponentValueVisitor auto&... visitors) requires(CSSUniqueComponentValueVisitors); @@ -28260,27 +31793,70 @@ class CSSSyntaxParser { currentToken_ = tokenizer_.next(); } } + constexpr bool consumeDelimiter(CSSDelimiter delimiter) { + if (delimiter == CSSDelimiter::None) { + return true; + } + bool hasWhiteSpace = peek().type() == CSSTokenType::WhiteSpace; + consumeWhitespace(); + switch (delimiter) { + case CSSDelimiter::Comma: + if (peek().type() == CSSTokenType::Comma) { + consumeToken(); + consumeWhitespace(); + return true; + } + return false; + case CSSDelimiter::Whitespace: + return hasWhiteSpace; + case CSSDelimiter::OptionalWhitespace: + return true; + case CSSDelimiter::CommaOrWhitespace: + if (peek().type() == CSSTokenType::Comma) { + consumeToken(); + consumeWhitespace(); + return true; + } + return hasWhiteSpace; + case CSSDelimiter::Solidus: + if (peek().type() == CSSTokenType::Delim && + peek().stringValue() == "/") { + consumeToken(); + consumeWhitespace(); + return true; + } + return false; + case CSSDelimiter::SolidusOrWhitespace: + if (peek().type() == CSSTokenType::Delim && + peek().stringValue() == "/") { + consumeToken(); + consumeWhitespace(); + return true; + } + return hasWhiteSpace; + case CSSDelimiter::None: + return true; + } + return false; + } +}; }; -template ... VisitorsT> +template < + CSSSyntaxVisitorReturn ReturnT, + CSSComponentValueVisitor... VisitorsT> struct CSSComponentValueVisitorDispatcher { CSSSyntaxParser& parser; constexpr ReturnT consumeComponentValue( - CSSComponentValueDelimiter delimiter, + CSSDelimiter delimiter, const VisitorsT&... visitors) { - switch (delimiter) { - case CSSComponentValueDelimiter::Comma: - parser.consumeWhitespace(); - if (parser.peek().type() != CSSTokenType::Comma) { - return ReturnT{}; - } - parser.consumeToken(); - parser.consumeWhitespace(); - break; - case CSSComponentValueDelimiter::Whitespace: - parser.consumeWhitespace(); - break; - case CSSComponentValueDelimiter::None: - break; + auto originalParser = parser; + if (!parser.consumeDelimiter(delimiter)) { + parser = originalParser; + return {}; + } + if (parser.peek().type() == parser.terminator_) { + parser = originalParser; + return {}; } switch (parser.peek().type()) { case CSSTokenType::Function: @@ -28312,67 +31888,71 @@ struct CSSComponentValueVisitorDispatcher { } break; } + parser = originalParser; return ReturnT{}; } - constexpr ReturnT consumeNextCommaDelimitedValue( - const VisitorsT&... visitors) { - parser.consumeWhitespace(); - if (parser.consumeToken().type() != CSSTokenType::Comma) { + constexpr std::optional visitFunction( + const CSSComponentValueVisitor auto& visitor, + const CSSComponentValueVisitor auto&... rest) { + if constexpr (CSSFunctionVisitor) { + auto name = parser.consumeToken().stringValue(); + parser.consumeWhitespace(); + auto blockParser = CSSSyntaxParser{parser, CSSTokenType::CloseParen}; + auto functionValue = visitor({name}, blockParser); + parser.advanceToBlockParser(blockParser); + parser.consumeWhitespace(); + if (parser.peek().type() == CSSTokenType::CloseParen && + functionValue != ReturnT{}) { + parser.consumeToken(); + return functionValue; + } return {}; } - parser.consumeWhitespace(); - return consumeComponentValue(std::forward(visitors)...); + return visitFunction(rest...); } - constexpr ReturnT consumeNextWhitespaceDelimitedValue( - const VisitorsT&... visitors) { - parser.consumeWhitespace(); - return consumeComponentValue(std::forward(visitors)...); - } - constexpr std::optional visitFunction(const VisitorsT&... visitors) { - for (auto visitor : {visitors...}) { - if constexpr (CSSFunctionVisitor) { - auto functionValue = - visitor({.name = parser.consumeToken().stringValue()}); - parser.consumeWhitespace(); - if (parser.peek().type() == CSSTokenType::CloseParen) { - parser.consumeToken(); - return functionValue; - } - return {}; - } - } + constexpr std::optional visitFunction() { return {}; } constexpr std::optional visitSimpleBlock( CSSTokenType endToken, - const VisitorsT&... visitors) { - for (auto visitor : {visitors...}) { - if constexpr (CSSSimpleBlockVisitor) { - auto blockValue = - visitor({.openBracketType = parser.consumeToken().type()}); - parser.consumeWhitespace(); - if (parser.peek().type() == endToken) { - parser.consumeToken(); - return blockValue; - } - return {}; + const CSSComponentValueVisitor auto& visitor, + const CSSComponentValueVisitor auto&... rest) { + if constexpr (CSSSimpleBlockVisitor) { + auto openBracketType = parser.consumeToken().type(); + parser.consumeWhitespace(); + auto blockParser = CSSSyntaxParser{parser, endToken}; + auto blockValue = visitor({openBracketType}, blockParser); + parser.advanceToBlockParser(blockParser); + parser.consumeWhitespace(); + if (parser.peek().type() == endToken && blockValue != ReturnT{}) { + parser.consumeToken(); + return blockValue; } + return {}; } + return visitSimpleBlock(endToken, rest...); + } + constexpr std::optional visitSimpleBlock(CSSTokenType endToken) { return {}; } constexpr std::optional visitPreservedToken( - const VisitorsT&... visitors) { - for (auto visitor : {visitors...}) { - if constexpr (CSSPreservedTokenVisitor) { - return visitor(parser.consumeToken()); + const CSSComponentValueVisitor auto& visitor, + const CSSComponentValueVisitor auto&... rest) { + if constexpr (CSSPreservedTokenVisitor) { + auto ret = visitor(parser.consumeToken()); + if (ret != ReturnT{}) { + return ret; } } + return visitPreservedToken(rest...); + } + constexpr std::optional visitPreservedToken() { return {}; } }; -template +template constexpr ReturnT CSSSyntaxParser::consumeComponentValue( - CSSComponentValueDelimiter delimiter, + CSSDelimiter delimiter, const CSSComponentValueVisitor auto&... visitors) requires(CSSUniqueComponentValueVisitors) { @@ -28380,13 +31960,12 @@ constexpr ReturnT CSSSyntaxParser::consumeComponentValue( *this} .consumeComponentValue(delimiter, visitors...); } -template +template constexpr ReturnT CSSSyntaxParser::consumeComponentValue( const CSSComponentValueVisitor auto&... visitors) requires(CSSUniqueComponentValueVisitors) { - return consumeComponentValue( - CSSComponentValueDelimiter::None, visitors...); + return consumeComponentValue(CSSDelimiter::None, visitors...); } } // namespace facebook::react @@ -28523,52 +32102,14 @@ class CSSTokenizer { return false; } constexpr CSSToken consumeNumber() { - int32_t signPart = 1.0; - if (peek() == '+' || peek() == '-') { - if (peek() == '-') { - signPart = -1.0; - } - advance(); - } - int32_t intPart = 0; - while (isDigit(peek())) { - intPart = intPart * 10 + (peek() - '0'); - advance(); - } - int32_t fractionalPart = 0; - int32_t fractionDigits = 0; - if (peek() == '.') { - advance(); - while (isDigit(peek())) { - fractionalPart = fractionalPart * 10 + (peek() - '0'); - fractionDigits++; - advance(); - } - } - int32_t exponentSign = 1.0; - int32_t exponentPart = 0; - if (peek() == 'e' || peek() == 'E') { - advance(); - if (peek() == '+' || peek() == '-') { - if (peek() == '-') { - exponentSign = -1.0; - } - advance(); - } - while (isDigit(peek())) { - exponentPart = exponentPart * 10 + (peek() - '0'); - advance(); - } - } + auto* b = remainingCharacters_.data(); + auto* e = b + remainingCharacters_.size(); float value; - if (exponentPart == 0 && fractionalPart == 0) { - value = static_cast(signPart * intPart); - } else { - value = static_cast( - signPart * - (intPart + (fractionalPart * std::pow(10, -fractionDigits))) * - std::pow(10, exponentSign * exponentPart)); - } + fast_float::parse_options options{ + fast_float::chars_format::general | + fast_float::chars_format::allow_leading_plus}; + auto [ptr, ec] = fast_float::from_chars_advanced(b, e, value, options); + position_ += ptr - b; consumeRunningValue(); return {CSSTokenType::Number, value}; } @@ -28634,102 +32175,528 @@ class CSSTokenizer { }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSValue.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSTransform.h}: namespace facebook::react { -enum class CSSValueType : uint8_t { - CSSWideKeyword, - Keyword, - Length, - Number, - Percentage, - Ratio, - Angle, - Color, -}; -template -concept CSSDataType = std::is_trivially_destructible_v && - std::is_copy_constructible_v && std::is_default_constructible_v; -#pragma pack(push, 1) -struct CSSLength { - float value{}; - CSSLengthUnit unit{CSSLengthUnit::Px}; -}; -#pragma pack(pop) -struct CSSPercentage { - float value{}; +namespace detail { +template < + typename DataT, + TemplateStringLiteral Name, + CSSDataType... AllowedComponentsT> + requires(std::is_same_v< + decltype(DataT::value), + std::variant>) +struct CSSVariantComponentTransformParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, Name)) { + return {}; + } + auto val = parseNextCSSValue(parser); + return std::visit( + [&](auto&& v) -> std::optional { + if constexpr (std::is_same_v< + std::remove_cvref_t, + std::monostate>) { + return {}; + } else { + return DataT{.value = std::forward(v)}; + } + }, + val); + } }; -struct CSSNumber { - float value{}; +template + requires(std::is_same_v) +struct CSSNumberPercentTransformParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, Name)) { + return {}; + } + auto val = parseNextCSSValue(parser); + if (std::holds_alternative(val)) { + return {}; + } + return DataT{ + .value = std::holds_alternative(val) + ? std::get(val).value + : std::get(val).value / 100.0f}; + } }; -struct CSSRatio { - float numerator{}; - float denominator{}; +template + requires(std::is_same_v) +struct CSSAngleTransformParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, Name)) { + return {}; + } + auto value = parseNextCSSValue(parser); + if (std::holds_alternative(value)) { + return {}; + } + return DataT{ + .degrees = std::holds_alternative(value) + ? std::get(value).degrees + : 0.0f, + }; + } }; -struct CSSAngle { +} // namespace detail +struct CSSMatrix { + std::array values{}; + constexpr bool operator==(const CSSMatrix& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "matrix")) { + return {}; + } + CSSMatrix matrix{}; + for (int i = 0; i < 6; i++) { + auto value = parseNextCSSValue( + parser, i == 0 ? CSSDelimiter::None : CSSDelimiter::Comma); + if (std::holds_alternative(value)) { + return {}; + } + matrix.values[i] = std::get(value).value; + } + return matrix; + } +}; +static_assert(CSSDataType); +struct CSSTranslate { + std::variant x{}; + std::variant y{}; + constexpr bool operator==(const CSSTranslate& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "translate")) { + return {}; + } + auto x = parseNextCSSValue(parser); + if (std::holds_alternative(x)) { + return {}; + } + auto y = + parseNextCSSValue(parser, CSSDelimiter::Comma); + CSSTranslate translate{}; + translate.x = std::holds_alternative(x) + ? std::variant{std::get(x)} + : std::variant{std::get(x)}; + if (!std::holds_alternative(y)) { + translate.y = std::holds_alternative(y) + ? std::variant{std::get(y)} + : std::variant{std::get(y)}; + } + return translate; + } +}; +static_assert(CSSDataType); +struct CSSTranslate3D { + std::variant x{}; + std::variant y{}; + CSSLength z{}; + constexpr bool operator==(const CSSTranslate3D& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "translate3d")) { + return {}; + } + auto x = parseNextCSSValue(parser); + if (std::holds_alternative(x)) { + return {}; + } + auto y = + parseNextCSSValue(parser, CSSDelimiter::Comma); + if (std::holds_alternative(y)) { + return {}; + } + auto z = parseNextCSSValue(parser, CSSDelimiter::Comma); + if (std::holds_alternative(z)) { + return {}; + } + return CSSTranslate3D{ + .x = std::holds_alternative(x) + ? std::variant{std::get(x)} + : std::variant{std::get( + x)}, + .y = std::holds_alternative(y) + ? std::variant{std::get(y)} + : std::variant{std::get( + y)}, + .z = std::get(z), + }; + } +}; +static_assert(CSSDataType); +struct CSSTranslateX { + std::variant value{}; + constexpr bool operator==(const CSSTranslateX& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSVariantComponentTransformParser< + CSSTranslateX, + "translateX", + CSSLength, + CSSPercentage> {}; +static_assert(CSSDataType); +struct CSSTranslateY { + std::variant value{}; + constexpr bool operator==(const CSSTranslateY& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSVariantComponentTransformParser< + CSSTranslateY, + "translateY", + CSSLength, + CSSPercentage> {}; +static_assert(CSSDataType); +struct CSSScale { + float x{}; + float y{}; + constexpr bool operator==(const CSSScale& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "scale")) { + return {}; + } + auto x = parseNextCSSValue(parser); + if (std::holds_alternative(x)) { + return {}; + } + auto y = parseNextCSSValue( + parser, CSSDelimiter::Comma); + auto normX = std::holds_alternative(x) + ? std::get(x).value + : std::get(x).value / 100.0f; + auto normY = std::holds_alternative(y) ? normX + : std::holds_alternative(y) + ? std::get(y).value + : std::get(y).value / 100.0f; + return CSSScale{normX, normY}; + } +}; +static_assert(CSSDataType); +struct CSSScaleX { + float value{}; + constexpr bool operator==(const CSSScaleX& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSNumberPercentTransformParser {}; +static_assert(CSSDataType); +struct CSSScaleY { + float value{}; + constexpr bool operator==(const CSSScaleY& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSNumberPercentTransformParser {}; +static_assert(CSSDataType); +struct CSSRotate { float degrees{}; + constexpr bool operator==(const CSSRotate& rhs) const = default; }; -struct CSSColor { - uint8_t r{}; - uint8_t g{}; - uint8_t b{}; - uint8_t a{}; +template <> +struct CSSDataTypeParser + : public detail::CSSAngleTransformParser {}; +static_assert(CSSDataType); +struct CSSRotateX { + float degrees{}; + constexpr bool operator==(const CSSRotateX& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSAngleTransformParser {}; +static_assert(CSSDataType); +struct CSSRotateY { + float degrees{}; + constexpr bool operator==(const CSSRotateY& rhs) const = default; }; +template <> +struct CSSDataTypeParser + : public detail::CSSAngleTransformParser {}; +static_assert(CSSDataType); +struct CSSRotateZ { + float degrees{}; + constexpr bool operator==(const CSSRotateZ& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSAngleTransformParser {}; +static_assert(CSSDataType); +struct CSSSkewX { + float degrees{}; + constexpr bool operator==(const CSSSkewX& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSAngleTransformParser {}; +static_assert(CSSDataType); +struct CSSSkewY { + float degrees{}; + constexpr bool operator==(const CSSSkewY& rhs) const = default; +}; +template <> +struct CSSDataTypeParser + : public detail::CSSAngleTransformParser {}; +static_assert(CSSDataType); +struct CSSPerspective { + CSSLength length{}; + constexpr bool operator==(const CSSPerspective& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& parser) -> std::optional { + if (!iequals(func.name, "perspective")) { + return {}; + } + auto value = parseNextCSSValue(parser); + if (std::holds_alternative(value) || + std::get(value).value < 0) { + return {}; + } + return CSSPerspective{ + .length = std::get(value), + }; + } +}; +static_assert(CSSDataType); +using CSSTransformFunction = CSSCompoundDataType< + CSSMatrix, + CSSTranslate, + CSSTranslateX, + CSSTranslateY, + CSSTranslate3D, + CSSScale, + CSSScaleX, + CSSScaleY, + CSSRotate, + CSSRotateX, + CSSRotateY, + CSSRotateZ, + CSSSkewX, + CSSSkewY, + CSSPerspective>; +using CSSTransformList = CSSWhitespaceSeparatedList; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSTransformOrigin.h}: +namespace facebook::react { +enum class CSSTransformOriginKeyword : std::underlying_type_t { + Center = static_cast>(CSSKeyword::Center), + Left = static_cast>(CSSKeyword::Left), + Right = static_cast>(CSSKeyword::Right), + Top = static_cast>(CSSKeyword::Top), + Bottom = static_cast>(CSSKeyword::Bottom), +}; +static_assert(CSSDataType); +struct CSSTransformOrigin { + std::variant x{}; + std::variant y{}; + CSSLength z{}; + constexpr bool operator==(const CSSTransformOrigin& rhs) const = default; +}; +template <> +struct CSSDataTypeParser { + static constexpr auto consume(CSSSyntaxParser& parser) + -> std::optional { + auto firstValue = + parseNextCSSValue( + parser); + if (std::holds_alternative(firstValue)) { + return {}; + } + auto secondValue = + parseNextCSSValue( + parser, CSSDelimiter::Whitespace); + if (std::holds_alternative(secondValue)) { + return singleValue(firstValue); + } + auto thirdValue = + parseNextCSSValue(parser, CSSDelimiter::Whitespace); + if (std::holds_alternative(firstValue) || + std::holds_alternative(firstValue) || + std::holds_alternative(secondValue) || + std::holds_alternative(secondValue)) { + return xyLengthPercentageValue(firstValue, secondValue, thirdValue); + } + if (std::holds_alternative(firstValue) && + std::holds_alternative(secondValue)) { + return xyKeywordValue( + std::get(firstValue), + std::get(secondValue), + thirdValue); + } + return {}; + } +}; + if (std::holds_alternative(value)) { + result.x = std::get(value); + result.y = keywordPercentage(CSSTransformOriginKeyword::Center); + } else if (std::holds_alternative(value)) { + result.x = std::get(value); + result.y = keywordPercentage(CSSTransformOriginKeyword::Center); + } else if (std::holds_alternative(value)) { + if (isHorizontalKeyword(std::get(value))) { + result.x = + keywordPercentage(std::get(value)); + result.y = keywordPercentage(CSSTransformOriginKeyword::Center); + } else { + result.x = keywordPercentage(CSSTransformOriginKeyword::Center); + result.y = + keywordPercentage(std::get(value)); + } + } + return result; + } + static constexpr std::optional xyLengthPercentageValue( + const std::variant< + std::monostate, + CSSLength, + CSSPercentage, + CSSTransformOriginKeyword>& val1, + const std::variant< + std::monostate, + CSSLength, + CSSPercentage, + CSSTransformOriginKeyword>& val2, + const std::variant& val3) { + CSSTransformOrigin result{}; + if (std::holds_alternative(val1)) { + result.x = std::get(val1); + } else if (std::holds_alternative(val1)) { + result.x = std::get(val1); + } else if (std::holds_alternative(val1)) { + if (!isHorizontalKeyword(std::get(val1))) { + return {}; + } + result.x = keywordPercentage(std::get(val1)); + } + if (std::holds_alternative(val2)) { + result.y = std::get(val2); + } else if (std::holds_alternative(val2)) { + result.y = std::get(val2); + } else if (std::holds_alternative(val2)) { + if (!isVerticalKeyword(std::get(val2))) { + return {}; + } + result.y = keywordPercentage(std::get(val2)); + } + if (std::holds_alternative(val3)) { + result.z = std::get(val3); + } + return result; + } + static constexpr std::optional xyKeywordValue( + CSSTransformOriginKeyword val1, + CSSTransformOriginKeyword val2, + const std::variant& val3) { + if (isHorizontalKeyword(val1) && isVerticalKeyword(val2)) { + return CSSTransformOrigin{ + .x = keywordPercentage(val1), + .y = keywordPercentage(val2), + .z = std::holds_alternative(val3) + ? std::get(val3) + : CSSLength{}}; + } + if (isVerticalKeyword(val1) && isHorizontalKeyword(val2)) { + return CSSTransformOrigin{ + .x = keywordPercentage(val2), + .y = keywordPercentage(val1), + .z = std::holds_alternative(val3) + ? std::get(val3) + : CSSLength{}}; + } + return {}; + } + static constexpr bool isHorizontalKeyword(CSSTransformOriginKeyword keyword) { + return keyword == CSSTransformOriginKeyword::Left || + keyword == CSSTransformOriginKeyword::Center || + keyword == CSSTransformOriginKeyword::Right; + } + static constexpr bool isVerticalKeyword(CSSTransformOriginKeyword keyword) { + return keyword == CSSTransformOriginKeyword::Top || + keyword == CSSTransformOriginKeyword::Center || + keyword == CSSTransformOriginKeyword::Bottom; + } + static constexpr CSSPercentage keywordPercentage( + CSSTransformOriginKeyword keyword) { + switch (keyword) { + case CSSTransformOriginKeyword::Left: + return CSSPercentage{0.0f}; + case CSSTransformOriginKeyword::Top: + return CSSPercentage{0.0f}; + case CSSTransformOriginKeyword::Center: + return CSSPercentage{50.0f}; + case CSSTransformOriginKeyword::Right: + return CSSPercentage{100.0f}; + case CSSTransformOriginKeyword::Bottom: + return CSSPercentage{100.0f}; + } + return {}; + } +}; +static_assert(CSSDataType); } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/css/CSSValueParser.h}: namespace facebook::react { namespace detail { -template class CSSValueParser { - using CSSValue = CSSValueVariant; - public: - explicit constexpr CSSValueParser(std::string_view css) : parser_{css} {} - constexpr CSSValue consumeValue( - CSSComponentValueDelimiter delimeter = CSSComponentValueDelimiter::None) { - return parser_.consumeComponentValue( - delimeter, [&](const CSSPreservedToken& token) { - if constexpr (hasType()) { - if (auto cssWideKeyword = consumeCSSWideKeyword(token)) { - return *cssWideKeyword; - } - } - if constexpr (hasType()) { - if (auto keyword = consumeKeyword(token)) { - return *keyword; - } - } - if constexpr (hasType()) { - if (auto ratio = consumeRatio(token)) { - return *ratio; - } - } - if constexpr (hasType()) { - if (auto number = consumeNumber(token)) { - return *number; - } - } - if constexpr (hasType()) { - if (auto length = consumeLength(token)) { - return *length; - } - } - if constexpr (hasType()) { - if (auto angle = consumeAngle(token)) { - return *angle; - } - } - if constexpr (hasType()) { - if (auto percentage = consumePercentage(token)) { - return *percentage; - } - } - if constexpr (hasType()) { - if (auto colorValue = consumeColorToken(token)) { - return *colorValue; - } - } - return CSSValue{}; + explicit constexpr CSSValueParser(CSSSyntaxParser& parser) + : parser_{parser} {} + template + constexpr std::variant consumeValue( + CSSDelimiter delimeter, + CSSCompoundDataType) { + using ReturnT = std::variant; + auto consumedValue = + tryConsumeParser...>( + delimeter); + if (!std::holds_alternative(consumedValue)) { + return consumedValue; + } + return parser_.consumeComponentValue( + delimeter, + [&](const CSSPreservedToken& token) { + return tryConsumePreservedToken< + ReturnT, + CSSDataTypeParser...>(token); + }, + [&](const CSSSimpleBlock& block, CSSSyntaxParser& blockParser) { + return tryConsumeSimpleBlock< + ReturnT, + CSSDataTypeParser...>(block, blockParser); + }, + [&](const CSSFunctionBlock& func, CSSSyntaxParser& blockParser) { + return tryConsumeFunctionBlock< + ReturnT, + CSSDataTypeParser...>(func, blockParser); }); } constexpr bool isFinished() const { @@ -28740,358 +32707,144 @@ class CSSValueParser { } }; } - constexpr std::optional consumeCSSWideKeyword( - const CSSPreservedToken& token) { - if (token.type() == CSSTokenType::Ident) { - if (auto keyword = parseCSSKeyword(token.stringValue())) { - return CSSValue::cssWideKeyword(*keyword); - } - } - return {}; - } - constexpr std::optional consumeAngle( - const CSSPreservedToken& token) { - if (token.type() == CSSTokenType::Dimension) { - if (auto unit = parseCSSAngleUnit(token.unit())) { - return CSSValue::angle(canonicalize(token.numericValue(), *unit)); + template < + typename ReturnT, + CSSValidDataTypeParser ParserT, + CSSValidDataTypeParser... RestParserT> + constexpr ReturnT tryConsumePreservedToken(const CSSPreservedToken& token) { + if constexpr (CSSPreservedTokenSink) { + if (auto ret = ParserT::consumePreservedToken(token)) { + return *ret; } } - return {}; + return tryConsumePreservedToken(token); } - constexpr std::optional consumePercentage( - const CSSPreservedToken& token) { - if (token.type() == CSSTokenType::Percentage) { - return CSSValue::percentage(token.numericValue()); - } + template + constexpr ReturnT tryConsumeSimpleBlock( + const CSSSimpleBlock&, + CSSSyntaxParser&) { return {}; } - constexpr std::optional consumeNumber( - const CSSPreservedToken& token) { - if (token.type() == CSSTokenType::Number) { - return CSSValue::number(token.numericValue()); + template < + typename ReturnT, + CSSValidDataTypeParser ParserT, + CSSValidDataTypeParser... RestParserT> + constexpr ReturnT tryConsumeSimpleBlock( + const CSSSimpleBlock& block, + CSSSyntaxParser& blockParser) { + if constexpr (CSSSimpleBlockSink) { + auto currentParser = blockParser; + if (auto ret = ParserT::consumeSimpleBlock(block, blockParser)) { + return *ret; + } + blockParser = currentParser; } - return {}; + return tryConsumeSimpleBlock(block, blockParser); } - constexpr std::optional consumeLength( - const CSSPreservedToken& token) { - switch (token.type()) { - case CSSTokenType::Dimension: - if (auto unit = parseCSSLengthUnit(token.unit())) { - return CSSValue::length(token.numericValue(), *unit); - } - break; - case CSSTokenType::Number: - if (token.numericValue() == 0) { - return CSSValue::length(token.numericValue(), CSSLengthUnit::Px); - } - break; - default: - break; - } + template + constexpr ReturnT tryConsumeFunctionBlock( + const CSSFunctionBlock&, + CSSSyntaxParser&) { return {}; } - constexpr std::optional consumeRatio( - const CSSPreservedToken& token) { - if (isValidRatioPart(token.numericValue())) { - float numerator = token.numericValue(); - CSSSyntaxParser lookaheadParser{parser_}; - auto hasSolidus = lookaheadParser.consumeComponentValue( - CSSComponentValueDelimiter::Whitespace, - [&](const CSSPreservedToken& token) { - return token.type() == CSSTokenType::Delim && - token.stringValue() == "/"; - }); - if (!hasSolidus) { - return CSSValue::ratio(numerator, 1.0f); - } - auto denominator = - lookaheadParser.consumeComponentValue>( - CSSComponentValueDelimiter::Whitespace, - [&](const CSSPreservedToken& token) { - if (token.type() == CSSTokenType::Number && - isValidRatioPart(token.numericValue())) { - return std::optional(token.numericValue()); - } - return std::optional{}; - }); - if (denominator.has_value()) { - parser_ = lookaheadParser; - return CSSValue::ratio(numerator, *denominator); + template < + typename ReturnT, + CSSValidDataTypeParser ParserT, + CSSValidDataTypeParser... RestParserT> + constexpr ReturnT tryConsumeFunctionBlock( + const CSSFunctionBlock& func, + CSSSyntaxParser& blockParser) { + if constexpr (CSSFunctionBlockSink) { + auto currentParser = blockParser; + if (auto ret = ParserT::consumeFunctionBlock(func, blockParser)) { + return *ret; } + blockParser = currentParser; } - return {}; + return tryConsumeFunctionBlock(func, blockParser); } - constexpr bool isValidRatioPart(float value) { - return value > 0.0f && value != +std::numeric_limits::infinity() && - value != -std::numeric_limits::infinity(); + template + constexpr ReturnT tryConsumeParser(CSSDelimiter) { + return {}; } - constexpr std::optional consumeColorToken( - const CSSPreservedToken& token) { - if (token.type() == CSSTokenType::Ident) { - return parseCSSNamedColor(token.stringValue()); - } else if (token.type() != CSSTokenType::Hash) { - return {}; - } - std::string_view hexColorValue = token.stringValue(); - if (isValidHexColor(hexColorValue)) { - if (hexColorValue.length() == 3) { - return CSSValue::color( - hexToNumeric(hexColorValue.substr(0, 1), HexColorType::Short), - hexToNumeric(hexColorValue.substr(1, 1), HexColorType::Short), - hexToNumeric(hexColorValue.substr(2, 1), HexColorType::Short), - 255u); - } else if (hexColorValue.length() == 4) { - return CSSValue::color( - hexToNumeric(hexColorValue.substr(0, 1), HexColorType::Short), - hexToNumeric(hexColorValue.substr(1, 1), HexColorType::Short), - hexToNumeric(hexColorValue.substr(2, 1), HexColorType::Short), - hexToNumeric(hexColorValue.substr(3, 1), HexColorType::Short)); - } else if (hexColorValue.length() == 6) { - return CSSValue::color( - hexToNumeric(hexColorValue.substr(0, 2), HexColorType::Long), - hexToNumeric(hexColorValue.substr(2, 2), HexColorType::Long), - hexToNumeric(hexColorValue.substr(4, 2), HexColorType::Long), - 255u); - } else if (hexColorValue.length() == 8) { - return CSSValue::color( - hexToNumeric(hexColorValue.substr(0, 2), HexColorType::Long), - hexToNumeric(hexColorValue.substr(2, 2), HexColorType::Long), - hexToNumeric(hexColorValue.substr(4, 2), HexColorType::Long), - hexToNumeric(hexColorValue.substr(6, 2), HexColorType::Long)); + template < + typename ReturnT, + CSSValidDataTypeParser ParserT, + CSSValidDataTypeParser... RestParserT> + constexpr ReturnT tryConsumeParser(CSSDelimiter delimeter) { + if constexpr (CSSParserSink) { + auto originalParser = parser_; + if (parser_.consumeDelimiter(delimeter)) { + if (auto ret = ParserT::consume(parser_)) { + return *ret; + } } + parser_ = originalParser; } - return {}; + return tryConsumeParser(delimeter); } - CSSSyntaxParser parser_; + CSSSyntaxParser& parser_; }; -template -constexpr void parseCSSValue( - std::string_view css, - CSSValueVariant& value) { - detail::CSSValueParser parser(css); +} // namespace detail +template +constexpr auto parseCSSProperty(std::string_view css) -> CSSVariantWithTypes< + CSSMergedDataTypes, + std::monostate> { + CSSSyntaxParser syntaxParser(css); + detail::CSSValueParser parser(syntaxParser); parser.consumeWhitespace(); - auto componentValue = parser.consumeValue(); + auto value = parser.consumeValue( + CSSDelimiter::None, + CSSMergedDataTypes{}); parser.consumeWhitespace(); if (parser.isFinished()) { - value = std::move(componentValue); - } else { - value = {}; + return value; } + return {}; }; -} // namespace detail -template -CSSValueVariant parseCSSValue(std::string_view css) { - CSSValueVariant value; - detail::parseCSSValue(css, value); - return value; -}; -template -constexpr CSSDeclaredValue parseCSSProp(std::string_view css) { - CSSDeclaredValue value; - detail::parseCSSValue(css, value); - return value; -} -} // namespace facebook::react - -/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSValueVariant.h}: -namespace facebook::react { -#pragma pack(push, 1) -template -class CSSValueVariant { - template - static constexpr bool canRepresent() { - return traits::containsType(); - } - template - static constexpr bool hasKeywordSet() { - if constexpr (CSSKeywordSet && !std::is_same_v) { - return true; - } else if constexpr (sizeof...(Rest) == 0) { - return false; - } else { - return hasKeywordSet(); - } - } - template - struct PackedKeywordSet { - using Type = void; - }; - template - struct PackedKeywordSet { - using Type = std::conditional_t< - hasKeywordSet(), - T, - typename PackedKeywordSet::Type>; - }; - - public: - using Keyword = typename PackedKeywordSet::Type; - constexpr CSSValueVariant() - requires(canRepresent()) - : CSSValueVariant(CSSValueType::CSSWideKeyword, CSSWideKeyword::Unset) {} - static constexpr CSSValueVariant cssWideKeyword(CSSWideKeyword keyword) { - return CSSValueVariant( - CSSValueType::CSSWideKeyword, CSSWideKeyword{keyword}); - } - template - static constexpr CSSValueVariant keyword(KeywordT keyword) - requires(canRepresent()) - { - return CSSValueVariant(CSSValueType::Keyword, KeywordT{keyword}); - } - static constexpr CSSValueVariant length(float value, CSSLengthUnit unit) - requires(canRepresent()) - { - return CSSValueVariant(CSSValueType::Length, CSSLength{value, unit}); - } - static constexpr CSSValueVariant number(float value) - requires(canRepresent()) - { - return CSSValueVariant(CSSValueType::Number, CSSNumber{value}); - } - static constexpr CSSValueVariant percentage(float value) - requires(canRepresent()) - { - return CSSValueVariant(CSSValueType::Percentage, CSSPercentage{value}); - } - static constexpr CSSValueVariant ratio(float numerator, float denominator) - requires(canRepresent()) - { - return CSSValueVariant( - CSSValueType::Ratio, CSSRatio{numerator, denominator}); - } - static constexpr CSSValueVariant angle(float degrees) - requires(canRepresent()) - { - return CSSValueVariant(CSSValueType::Angle, CSSAngle{degrees}); - } - static constexpr CSSValueVariant - color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) - requires(canRepresent()) - { - return CSSValueVariant(CSSValueType::Color, CSSColor{r, g, b, a}); - } - constexpr CSSValueType type() const { - return type_; - } - constexpr CSSWideKeyword getCSSWideKeyword() const - requires(canRepresent()) - { - return getIf(); - } - constexpr Keyword getKeyword() const - requires(hasKeywordSet()) - { - return getIf(); - } - constexpr CSSLength getLength() const - requires(canRepresent()) - { - return getIf(); - } - constexpr CSSNumber getNumber() const - requires(canRepresent()) - { - return getIf(); - } - constexpr CSSPercentage getPercentage() const - requires(canRepresent()) - { - return getIf(); - } - constexpr CSSRatio getRatio() const - requires(canRepresent()) - { - return getIf(); - } - constexpr CSSAngle getAngle() const - requires(canRepresent()) - { - return getIf(); - } - constexpr CSSColor getColor() const - requires(canRepresent()) - { - return getIf(); - } - constexpr bool hasValue() const - requires(canRepresent()) - { - return type() != CSSValueType::CSSWideKeyword || - getCSSWideKeyword() != CSSWideKeyword::Unset; - } - constexpr operator bool() const { - return hasValue(); - } - constexpr bool operator==(const CSSValueVariant& other) const { - if (type() != other.type()) { - return false; - } - switch (type()) { - case CSSValueType::CSSWideKeyword: - return getCSSWideKeyword() == other.getCSSWideKeyword(); - case CSSValueType::Keyword: - return getKeyword() == other.getKeyword(); - case CSSValueType::Length: - return getLength() == other.getLength(); - case CSSValueType::Number: - return getNumber() == other.getNumber(); - case CSSValueType::Percentage: - return getPercentage() == other.getPercentage(); - case CSSValueType::Ratio: - return getRatio() == other.getRatio(); - case CSSValueType::Angle: - return getAngle() == other.getAngle(); - case CSSValueType::Color: - return getColor() == other.getColor(); - } - return false; - } +template +constexpr auto parseNextCSSValue( + CSSSyntaxParser& syntaxParser, + CSSDelimiter delimeter = CSSDelimiter::None) + -> CSSVariantWithTypes< + CSSMergedDataTypes, + std::monostate> { + detail::CSSValueParser valueParser(syntaxParser); + return valueParser.consumeValue( + delimeter, CSSMergedDataTypes{}); +} +template +constexpr auto peekNextCSSValue( + CSSSyntaxParser& syntaxParser, + CSSDelimiter delimeter = CSSDelimiter::None) + -> CSSVariantWithTypes< + CSSMergedDataTypes, + std::monostate> { + auto savedParser = syntaxParser; + detail::CSSValueParser valueParser(syntaxParser); + auto ret = valueParser.consumeValue( + delimeter, CSSMergedDataTypes{}); + syntaxParser = savedParser; + return ret; +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/css/CSSZero.h}: +namespace facebook::react { +struct CSSZero { + constexpr bool operator==(const CSSZero& rhs) const = default; }; +template <> +struct CSSDataTypeParser { + static constexpr auto consumePreservedToken(const CSSPreservedToken& token) + -> std::optional { + if (token.type() == CSSTokenType::Number && token.numericValue() == 0) { + return CSSZero{}; } + return {}; } - template - union RecursiveUnion { - ValueT first; - RecursiveUnion rest; - }; - template - union RecursiveUnion { - ValueT first; - }; - template - constexpr const ValueT& getFromUnion(const UnionT& u) const { - if constexpr (std::is_same_v) { - return u.first; - } else { - return getFromUnion(u.rest); - } - } - template - constexpr CSSValueVariant(CSSValueType type, DataTypeT&& value) - : type_{type}, - data_{constructIntoUnion( - std::forward(value))} {} - template - constexpr UnionT constructIntoUnion(DataTypeT&& value) { - if constexpr (std::is_same_v) { - return UnionT{.first = std::forward(value)}; - } else { - return UnionT{ - .rest = constructIntoUnion( - std::forward(value))}; - } - } - CSSValueType type_; - RecursiveUnion data_; }; -#pragma pack(pop) -static_assert(sizeof(CSSValueVariant) == 2); -static_assert(sizeof(CSSValueVariant) == 6); -static_assert( - sizeof(CSSValueVariant) == 6); -static_assert(sizeof(CSSValueVariant) == 5); -static_assert(sizeof(CSSValueVariant) == 9); +static_assert(CSSDataType); } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/debug/DebugStringConvertible.h}: @@ -29111,6 +32864,11 @@ class DebugStringConvertible {}; /// @src {packages/react-native/ReactCommon/react/renderer/dom/DOM.h}: namespace facebook::react::dom { +constexpr uint_fast16_t DOCUMENT_POSITION_DISCONNECTED = 1; +constexpr uint_fast16_t DOCUMENT_POSITION_PRECEDING = 2; +constexpr uint_fast16_t DOCUMENT_POSITION_FOLLOWING = 4; +constexpr uint_fast16_t DOCUMENT_POSITION_CONTAINS = 8; +constexpr uint_fast16_t DOCUMENT_POSITION_CONTAINED_BY = 16; struct DOMRect { double x = 0; double y = 0; @@ -29302,7 +33060,7 @@ class ElementFragment final { using List = std::vector; using ListOfShared = std::vector; using ReferenceCallback = - std::function; + std::function& shadowNode)>; using FinalizeCallback = std::function; using StateCallback = std::function; @@ -29348,7 +33106,7 @@ inline ComponentBuilder simpleComponentBuilder( /// @src {packages/react-native/ReactCommon/react/renderer/graphics/BackgroundImage.h}: namespace facebook::react { -using BackgroundImage = std::variant; +using BackgroundImage = std::variant; }; /// @src {packages/react-native/ReactCommon/react/renderer/graphics/BlendMode.h}: @@ -29409,6 +33167,42 @@ inline std::optional blendModeFromString( return std::nullopt; } } +inline std::string toString(const BlendMode& blendMode) { + switch (blendMode) { + case BlendMode::Normal: + return "normal"; + case BlendMode::Multiply: + return "multiply"; + case BlendMode::Screen: + return "screen"; + case BlendMode::Overlay: + return "overlay"; + case BlendMode::Darken: + return "darken"; + case BlendMode::Lighten: + return "lighten"; + case BlendMode::ColorDodge: + return "color-dodge"; + case BlendMode::ColorBurn: + return "color-burn"; + case BlendMode::HardLight: + return "hard-light"; + case BlendMode::SoftLight: + return "soft-light"; + case BlendMode::Difference: + return "difference"; + case BlendMode::Exclusion: + return "exclusion"; + case BlendMode::Hue: + return "hue"; + case BlendMode::Saturation: + return "saturation"; + case BlendMode::Color: + return "color"; + case BlendMode::Luminosity: + return "luminosity"; + } +} } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/graphics/BoxShadow.h}: @@ -29479,6 +33273,20 @@ struct ColorComponents { }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/graphics/ColorStop.h}: +namespace facebook::react { +struct ColorStop { + bool operator==(const ColorStop& other) const = default; + SharedColor color; + ValueUnit position; +}; +struct ProcessedColorStop { + bool operator==(const ProcessedColorStop& other) const = default; + SharedColor color; + std::optional position; +}; +}; // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/graphics/Filter.h}: namespace facebook::react { enum class FilterType { @@ -29530,6 +33338,30 @@ inline FilterType filterTypeFromString(std::string_view filterName) { throw std::invalid_argument(std::string(filterName)); } } +inline std::string toString(const FilterType& filterType) { + switch (filterType) { + case FilterType::Blur: + return "blur"; + case FilterType::Brightness: + return "brightness"; + case FilterType::Contrast: + return "contrast"; + case FilterType::Grayscale: + return "grayscale"; + case FilterType::HueRotate: + return "hueRotate"; + case FilterType::Invert: + return "invert"; + case FilterType::Opacity: + return "opacity"; + case FilterType::Saturate: + return "saturate"; + case FilterType::Sepia: + return "sepia"; + case FilterType::DropShadow: + return "dropShadow"; + } +} } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/graphics/Geometry.h}: @@ -29569,11 +33401,6 @@ struct GradientDirection { return type == other.type && value == other.value; } }; -struct ColorStop { - bool operator==(const ColorStop& other) const = default; - SharedColor color; - Float position = 0.0f; -}; struct LinearGradient { GradientDirection direction; std::vector colorStops; @@ -29599,44 +33426,116 @@ namespace facebook::react { struct Point { Float x{0}; Float y{0}; - Point& operator+=(const Point& point) noexcept { + inline Point& operator+=(const Point& point) noexcept { x += point.x; y += point.y; return *this; } - Point& operator-=(const Point& point) noexcept { + inline Point& operator-=(const Point& point) noexcept { x -= point.x; y -= point.y; return *this; } - Point& operator*=(const Point& point) noexcept { + inline Point& operator*=(const Point& point) noexcept { x *= point.x; y *= point.y; return *this; } - friend Point operator+(Point lhs, const Point& rhs) noexcept { - return lhs += rhs; + inline Point operator+(const Point& rhs) const noexcept { + return { + .x = this->x + rhs.x, + .y = this->y + rhs.y, + }; } - friend Point operator-(Point lhs, const Point& rhs) noexcept { - return lhs -= rhs; + inline Point operator-(const Point& rhs) const noexcept { + return { + .x = this->x - rhs.x, + .y = this->y - rhs.y, + }; } + inline Point operator-() const noexcept { + return { + .x = -x, + .y = -y, + }; + } + inline bool operator==(const Point& rhs) const = default; + inline bool operator!=(const Point& rhs) const = default; }; -inline bool operator==(const Point& rhs, const Point& lhs) noexcept { - return std::tie(lhs.x, lhs.y) == std::tie(rhs.x, rhs.y); -} -inline bool operator!=(const Point& rhs, const Point& lhs) noexcept { - return !(lhs == rhs); -} } // namespace facebook::react namespace std { template <> struct hash { - size_t operator()(const facebook::react::Point& point) const noexcept { + inline size_t operator()(const facebook::react::Point& point) const noexcept { return facebook::react::hash_combine(point.x, point.y); } }; } // namespace std +/// @src {packages/react-native/ReactCommon/react/renderer/graphics/RadialGradient.h}: +namespace facebook::react { +enum class RadialGradientShape { Circle, Ellipse }; +struct RadialGradientSize { + enum class SizeKeyword { + ClosestSide, + FarthestSide, + ClosestCorner, + FarthestCorner + }; + struct Dimensions { + ValueUnit x; + ValueUnit y; + bool operator==(const Dimensions& other) const { + return x == other.x && y == other.y; + } + bool operator!=(const Dimensions& other) const { + return !(*this == other); + } + }; + std::variant value; + bool operator==(const RadialGradientSize& other) const { + if (std::holds_alternative(value) && + std::holds_alternative(other.value)) { + return std::get(value) == std::get(other.value); + } else if ( + std::holds_alternative(value) && + std::holds_alternative(other.value)) { + return std::get(value) == std::get(other.value); + } + return false; + } + bool operator!=(const RadialGradientSize& other) const { + return !(*this == other); + } +}; +struct RadialGradientPosition { + std::optional top; + std::optional left; + std::optional right; + std::optional bottom; + bool operator==(const RadialGradientPosition& other) const { + return top == other.top && left == other.left && right == other.right && + bottom == other.bottom; + } + bool operator!=(const RadialGradientPosition& other) const { + return !(*this == other); + } +}; +struct RadialGradient { + RadialGradientShape shape; + RadialGradientSize size; + RadialGradientPosition position; + std::vector colorStops; + bool operator==(const RadialGradient& other) const { + return shape == other.shape && size == other.size && + position == other.position && colorStops == other.colorStops; + } + bool operator!=(const RadialGradient& other) const { + return !(*this == other); + } +}; +}; // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/graphics/Rect.h}: namespace facebook::react { struct Rect { @@ -30000,6 +33899,9 @@ struct ValueUnit { } return 0.0f; } + constexpr operator bool() const { + return unit != UnitType::Undefined; + } }; } // namespace facebook::react @@ -30075,8 +33977,7 @@ inline void fromRawValueShared( namespace facebook::react { using Color = int32_t; namespace HostPlatformColor { -static const facebook::react::Color UndefinedColor = - std::numeric_limits::max(); +constexpr facebook::react::Color UndefinedColor = 0; } inline Color hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -30109,6 +34010,9 @@ inline float greenFromHostPlatformColor(Color color) { inline float blueFromHostPlatformColor(Color color) { return static_cast((color >> 0) & 0xff); } +inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept { + return alphaFromHostPlatformColor(color) > 0; +} } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/graphics/platform/android/react/renderer/graphics/PlatformColorParser.h}: @@ -30160,8 +34064,7 @@ inline void fromRawValue( namespace facebook::react { using Color = int32_t; namespace HostPlatformColor { -static const facebook::react::Color UndefinedColor = - std::numeric_limits::max(); +constexpr facebook::react::Color UndefinedColor = 0; } inline Color hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -30187,6 +34090,9 @@ inline float greenFromHostPlatformColor(Color color) { inline float blueFromHostPlatformColor(Color color) { return static_cast((color >> 0) & 0xff); } +inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept { + return alphaFromHostPlatformColor(color) > 0; +} inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { float ratio = 255; return ColorComponents{ @@ -30221,12 +34127,90 @@ inline void fromRawValue( /// @dep {packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/Float.h} /// @src {packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.h} +namespace facebook::react { +struct DynamicColor { + int32_t lightColor = 0; + int32_t darkColor = 0; + int32_t highContrastLightColor = 0; + int32_t highContrastDarkColor = 0; +}; +struct Color { + Color(int32_t color); + Color(const DynamicColor& dynamicColor); + Color(const ColorComponents& components); + Color() : uiColor_(nullptr) {}; + int32_t getColor() const; + std::size_t getUIColorHash() const; + static Color createSemanticColor(std::vector& semanticItems); + std::shared_ptr getUIColor() const { + return uiColor_; + } + float getChannel(int channelId) const; + ColorComponents getColorComponents() const { + float ratio = 255; + int32_t primitiveColor = getColor(); + return ColorComponents{ + (float)((primitiveColor >> 16) & 0xff) / ratio, + (float)((primitiveColor >> 8) & 0xff) / ratio, + (float)((primitiveColor >> 0) & 0xff) / ratio, + (float)((primitiveColor >> 24) & 0xff) / ratio}; + } + bool operator==(const Color& other) const; + bool operator!=(const Color& other) const; + operator int32_t() const { + return getColor(); + } +}; +namespace HostPlatformColor { +[[clang::no_destroy]] static const facebook::react::Color UndefinedColor = + Color(); +} +inline Color +hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + float ratio = 255; + const auto colorComponents = ColorComponents{ + .red = r / ratio, + .green = g / ratio, + .blue = b / ratio, + .alpha = a / ratio, + }; + return Color(colorComponents); +} +inline Color hostPlatformColorFromComponents(ColorComponents components) { + return Color(components); +} +inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { + return color.getColorComponents(); +} +inline float alphaFromHostPlatformColor(Color color) { + return color.getChannel(3) * 255; +} +inline float redFromHostPlatformColor(Color color) { + return color.getChannel(0) * 255; +} +inline float greenFromHostPlatformColor(Color color) { + return color.getChannel(1) * 255; +} +inline float blueFromHostPlatformColor(Color color) { + return color.getChannel(2) * 255; +} +inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept { + return alphaFromHostPlatformColor(color) > 0; +} +} // namespace facebook::react +template <> +struct std::hash { + size_t operator()(const facebook::react::Color& color) const { + return color.getUIColorHash(); + } +}; /// @src {packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.h} /// @src {packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.h}: +namespace facebook::react { +} // namespace facebook::react facebook::react::ColorComponents RCTPlatformColorComponentsFromSemanticItems( std::vector& semanticItems); UIColor* RCTPlatformColorFromSemanticItems( @@ -30237,7 +34221,83 @@ UIColor* RCTPlatformColorFromColor(const facebook::react::Color& color); /// @dep {packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/Float.h} /// @src {packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/HostPlatformColor.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.h} +namespace facebook::react { +struct DynamicColor { + int32_t lightColor = 0; + int32_t darkColor = 0; + int32_t highContrastLightColor = 0; + int32_t highContrastDarkColor = 0; +}; +struct Color { + Color(int32_t color); + Color(const DynamicColor& dynamicColor); + Color(const ColorComponents& components); + Color(std::shared_ptr uiColor); + int32_t getColor() const; + std::shared_ptr getUIColor() const { + return uiColor_; + } + float getChannel(int channelId) const; + ColorComponents getColorComponents() const { + float ratio = 255; + int32_t primitiveColor = getColor(); + return ColorComponents{ + (float)((primitiveColor >> 16) & 0xff) / ratio, + (float)((primitiveColor >> 8) & 0xff) / ratio, + (float)((primitiveColor >> 0) & 0xff) / ratio, + (float)((primitiveColor >> 24) & 0xff) / ratio}; + } + bool operator==(const Color& other) const; + bool operator!=(const Color& other) const; + operator int32_t() const { + return getColor(); + } +}; +namespace HostPlatformColor { +[[clang::no_destroy]] static const facebook::react::Color UndefinedColor = + Color(nullptr); +} +inline Color +hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + float ratio = 255; + const auto colorComponents = ColorComponents{ + .red = r / ratio, + .green = g / ratio, + .blue = b / ratio, + .alpha = a / ratio, + }; + return Color(colorComponents); +} +inline Color hostPlatformColorFromComponents(ColorComponents components) { + return Color(components); +} +inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { + return color.getColorComponents(); +} +inline float alphaFromHostPlatformColor(Color color) { + return color.getChannel(3) * 255; +} +inline float redFromHostPlatformColor(Color color) { + return color.getChannel(0) * 255; +} +inline float greenFromHostPlatformColor(Color color) { + return color.getChannel(1) * 255; +} +inline float blueFromHostPlatformColor(Color color) { + return color.getChannel(2) * 255; +} +inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept { + return alphaFromHostPlatformColor(color) > 0; +} +} // namespace facebook::react +template <> +struct std::hash { + size_t operator()(const facebook::react::Color& color) const { + auto seed = size_t{0}; + facebook::react::hash_combine(seed, color.getColor()); + return seed; + } +}; /// @src {packages/react-native/ReactCommon/react/renderer/graphics/platform/macos/react/renderer/graphics/PlatformColorParser.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.h} @@ -30266,6 +34326,18 @@ struct Color { m_color != otherColor.m_color || m_platformColor != otherColor.m_platformColor; } + Color(int32_t color) { + m_color = ColorFrom(color); + } + Color(const winrt::Windows::UI::Color& color) { + m_color = color; + } + Color() { + m_isUndefined = true; + }; + Color(const Color&) = default; + Color(Color&&) = default; + ~Color() = default; winrt::Windows::UI::Color AsWindowsColor() const { if (m_platformColor.empty()) { return m_color; @@ -30281,17 +34353,23 @@ struct Color { COLORREF AsColorRefWithAlpha() const { return RGB(m_color.R, m_color.G, m_color.B) | (m_color.A << 24); } - bool m_isUndefined; - winrt::Windows::UI::Color m_color; - std::vector m_platformColor; + operator int32_t() const { + const auto resolvedColor = AsWindowsColor(); + return (resolvedColor.A & 0xff) << 24 | (resolvedColor.R & 0xff) << 16 | + (resolvedColor.G & 0xff) << 8 | (resolvedColor.B & 0xff); + } + Color& operator=(const Color&) = default; + Color& operator=(Color&&) = default; + bool m_isUndefined{false}; + winrt::Windows::UI::Color m_color{}; + std::vector m_platformColor{}; }; namespace HostPlatformColor { -static const facebook::react::Color UndefinedColor{true, {}, {}}; +static const facebook::react::Color UndefinedColor{}; } inline Color hostPlatformColorFromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - const winrt::Windows::UI::Color color = {a, r, g, b}; - return {false, color, {}}; + return winrt::Windows::UI::Color{a, r, g, b}; } inline Color hostPlatformColorFromComponents(ColorComponents components) { float ratio = 255; @@ -30313,6 +34391,9 @@ inline float greenFromHostPlatformColor(Color color) { inline float blueFromHostPlatformColor(Color color) { return color.AsWindowsColor().B; } +inline bool hostPlatformColorIsColorMeaningful(Color color) noexcept { + return alphaFromHostPlatformColor(color) > 0; +} inline ColorComponents colorComponentsFromHostPlatformColor(Color color) { float ratio = 255; if (color.m_platformColor.empty()) { @@ -30351,15 +34432,13 @@ inline SharedColor parsePlatformColor( std::unordered_map>>()) { auto map = (std::unordered_map>)value; if (map.find("windowsbrush") != map.end()) { - facebook::react::Color color = { - true, - {}, - map["windowsbrush"], - }; - return {color}; + facebook::react::Color color; + color.m_isUndefined = false; + color.m_platformColor = map["windowsbrush"]; + return color; } } - return {HostPlatformColor::UndefinedColor}; + return HostPlatformColor::UndefinedColor; } inline void fromRawValue( const ContextContainer& contextContainer, @@ -30741,7 +34820,123 @@ NS_ASSUME_NONNULL_END /// @dep {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/macos/react/renderer/imagemanager/RCTImageManagerProtocol.h} /// @src {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImagePrimitivesConversions.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/macos/react/renderer/imagemanager/RCTImagePrimitivesConversions.h} +inline static UIViewContentMode RCTContentModeFromImageResizeMode(facebook::react::ImageResizeMode imageResizeMode) +{ + switch (imageResizeMode) { + case facebook::react::ImageResizeMode::Cover: + return UIViewContentModeScaleAspectFill; + case facebook::react::ImageResizeMode::Contain: + return UIViewContentModeScaleAspectFit; + case facebook::react::ImageResizeMode::Stretch: + return UIViewContentModeScaleToFill; + case facebook::react::ImageResizeMode::Center: + return UIViewContentModeCenter; + case facebook::react::ImageResizeMode::Repeat: + return UIViewContentModeScaleToFill; + case facebook::react::ImageResizeMode::None: + return UIViewContentModeTopLeft; + } +} +inline std::string toString(const facebook::react::ImageResizeMode &value) +{ + switch (value) { + case facebook::react::ImageResizeMode::Cover: + return "cover"; + case facebook::react::ImageResizeMode::Contain: + return "contain"; + case facebook::react::ImageResizeMode::Stretch: + return "stretch"; + case facebook::react::ImageResizeMode::Center: + return "center"; + case facebook::react::ImageResizeMode::Repeat: + return "repeat"; + case facebook::react::ImageResizeMode::None: + return "none"; + } +} +inline static NSURLRequestCachePolicy NSURLRequestCachePolicyFromImageSource( + const facebook::react::ImageSource &imageSource) +{ + switch (imageSource.cache) { + case facebook::react::ImageSource::CacheStategy::Reload: + return NSURLRequestReloadIgnoringLocalCacheData; + break; + case facebook::react::ImageSource::CacheStategy::ForceCache: + return NSURLRequestReturnCacheDataElseLoad; + break; + case facebook::react::ImageSource::CacheStategy::OnlyIfCached: + return NSURLRequestReturnCacheDataDontLoad; + break; + default: + return NSURLRequestUseProtocolCachePolicy; + break; + } +} +inline static NSURL *NSURLFromImageSource(const facebook::react::ImageSource &imageSource) +{ + @try { + NSString *urlString = [NSString stringWithUTF8String:imageSource.uri.c_str()]; + if (!imageSource.bundle.empty()) { + NSString *bundle = [NSString stringWithUTF8String:imageSource.bundle.c_str()]; + urlString = [NSString stringWithFormat:@"%@.bundle/%@", bundle, urlString]; + } + NSURL *url = [[NSURL alloc] initWithString:urlString]; + if (url.scheme) { + return url; + } + if ([urlString rangeOfString:@":"].location != NSNotFound) { + urlString = + [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + url = [NSURL URLWithString:urlString]; + return url; + } + urlString = [urlString stringByRemovingPercentEncoding]; + if ([urlString hasPrefix:@"~"]) { + urlString = [urlString stringByExpandingTildeInPath]; + } else { + if (![urlString isAbsolutePath]) { + urlString = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:urlString]; + } + } + url = [NSURL fileURLWithPath:urlString]; + return url; + } @catch (__unused NSException *exception) { + return nil; + } +} +inline static NSURLRequest *NSURLRequestFromImageSource(const facebook::react::ImageSource &imageSource) +{ + NSURL *url = NSURLFromImageSource(imageSource); + if (!url) { + RCTLogError(@"URI parsing error."); + return nil; + } + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; + NSString *method = @"GET"; + if (!imageSource.method.empty()) { + method = [[NSString alloc] initWithUTF8String:imageSource.method.c_str()].uppercaseString; + } + NSData *body = nil; + if (!imageSource.body.empty()) { + body = [NSData dataWithBytes:imageSource.body.c_str() length:imageSource.body.size()]; + } + NSURLRequestCachePolicy cachePolicy = NSURLRequestCachePolicyFromImageSource(imageSource); + if ([method isEqualToString:@"GET"] && imageSource.headers.empty() && body == nil && + cachePolicy == NSURLRequestUseProtocolCachePolicy) { + return request; + } + for (const auto &header : imageSource.headers) { + NSString *key = [NSString stringWithUTF8String:header.first.c_str()]; + NSString *value = [NSString stringWithUTF8String:header.second.c_str()]; + if (key != nullptr && value != nullptr) { + [request setValue:value forHTTPHeaderField:key]; + } + } + request.HTTPBody = body; + request.HTTPMethod = method; + request.cachePolicy = cachePolicy; + return request; +} /// @src {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManagerProtocol.h} @@ -30764,7 +34959,123 @@ NS_ASSUME_NONNULL_END /// @dep {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManagerProtocol.h} /// @src {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/macos/react/renderer/imagemanager/RCTImagePrimitivesConversions.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImagePrimitivesConversions.h} +inline static UIViewContentMode RCTContentModeFromImageResizeMode(facebook::react::ImageResizeMode imageResizeMode) +{ + switch (imageResizeMode) { + case facebook::react::ImageResizeMode::Cover: + return UIViewContentModeScaleAspectFill; + case facebook::react::ImageResizeMode::Contain: + return UIViewContentModeScaleAspectFit; + case facebook::react::ImageResizeMode::Stretch: + return UIViewContentModeScaleToFill; + case facebook::react::ImageResizeMode::Center: + return UIViewContentModeCenter; + case facebook::react::ImageResizeMode::Repeat: + return UIViewContentModeScaleToFill; + case facebook::react::ImageResizeMode::None: + return UIViewContentModeTopLeft; + } +} +inline std::string toString(const facebook::react::ImageResizeMode &value) +{ + switch (value) { + case facebook::react::ImageResizeMode::Cover: + return "cover"; + case facebook::react::ImageResizeMode::Contain: + return "contain"; + case facebook::react::ImageResizeMode::Stretch: + return "stretch"; + case facebook::react::ImageResizeMode::Center: + return "center"; + case facebook::react::ImageResizeMode::Repeat: + return "repeat"; + case facebook::react::ImageResizeMode::None: + return "none"; + } +} +inline static NSURLRequestCachePolicy NSURLRequestCachePolicyFromImageSource( + const facebook::react::ImageSource &imageSource) +{ + switch (imageSource.cache) { + case facebook::react::ImageSource::CacheStategy::Reload: + return NSURLRequestReloadIgnoringLocalCacheData; + break; + case facebook::react::ImageSource::CacheStategy::ForceCache: + return NSURLRequestReturnCacheDataElseLoad; + break; + case facebook::react::ImageSource::CacheStategy::OnlyIfCached: + return NSURLRequestReturnCacheDataDontLoad; + break; + default: + return NSURLRequestUseProtocolCachePolicy; + break; + } +} +inline static NSURL *NSURLFromImageSource(const facebook::react::ImageSource &imageSource) +{ + @try { + NSString *urlString = [NSString stringWithUTF8String:imageSource.uri.c_str()]; + if (!imageSource.bundle.empty()) { + NSString *bundle = [NSString stringWithUTF8String:imageSource.bundle.c_str()]; + urlString = [NSString stringWithFormat:@"%@.bundle/%@", bundle, urlString]; + } + NSURL *url = [[NSURL alloc] initWithString:urlString]; + if (url.scheme) { + return url; + } + if ([urlString rangeOfString:@":"].location != NSNotFound) { + urlString = + [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + url = [NSURL URLWithString:urlString]; + return url; + } + urlString = [urlString stringByRemovingPercentEncoding]; + if ([urlString hasPrefix:@"~"]) { + urlString = [urlString stringByExpandingTildeInPath]; + } else { + if (![urlString isAbsolutePath]) { + urlString = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:urlString]; + } + } + url = [NSURL fileURLWithPath:urlString]; + return url; + } @catch (__unused NSException *exception) { + return nil; + } +} +inline static NSURLRequest *NSURLRequestFromImageSource(const facebook::react::ImageSource &imageSource) +{ + NSURL *url = NSURLFromImageSource(imageSource); + if (!url) { + RCTLogError(@"URI parsing error."); + return nil; + } + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; + NSString *method = @"GET"; + if (!imageSource.method.empty()) { + method = [[NSString alloc] initWithUTF8String:imageSource.method.c_str()].uppercaseString; + } + NSData *body = nil; + if (!imageSource.body.empty()) { + body = [NSData dataWithBytes:imageSource.body.c_str() length:imageSource.body.size()]; + } + NSURLRequestCachePolicy cachePolicy = NSURLRequestCachePolicyFromImageSource(imageSource); + if ([method isEqualToString:@"GET"] && imageSource.headers.empty() && body == nil && + cachePolicy == NSURLRequestUseProtocolCachePolicy) { + return request; + } + for (const auto &header : imageSource.headers) { + NSString *key = [NSString stringWithUTF8String:header.first.c_str()]; + NSString *value = [NSString stringWithUTF8String:header.second.c_str()]; + if (key != NULL && value != NULL) { + [request setValue:value forHTTPHeaderField:key]; + } + } + request.HTTPBody = body; + request.HTTPMethod = method; + request.cachePolicy = cachePolicy; + return request; +} /// @src {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/macos/react/renderer/imagemanager/RCTSyncImageManager.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManagerProtocol.h} @@ -30924,30 +35235,10 @@ class MapBufferBuilder { /// @src {packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.h}: namespace facebook::react { -struct ShadowViewNodePair final { - ShadowView shadowView; - const ShadowNode* shadowNode; - bool flattened{false}; - bool isConcreteView{true}; - Point contextOrigin{0, 0}; - size_t mountIndex{0}; - mutable const ShadowViewNodePair* otherTreePair{nullptr}; - bool operator==(const ShadowViewNodePair& rhs) const; - bool operator!=(const ShadowViewNodePair& rhs) const; - bool inOtherTree() const { - return this->otherTreePair != nullptr; - } -}; -using ViewNodePairScope = std::deque; ShadowViewMutation::List calculateShadowViewMutations( const ShadowNode& oldRootShadowNode, const ShadowNode& newRootShadowNode); -std::vector sliceChildShadowNodeViewPairs( - const ShadowViewNodePair& shadowNodePair, - ViewNodePairScope& viewNodePairScope, - bool allowFlattened = false, - Point layoutOffset = {0, 0}); -} // namespace facebook::react +} /// @src {packages/react-native/ReactCommon/react/renderer/mounting/MountingCoordinator.h}: namespace facebook::react { @@ -31023,22 +35314,31 @@ class MountingTransaction final { namespace facebook::react { using ShadowTreeCommitTransaction = std::function; +enum class ShadowTreeCommitStatus { + Succeeded, + Failed, + Cancelled, +}; +enum class ShadowTreeCommitMode { + Normal, + Suspended, +}; +enum class ShadowTreeCommitSource { + Unknown, + React, +}; +struct ShadowTreeCommitOptions { + bool enableStateReconciliation{false}; + bool mountSynchronously{true}; + ShadowTreeCommitSource source{ShadowTreeCommitSource::Unknown}; +}; class ShadowTree final { public: using Unique = std::unique_ptr; - enum class CommitStatus { - Succeeded, - Failed, - Cancelled, - }; - enum class CommitMode { - Normal, - Suspended, - }; - struct CommitOptions { - bool enableStateReconciliation{false}; - bool mountSynchronously{true}; - }; + using CommitStatus = ShadowTreeCommitStatus; + using CommitMode = ShadowTreeCommitMode; + using CommitSource = ShadowTreeCommitSource; + using CommitOptions = ShadowTreeCommitOptions; ShadowTree( SurfaceId surfaceId, const LayoutConstraints& layoutConstraints, @@ -31068,7 +35368,6 @@ class ShadowTree final { mutable std::shared_mutex commitMutex_; mutable CommitMode commitMode_{CommitMode::Normal}; mutable ShadowTreeRevision currentRevision_; - mutable ShadowTreeRevision::Number lastRevisionNumberWithNewState_; std::shared_ptr mountingCoordinator_; }; } // namespace facebook::react @@ -31080,7 +35379,8 @@ class ShadowTreeDelegate { virtual RootShadowNode::Unshared shadowTreeWillCommit( const ShadowTree& shadowTree, const RootShadowNode::Shared& oldRootShadowNode, - const RootShadowNode::Unshared& newRootShadowNode) const = 0; + const RootShadowNode::Unshared& newRootShadowNode, + const ShadowTreeCommitOptions& commitOptions) const = 0; virtual void shadowTreeDidFinishTransaction( std::shared_ptr mountingCoordinator, bool mountSynchronously) const = 0; @@ -31230,6 +35530,101 @@ class TelemetryController final { }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/mounting/internal/CullingContext.h}: +namespace facebook::react { +struct CullingContext { + Rect frame; + Transform transform; + bool shouldConsiderCulling() const; + CullingContext adjustCullingContextIfNeeded( + const ShadowViewNodePair& pair) const; + bool operator==(const CullingContext& rhs) const = default; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/mounting/internal/ShadowViewNodePair.h}: +namespace facebook::react { +struct ShadowViewNodePair final { + ShadowView shadowView; + const ShadowNode* shadowNode; + bool flattened{false}; + bool isConcreteView{true}; + Point contextOrigin{0, 0}; + size_t mountIndex{0}; + mutable const ShadowViewNodePair* otherTreePair{nullptr}; + bool operator==(const ShadowViewNodePair& rhs) const { + return this->shadowNode == rhs.shadowNode; + } + bool operator!=(const ShadowViewNodePair& rhs) const { + return !(*this == rhs); + } + bool inOtherTree() const { + return this->otherTreePair != nullptr; + } +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/mounting/internal/TinyMap.h}: +template +class TinyMap final { + public: + using Pair = std::pair; + using Iterator = Pair*; + inline Iterator begin() { + cleanVector(erasedAtFront_ != numErased_); + Iterator it = begin_(); + if (it != nullptr) { + return it + erasedAtFront_; + } + return nullptr; + } + inline Iterator end() { + if (vector_.empty() || numErased_ == vector_.size()) { + return nullptr; + } + return &vector_.back() + 1; + } + inline Iterator find(KeyT key) { + cleanVector(); + react_native_assert(key != 0); + if (begin_() == nullptr) { + return end(); + } + for (auto it = begin_() + erasedAtFront_; it != end(); it++) { + if (it->first == key) { + return it; + } + } + return end(); + } + inline void insert(Pair pair) { + react_native_assert(pair.first != 0); + vector_.push_back(pair); + } + inline void erase(Iterator iterator) { + iterator->first = 0; + if (iterator == begin_() + erasedAtFront_) { + erasedAtFront_++; + } + numErased_++; + } +}; + size_t erasedAtFront_{0}; +}; + +/// @src {packages/react-native/ReactCommon/react/renderer/mounting/internal/sliceChildShadowNodeViewPairs.h}: +/// @dep {packages/react-native/ReactCommon/react/renderer/mounting/internal/CullingContext.h} + +namespace facebook::react { +using ViewNodePairScope = std::deque; +std::vector sliceChildShadowNodeViewPairs( + const ShadowViewNodePair& shadowNodePair, + ViewNodePairScope& viewNodePairScope, + bool allowFlattened, + Point layoutOffset, + const CullingContext& cullingContext); +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/mounting/stubs/StubView.h}: namespace facebook::react { static const int NO_VIEW_TAG = -1; @@ -31244,6 +35639,7 @@ class StubView final { ComponentHandle componentHandle; SurfaceId surfaceId; Tag tag; + ShadowNodeTraits traits{}; Props::Shared props; SharedEventEmitter eventEmitter; LayoutMetrics layoutMetrics; @@ -31262,17 +35658,26 @@ class StubViewTree { StubViewTree() = default; StubViewTree(const ShadowView& shadowView); void mutate(const ShadowViewMutationList& mutations); + void dispatchCommand( + const ShadowView& shadowView, + const std::string& commandName, + const folly::dynamic& args); const StubView& getRootStubView() const; const StubView& getStubView(Tag tag) const; size_t size() const; + std::vector takeMountingLogs(); }; std::unordered_map registry_{}; + std::vector mountingLogs_{}; friend bool operator==(const StubViewTree& lhs, const StubViewTree& rhs); friend bool operator!=(const StubViewTree& lhs, const StubViewTree& rhs); std::ostream& dumpTags(std::ostream& stream) const; bool hasTag(Tag tag) const { return registry_.find(tag) != registry_.end(); } + std::string getNativeId(Tag tag); + std::string getNativeId(const ShadowView& shadowView); + void recordMutation(const ShadowViewMutation& mutation); }; bool operator==(const StubViewTree& lhs, const StubViewTree& rhs); bool operator!=(const StubViewTree& lhs, const StubViewTree& rhs); @@ -31290,7 +35695,8 @@ StubViewTree buildStubViewTreeUsingDifferentiator( namespace facebook::react { void updateMountedFlag( const ShadowNode::ListOfShared& oldChildren, - const ShadowNode::ListOfShared& newChildren); + const ShadowNode::ListOfShared& newChildren, + ShadowTreeCommitSource commitSource); } /// @src {packages/react-native/ReactCommon/react/renderer/observers/events/EventPerformanceLogger.h}: @@ -31304,8 +35710,8 @@ class EventPerformanceLogger : public EventLogger, EventTag onEventStart( std::string_view name, SharedEventTarget target, - DOMHighResTimeStamp eventStartTimeStamp = - DOM_HIGH_RES_TIME_STAMP_UNSET) override; + std::optional eventStartTimeStamp = + std::nullopt) override; void onEventProcessingStart(EventTag tag) override; void onEventProcessingEnd(EventTag tag) override; void dispatchPendingEventTimingEntries( @@ -31313,15 +35719,15 @@ class EventPerformanceLogger : public EventLogger, surfaceIdsWithPendingRenderingUpdates) override; void shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - double mountTime) noexcept override; + HighResTimeStamp mountTime) noexcept override; }; - DOMHighResTimeStamp startTime{0.0}; - DOMHighResTimeStamp processingStartTime{0.0}; - DOMHighResTimeStamp processingEndTime{0.0}; + HighResTimeStamp startTime; + std::optional processingStartTime; + std::optional processingEndTime; bool isWaitingForMount{false}; PerformanceEntryInteractionId interactionId{0}; bool isWaitingForDispatch() { - return processingEndTime == 0.0; + return !processingEndTime.has_value(); } }; std::unordered_map eventsInFlight_; @@ -31339,30 +35745,36 @@ namespace facebook::react { using IntersectionObserverObserverId = int32_t; struct IntersectionObserverEntry { IntersectionObserverObserverId intersectionObserverId; - ShadowNode::Shared shadowNode; + ShadowNodeFamily::Shared shadowNodeFamily; Rect targetRect; Rect rootRect; Rect intersectionRect; bool isIntersectingAboveThresholds; - double time; + HighResTimeStamp time; + bool sameShadowNodeFamily( + const ShadowNodeFamily& otherShadowNodeFamily) const { + return std::addressof(*shadowNodeFamily) == + std::addressof(otherShadowNodeFamily); + } }; class IntersectionObserver { public: IntersectionObserver( IntersectionObserverObserverId intersectionObserverId, - ShadowNode::Shared targetShadowNode, + std::optional observationRootShadowNodeFamily, + ShadowNodeFamily::Shared targetShadowNodeFamily, std::vector thresholds, std::optional> rootThresholds = std::nullopt); std::optional updateIntersectionObservation( const RootShadowNode& rootShadowNode, - double time); + HighResTimeStamp time); std::optional - updateIntersectionObservationForSurfaceUnmount(double time); + updateIntersectionObservationForSurfaceUnmount(HighResTimeStamp time); IntersectionObserverObserverId getIntersectionObserverId() const { return intersectionObserverId_; } - const ShadowNode& getTargetShadowNode() const { - return *targetShadowNode_; + ShadowNodeFamily::Shared getTargetShadowNodeFamily() const { + return targetShadowNodeFamily_; } std::vector getThresholds() const { return thresholds_; @@ -31374,35 +35786,47 @@ class IntersectionObserver { /// @dep {packages/react-native/ReactCommon/react/renderer/observers/intersection/IntersectionObserver.h} namespace facebook::react { -class IntersectionObserverManager final : public UIManagerMountHook { +class IntersectionObserverManager final + : public UIManagerMountHook, + public RuntimeSchedulerIntersectionObserverDelegate { public: IntersectionObserverManager(); void observe( IntersectionObserverObserverId intersectionObserverId, - const ShadowNode::Shared& shadowNode, + const std::optional& observationRootShadowNode, + const ShadowNodeFamily::Shared& shadowNode, std::vector thresholds, std::optional> rootThresholds, const UIManager& uiManager); void unobserve( IntersectionObserverObserverId intersectionObserverId, - const ShadowNode& shadowNode); + const ShadowNodeFamily::Shared& shadowNode); void connect( + RuntimeScheduler& runtimeScheduler, UIManager& uiManager, std::function notifyIntersectionObserversCallback); - void disconnect(UIManager& uiManager); + void disconnect(RuntimeScheduler& runtimeScheduler, UIManager& uiManager); std::vector takeRecords(); + void updateIntersectionObservations( + const std::unordered_set& + surfaceIdsWithPendingRenderingUpdates) override; void shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - double time) noexcept override; - void shadowTreeDidUnmount(SurfaceId surfaceId, double time) noexcept override; + HighResTimeStamp time) noexcept override; + void shadowTreeDidUnmount(SurfaceId surfaceId, HighResTimeStamp time) noexcept + override; }; + mutable std::function notifyIntersectionObserversCallback_; + mutable std::vector pendingEntries_; + mutable std::mutex pendingEntriesMutex_; + mutable bool notifiedIntersectionObservers_{}; mutable bool mountHookRegistered_{}; void notifyObserversIfNecessary(); void notifyObservers(); void updateIntersectionObservations( SurfaceId surfaceId, const RootShadowNode* rootShadowNode, - double time); + HighResTimeStamp time); const IntersectionObserver& getRegisteredIntersectionObserver( SurfaceId surfaceId, IntersectionObserverObserverId observerId) const; @@ -31445,14 +35869,14 @@ struct MutationRecord { }; class MutationObserver { public: - MutationObserver(MutationObserverId intersectionObserverId); + explicit MutationObserver(MutationObserverId mutationObserverId); MutationObserver(const MutationObserver&) = delete; MutationObserver& operator=(const MutationObserver&) = delete; MutationObserver(MutationObserver&&) = default; MutationObserver& operator=(MutationObserver&&) = default; - void observe(ShadowNode::Shared targetShadowNode, bool observeSubtree); - void unobserve(const ShadowNode& targetShadowNode); - bool isObserving() const; + void observe( + std::shared_ptr targetShadowNodeFamily, + bool observeSubtree); void recordMutations( const RootShadowNode& oldRootShadowNode, const RootShadowNode& newRootShadowNode, @@ -31472,9 +35896,7 @@ class MutationObserverManager final : public UIManagerCommitHook { ShadowNode::Shared shadowNode, bool observeSubtree, const UIManager& uiManager); - void unobserve( - MutationObserverId mutationObserverId, - const ShadowNode& shadowNode); + void unobserveAll(MutationObserverId mutationObserverId); void connect( UIManager& uiManager, std::function&)> onMutations); @@ -31484,7 +35906,8 @@ class MutationObserverManager final : public UIManagerCommitHook { RootShadowNode::Unshared shadowTreeWillCommit( const ShadowTree& shadowTree, const RootShadowNode::Shared& oldRootShadowNode, - const RootShadowNode::Unshared& newRootShadowNode) noexcept override; + const RootShadowNode::Unshared& newRootShadowNode, + const ShadowTree::CommitOptions& commitOptions) noexcept override; }; void runMutationObservations( const ShadowTree& shadowTree, @@ -31495,13 +35918,14 @@ class MutationObserverManager final : public UIManagerCommitHook { /// @src {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h}: /// @dep {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerEventTimingDelegate.h} +/// @dep {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerIntersectionObserverDelegate.h} namespace facebook::react { using RuntimeSchedulerRenderingUpdate = std::function; -using RuntimeSchedulerTimeout = std::chrono::milliseconds; using SurfaceId = int32_t; using RuntimeSchedulerTaskErrorHandler = std::function; +extern const char RuntimeSchedulerKey[]; class RuntimeSchedulerBase { public: virtual ~RuntimeSchedulerBase() = default; @@ -31515,16 +35939,16 @@ class RuntimeSchedulerBase { RawCallback&& callback) noexcept = 0; virtual std::shared_ptr scheduleIdleTask( jsi::Function&& callback, - RuntimeSchedulerTimeout timeout = timeoutForSchedulerPriority( + HighResDuration timeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept = 0; virtual std::shared_ptr scheduleIdleTask( RawCallback&& callback, - RuntimeSchedulerTimeout timeout = timeoutForSchedulerPriority( + HighResDuration timeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept = 0; virtual void cancelTask(Task& task) noexcept = 0; virtual bool getShouldYield() noexcept = 0; virtual SchedulerPriority getCurrentPriorityLevel() const noexcept = 0; - virtual RuntimeSchedulerTimePoint now() const noexcept = 0; + virtual HighResTimeStamp now() const noexcept = 0; virtual void callExpiredTasks(jsi::Runtime& runtime) = 0; virtual void scheduleRenderingUpdate( SurfaceId surfaceId, @@ -31535,13 +35959,15 @@ class RuntimeSchedulerBase { PerformanceEntryReporter* reporter) = 0; virtual void setEventTimingDelegate( RuntimeSchedulerEventTimingDelegate* eventTimingDelegate) = 0; + virtual void setIntersectionObserverDelegate( + RuntimeSchedulerIntersectionObserverDelegate* + intersectionObserverDelegate) = 0; }; class RuntimeScheduler final : RuntimeSchedulerBase { public: explicit RuntimeScheduler( RuntimeExecutor runtimeExecutor, - std::function now = - RuntimeSchedulerClock::now, + std::function now = HighResTimeStamp::now, RuntimeSchedulerTaskErrorHandler onTaskError = handleTaskErrorDefault); RuntimeScheduler(const RuntimeScheduler&) = delete; RuntimeScheduler& operator=(const RuntimeScheduler&) = delete; @@ -31557,16 +35983,16 @@ class RuntimeScheduler final : RuntimeSchedulerBase { RawCallback&& callback) noexcept override; std::shared_ptr scheduleIdleTask( jsi::Function&& callback, - RuntimeSchedulerTimeout timeout = timeoutForSchedulerPriority( + HighResDuration timeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept override; std::shared_ptr scheduleIdleTask( RawCallback&& callback, - RuntimeSchedulerTimeout timeout = timeoutForSchedulerPriority( + HighResDuration timeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept override; void cancelTask(Task& task) noexcept override; bool getShouldYield() noexcept override; SchedulerPriority getCurrentPriorityLevel() const noexcept override; - RuntimeSchedulerTimePoint now() const noexcept override; + HighResTimeStamp now() const noexcept override; void callExpiredTasks(jsi::Runtime& runtime) override; void scheduleRenderingUpdate( SurfaceId surfaceId, @@ -31577,6 +36003,9 @@ class RuntimeScheduler final : RuntimeSchedulerBase { void setPerformanceEntryReporter(PerformanceEntryReporter* reporter) override; void setEventTimingDelegate( RuntimeSchedulerEventTimingDelegate* eventTimingDelegate) override; + void setIntersectionObserverDelegate( + RuntimeSchedulerIntersectionObserverDelegate* + intersectionObserverDelegate) override; }; } // namespace facebook::react @@ -31607,13 +36036,6 @@ class RuntimeSchedulerCallInvoker : public CallInvoker { }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h}: -namespace facebook::react { -using RuntimeSchedulerClock = std::chrono::steady_clock; -using RuntimeSchedulerTimePoint = RuntimeSchedulerClock::time_point; -using RuntimeSchedulerDuration = RuntimeSchedulerClock::duration; -} // namespace facebook::react - /// @src {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerEventTimingDelegate.h}: namespace facebook::react { using SurfaceId = int32_t; @@ -31626,13 +36048,25 @@ class RuntimeSchedulerEventTimingDelegate { }; } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerIntersectionObserverDelegate.h}: +namespace facebook::react { +using SurfaceId = int32_t; +class RuntimeSchedulerIntersectionObserverDelegate { + public: + virtual ~RuntimeSchedulerIntersectionObserverDelegate() = default; + virtual void updateIntersectionObservations( + const std::unordered_set& + surfaceIdsWithPendingRenderingUpdates) = 0; +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h}: namespace facebook::react { class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase { public: explicit RuntimeScheduler_Legacy( RuntimeExecutor runtimeExecutor, - std::function now, + std::function now, RuntimeSchedulerTaskErrorHandler onTaskError); RuntimeScheduler_Legacy(const RuntimeScheduler_Legacy&) = delete; RuntimeScheduler_Legacy& operator=(const RuntimeScheduler_Legacy&) = delete; @@ -31648,16 +36082,16 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase { RawCallback&& callback) noexcept override; std::shared_ptr scheduleIdleTask( jsi::Function&& callback, - RuntimeSchedulerTimeout timeout = timeoutForSchedulerPriority( + HighResDuration timeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept override; std::shared_ptr scheduleIdleTask( RawCallback&& callback, - RuntimeSchedulerTimeout timeout = timeoutForSchedulerPriority( + HighResDuration timeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept override; void cancelTask(Task& task) noexcept override; bool getShouldYield() noexcept override; SchedulerPriority getCurrentPriorityLevel() const noexcept override; - RuntimeSchedulerTimePoint now() const noexcept override; + HighResTimeStamp now() const noexcept override; void callExpiredTasks(jsi::Runtime& runtime) override; void scheduleRenderingUpdate( SurfaceId surfaceId, @@ -31669,6 +36103,9 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase { PerformanceEntryReporter* performanceEntryReporter) override; void setEventTimingDelegate( RuntimeSchedulerEventTimingDelegate* eventTimingDelegate) override; + void setIntersectionObserverDelegate( + RuntimeSchedulerIntersectionObserverDelegate* + intersectionObserverDelegate) override; }; std::atomic runtimeAccessRequests_{0}; std::atomic_bool isSynchronous_{false}; @@ -31678,11 +36115,11 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase { jsi::Runtime& runtime, const std::shared_ptr& task, bool didUserCallbackTimeout); - std::function now_; + std::function now_; std::atomic_bool isWorkLoopScheduled_{false}; std::atomic_bool isPerformingWork_{false}; - ShadowTreeRevisionConsistencyManager* shadowTreeRevisionConsistencyManager_{ - nullptr}; + std::atomic + shadowTreeRevisionConsistencyManager_{nullptr}; RuntimeSchedulerTaskErrorHandler onTaskError_; }; } // namespace facebook::react @@ -31693,7 +36130,7 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { public: explicit RuntimeScheduler_Modern( RuntimeExecutor runtimeExecutor, - std::function now, + std::function now, RuntimeSchedulerTaskErrorHandler onTaskError); RuntimeScheduler_Modern(const RuntimeScheduler_Modern&) = delete; RuntimeScheduler_Modern& operator=(const RuntimeScheduler_Modern&) = delete; @@ -31709,16 +36146,16 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { RawCallback&& callback) noexcept override; std::shared_ptr scheduleIdleTask( jsi::Function&& callback, - RuntimeSchedulerTimeout customTimeout = timeoutForSchedulerPriority( + HighResDuration customTimeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept override; std::shared_ptr scheduleIdleTask( RawCallback&& callback, - RuntimeSchedulerTimeout customTimeout = timeoutForSchedulerPriority( + HighResDuration customTimeout = timeoutForSchedulerPriority( SchedulerPriority::IdlePriority)) noexcept override; void cancelTask(Task& task) noexcept override; bool getShouldYield() noexcept override; SchedulerPriority getCurrentPriorityLevel() const noexcept override; - RuntimeSchedulerTimePoint now() const noexcept override; + HighResTimeStamp now() const noexcept override; void callExpiredTasks(jsi::Runtime& runtime) override; void scheduleRenderingUpdate( SurfaceId surfaceId, @@ -31730,6 +36167,9 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { PerformanceEntryReporter* performanceEntryReporter) override; void setEventTimingDelegate( RuntimeSchedulerEventTimingDelegate* eventTimingDelegate) override; + void setIntersectionObserverDelegate( + RuntimeSchedulerIntersectionObserverDelegate* + intersectionObserverDelegate) override; }; std::priority_queue< std::shared_ptr, @@ -31737,22 +36177,22 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { TaskPriorityComparer> taskQueue_; Task* currentTask_{}; - RuntimeSchedulerTimePoint lastYieldingOpportunity_; - RuntimeSchedulerDuration longestPeriodWithoutYieldingOpportunity_{}; - void markYieldingOpportunity(RuntimeSchedulerTimePoint currentTime); + HighResTimeStamp lastYieldingOpportunity_; + HighResDuration longestPeriodWithoutYieldingOpportunity_; + void markYieldingOpportunity(HighResTimeStamp currentTime); mutable std::shared_mutex schedulingMutex_; const RuntimeExecutor runtimeExecutor_; SchedulerPriority currentPriority_{SchedulerPriority::NormalPriority}; void scheduleEventLoop(); void runEventLoop(jsi::Runtime& runtime, bool onlyExpired); std::shared_ptr selectTask( - RuntimeSchedulerTimePoint currentTime, + HighResTimeStamp currentTime, bool onlyExpired); void scheduleTask(std::shared_ptr task); void runEventLoopTick( jsi::Runtime& runtime, Task& task, - RuntimeSchedulerTimePoint currentTime); + HighResTimeStamp taskStartTime); void executeTask( jsi::Runtime& runtime, Task& task, @@ -31762,16 +36202,19 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { void performMicrotaskCheckpoint(jsi::Runtime& runtime); void reportLongTasks( const Task& task, - RuntimeSchedulerTimePoint startTime, - RuntimeSchedulerTimePoint endTime); - std::function now_; + HighResTimeStamp startTime, + HighResTimeStamp endTime); + std::function now_; bool isEventLoopScheduled_{false}; std::queue pendingRenderingUpdates_; std::unordered_set surfaceIdsWithPendingRenderingUpdates_; - ShadowTreeRevisionConsistencyManager* shadowTreeRevisionConsistencyManager_{ + std::atomic + shadowTreeRevisionConsistencyManager_{nullptr}; + std::atomic eventTimingDelegate_{ nullptr}; PerformanceEntryReporter* performanceEntryReporter_{nullptr}; - RuntimeSchedulerEventTimingDelegate* eventTimingDelegate_{nullptr}; + RuntimeSchedulerIntersectionObserverDelegate* intersectionObserverDelegate_{ + nullptr}; RuntimeSchedulerTaskErrorHandler onTaskError_; }; } // namespace facebook::react @@ -31799,22 +36242,22 @@ static inline SchedulerPriority fromRawValue(double value) { react_native_assert(false && "Unsupported SchedulerPriority value"); return SchedulerPriority::NormalPriority; } -static inline std::chrono::milliseconds timeoutForSchedulerPriority( +static inline HighResDuration timeoutForSchedulerPriority( SchedulerPriority schedulerPriority) noexcept { switch (schedulerPriority) { case SchedulerPriority::ImmediatePriority: - return std::chrono::milliseconds(0); + return HighResDuration::fromChrono(std::chrono::milliseconds(0)); case SchedulerPriority::UserBlockingPriority: - return std::chrono::milliseconds(250); + return HighResDuration::fromChrono(std::chrono::milliseconds(250)); case SchedulerPriority::NormalPriority: - return std::chrono::seconds(5); + return HighResDuration::fromChrono(std::chrono::seconds(5)); case SchedulerPriority::LowPriority: - return std::chrono::seconds(10); + return HighResDuration::fromChrono(std::chrono::seconds(10)); case SchedulerPriority::IdlePriority: - return std::chrono::minutes(5); + return HighResDuration::fromChrono(std::chrono::minutes(5)); } react_native_assert(false && "Unsupported SchedulerPriority value"); - return std::chrono::seconds(5); + return HighResDuration::fromChrono(std::chrono::seconds(5)); } } // namespace facebook::react @@ -31825,11 +36268,11 @@ struct Task final : public jsi::NativeState { Task( SchedulerPriority priority, jsi::Function&& callback, - std::chrono::steady_clock::time_point expirationTime); + HighResTimeStamp expirationTime); Task( SchedulerPriority priority, RawCallback&& callback, - std::chrono::steady_clock::time_point expirationTime); + HighResTimeStamp expirationTime); }; class TaskPriorityComparer { public: @@ -31864,19 +36307,16 @@ inline static std::shared_ptr taskFromValue( namespace facebook::react { class StubClock { public: - RuntimeSchedulerTimePoint getNow() const { + HighResTimeStamp getNow() const { return timePoint_; } - void setTimePoint(RuntimeSchedulerTimePoint timePoint) { + void setTimePoint(HighResTimeStamp timePoint) { timePoint_ = timePoint; } - void setTimePoint(RuntimeSchedulerDuration duration) { - timePoint_ = RuntimeSchedulerTimePoint(duration); - } - RuntimeSchedulerTimePoint getTimePoint() { + HighResTimeStamp getTimePoint() { return timePoint_; } - void advanceTimeBy(RuntimeSchedulerDuration duration) { + void advanceTimeBy(HighResDuration duration) { timePoint_ += duration; } }; @@ -31993,8 +36433,6 @@ class Scheduler final : public UIManagerDelegate { ~Scheduler() override; void registerSurface(const SurfaceHandler& surfaceHandler) const noexcept; void unregisterSurface(const SurfaceHandler& surfaceHandler) const noexcept; - InspectorData getInspectorDataForInstance( - const EventEmitter& eventEmitter) const noexcept; const ComponentDescriptor* findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN( ComponentHandle handle) const; @@ -32016,13 +36454,25 @@ class Scheduler final : public UIManagerDelegate { const ShadowNode::Shared& shadowNode, bool isJSResponder, bool blockNativeResponder) override; + void uiManagerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) override; + void uiManagerShouldAddEventListener( + std::shared_ptr listener) final; + void uiManagerShouldRemoveEventListener( + const std::shared_ptr& listener) final; + void uiManagerDidStartSurface(const ShadowTree& shadowTree) override; ContextContainer::Shared getContextContainer() const; std::shared_ptr getUIManager() const; void reportMount(SurfaceId surfaceId) const; void addEventListener(std::shared_ptr listener); void removeEventListener( const std::shared_ptr& listener); + void uiManagerShouldSetOnSurfaceStartCallback( + OnSurfaceStartCallback&& callback) override; }; + mutable std::shared_mutex onSurfaceStartCallbackMutex_; + OnSurfaceStartCallback onSurfaceStartCallback_; }; } // namespace facebook::react @@ -32049,6 +36499,9 @@ class SchedulerDelegate { const ShadowView& shadowView, bool isJSResponder, bool blockNativeResponder) = 0; + virtual void schedulerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) = 0; virtual ~SchedulerDelegate() noexcept = default; }; } // namespace facebook::react @@ -32075,7 +36528,6 @@ class SurfaceHandler { Running = 2, }; SurfaceHandler(const std::string& moduleName, SurfaceId surfaceId) noexcept; - SurfaceHandler(SurfaceId surfaceId) noexcept; virtual ~SurfaceHandler() noexcept; SurfaceHandler(SurfaceHandler&& other) noexcept; SurfaceHandler(const SurfaceHandler& SurfaceHandler) noexcept = delete; @@ -32097,10 +36549,10 @@ class SurfaceHandler { const noexcept; Size measure( const LayoutConstraints& layoutConstraints, - const LayoutContext& layoutContext) const noexcept; + const LayoutContext& layoutContext) const; void constraintLayout( const LayoutConstraints& layoutConstraints, - const LayoutContext& layoutContext) const noexcept; + const LayoutContext& layoutContext) const; LayoutConstraints getLayoutConstraints() const noexcept; LayoutContext getLayoutContext() const noexcept; }; @@ -32128,17 +36580,26 @@ namespace facebook::react { class SurfaceManager final { public: explicit SurfaceManager(const Scheduler& scheduler) noexcept; + ~SurfaceManager() noexcept; + struct SurfaceProps { + SurfaceId surfaceId; + std::string moduleName; + folly::dynamic props; + LayoutConstraints layoutConstraints; + LayoutContext layoutContext; + }; void startSurface( SurfaceId surfaceId, const std::string& moduleName, const folly::dynamic& props, const LayoutConstraints& layoutConstraints = {}, - const LayoutContext& layoutContext = {}) const noexcept; - void startEmptySurface( - SurfaceId surfaceId, - const LayoutConstraints& layoutConstraints = {}, - const LayoutContext& layoutContext = {}) const noexcept; - void stopSurface(SurfaceId surfaceId) const noexcept; + const LayoutContext& layoutContext = {}) noexcept; + void stopSurface(SurfaceId surfaceId) noexcept; + void stopAllSurfaces() noexcept; + bool isSurfaceRunning(SurfaceId surfaceId) const noexcept; + std::unordered_set getRunningSurfaces() const noexcept; + std::optional getSurfaceProps( + SurfaceId surfaceId) const noexcept; Size measureSurface( SurfaceId surfaceId, const LayoutConstraints& layoutConstraints, @@ -32238,47 +36699,100 @@ class TransactionTelemetry final { namespace facebook::react { struct TextLayoutContext { Float pointScaleFactor{1.0}; + SurfaceId surfaceId{-1}; + bool operator==(const TextLayoutContext& rhs) const = default; }; -inline bool operator==( - const TextLayoutContext& lhs, - const TextLayoutContext& rhs) { - return std::tie(lhs.pointScaleFactor) == std::tie(rhs.pointScaleFactor); -} -inline bool operator!=( - const TextLayoutContext& lhs, - const TextLayoutContext& rhs) { - return !(lhs == rhs); -} } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/TextLayoutManager.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/TextLayoutManagerExtended.h}: namespace facebook::react { -class TextLayoutManager { +template +concept TextLayoutManagerWithPreparedLayout = requires( + TextLayoutManagerT textLayoutManager, + AttributedString attributedString, + ParagraphAttributes paragraphAttributes, + TextLayoutContext layoutContext, + LayoutConstraints layoutConstraints, + typename TextLayoutManagerT::PreparedLayout preparedLayout) { + sizeof(typename TextLayoutManagerT::PreparedLayout); + { + textLayoutManager.prepareLayout( + attributedString, paragraphAttributes, layoutContext, layoutConstraints) + } -> std::same_as; + { + textLayoutManager.measurePreparedLayout( + preparedLayout, layoutContext, layoutConstraints) + } -> std::same_as; +}; +namespace detail { +template +struct PreparedLayoutT { + using type = std::nullptr_t; +}; +template +struct PreparedLayoutT { + using type = typename T::PreparedLayout; +}; +template +class TextLayoutManagerExtended { public: - TextLayoutManager(const ContextContainer::Shared& contextContainer); - virtual ~TextLayoutManager() = default; - TextLayoutManager(const TextLayoutManager&) = delete; - TextLayoutManager& operator=(const TextLayoutManager&) = delete; - TextLayoutManager(TextLayoutManager&&) = delete; - TextLayoutManager& operator=(TextLayoutManager&&) = delete; - virtual TextMeasurement measure( - const AttributedStringBox& attributedStringBox, - const ParagraphAttributes& paragraphAttributes, - const TextLayoutContext& layoutContext, - const LayoutConstraints& layoutConstraints) const; - virtual LinesMeasurements measureLines( + static constexpr bool supportsLineMeasurement() { + return requires(TextLayoutManagerT textLayoutManager) { + { + textLayoutManager.measureLines( + AttributedStringBox{}, ParagraphAttributes{}, Size{}) + } -> std::same_as; + }; + } + static constexpr bool supportsPreparedLayout() { + return TextLayoutManagerWithPreparedLayout; + } + using PreparedLayout = typename PreparedLayoutT::type; + TextLayoutManagerExtended(const TextLayoutManagerT& textLayoutManager) + : textLayoutManager_(textLayoutManager) {} + LinesMeasurements measureLines( const AttributedStringBox& attributedStringBox, const ParagraphAttributes& paragraphAttributes, - const Size& size) const; - Float baseline( - const AttributedStringBox& attributedStringBox, + const Size& size) { + if constexpr (supportsLineMeasurement()) { + return textLayoutManager_.measureLines( + attributedStringBox, paragraphAttributes, size); + } + LOG(FATAL) << "Platform TextLayoutManager does not support measureLines"; + } + PreparedLayout prepareLayout( + const AttributedString& attributedString, const ParagraphAttributes& paragraphAttributes, - const Size& size) const; - - protected: - std::shared_ptr contextContainer_; - TextMeasureCache textMeasureCache_; - LineMeasureCache lineMeasureCache_; + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const { + if constexpr (supportsPreparedLayout()) { + return textLayoutManager_.prepareLayout( + attributedString, + paragraphAttributes, + layoutContext, + layoutConstraints); + } + LOG(FATAL) << "Platform TextLayoutManager does not support prepareLayout"; + } + TextMeasurement measurePreparedLayout( + const PreparedLayout& layout, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const { + if constexpr (supportsPreparedLayout()) { + return textLayoutManager_.measurePreparedLayout( + layout, layoutContext, layoutConstraints); + } + LOG(FATAL) + << "Platform TextLayoutManager does not support measurePreparedLayout"; + } +}; +} // namespace detail +using TextLayoutManagerExtended = + detail::TextLayoutManagerExtended; +struct MeasuredPreparedLayout { + LayoutConstraints layoutConstraints; + TextMeasurement measurement; + TextLayoutManagerExtended::PreparedLayout preparedLayout{}; }; } // namespace facebook::react @@ -32300,6 +36814,12 @@ struct LineMeasurement { Float xHeight); LineMeasurement(const folly::dynamic& data); bool operator==(const LineMeasurement& rhs) const; + static inline Float baseline(const std::vector& lines) { + if (!lines.empty()) { + return lines[0].ascender; + } + return 0; + } }; using LinesMeasurements = std::vector; class TextMeasurement final { @@ -32420,8 +36940,7 @@ inline bool operator==( return areAttributedStringsEquivalentLayoutWise( lhs.attributedString, rhs.attributedString) && lhs.paragraphAttributes == rhs.paragraphAttributes && - lhs.layoutConstraints.maximumSize.width == - rhs.layoutConstraints.maximumSize.width; + lhs.layoutConstraints == rhs.layoutConstraints; } inline bool operator!=( const TextMeasureCacheKey& lhs, @@ -32449,7 +36968,7 @@ struct hash { return facebook::react::hash_combine( attributedStringHashLayoutWise(key.attributedString), key.paragraphAttributes, - key.layoutConstraints.maximumSize.width); + key.layoutConstraints); } }; template <> @@ -32463,132 +36982,357 @@ struct hash { }; } // namespace std -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h} +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/JPreparedLayout.h}: +namespace facebook::react { +class JPreparedLayout : public jni::JavaClass { + public: + static auto constexpr kJavaDescriptor = + "Lcom/facebook/react/views/text/PreparedLayout;"; +}; +} // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontProperties.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontProperties.h} +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h}: +namespace facebook::react { +class TextLayoutManager { + public: + using PreparedLayout = SafeReleaseJniRef>; + TextLayoutManager(const ContextContainer::Shared& contextContainer); + TextLayoutManager(const TextLayoutManager&) = delete; + TextLayoutManager& operator=(const TextLayoutManager&) = delete; + TextLayoutManager(TextLayoutManager&&) = delete; + TextLayoutManager& operator=(TextLayoutManager&&) = delete; + TextMeasurement measure( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const; + TextMeasurement measureCachedSpannableById( + int64_t cacheId, + const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const; + LinesMeasurements measureLines( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const Size& size) const; + PreparedLayout prepareLayout( + const AttributedString& attributedString, + const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const; + TextMeasurement measurePreparedLayout( + const PreparedLayout& layout, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const; +}; +} // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontUtils.h} +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.h}: +namespace facebook::react { +class TextLayoutManager { + public: + TextLayoutManager(const ContextContainer::Shared& contextContainer); + virtual ~TextLayoutManager() = default; + TextLayoutManager(const TextLayoutManager&) = delete; + TextLayoutManager& operator=(const TextLayoutManager&) = delete; + TextLayoutManager(TextLayoutManager&&) = delete; + TextLayoutManager& operator=(TextLayoutManager&&) = delete; + virtual TextMeasurement measure( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const; -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTTextLayoutManager.h} + protected: + std::shared_ptr contextContainer_; + TextMeasureCache textMeasureCache_; +}; +} // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h}: -inline static NSTextAlignment RCTNSTextAlignmentFromTextAlignment(facebook::react::TextAlignment textAlignment) -{ - switch (textAlignment) { - case facebook::react::TextAlignment::Natural: - return NSTextAlignmentNatural; - case facebook::react::TextAlignment::Left: - return NSTextAlignmentLeft; - case facebook::react::TextAlignment::Right: - return NSTextAlignmentRight; - case facebook::react::TextAlignment::Center: - return NSTextAlignmentCenter; - case facebook::react::TextAlignment::Justified: - return NSTextAlignmentJustified; - } -} -inline static NSWritingDirection RCTNSWritingDirectionFromWritingDirection( - facebook::react::WritingDirection writingDirection) -{ - switch (writingDirection) { - case facebook::react::WritingDirection::Natural: - return NSWritingDirectionNatural; - case facebook::react::WritingDirection::LeftToRight: - return NSWritingDirectionLeftToRight; - case facebook::react::WritingDirection::RightToLeft: - return NSWritingDirectionRightToLeft; - } -} -inline static NSLineBreakStrategy RCTNSLineBreakStrategyFromLineBreakStrategy( - facebook::react::LineBreakStrategy lineBreakStrategy) -{ - switch (lineBreakStrategy) { - case facebook::react::LineBreakStrategy::None: - return NSLineBreakStrategyNone; - case facebook::react::LineBreakStrategy::PushOut: - return NSLineBreakStrategyPushOut; - case facebook::react::LineBreakStrategy::HangulWordPriority: - if (@available(iOS 14.0, *)) { - return NSLineBreakStrategyHangulWordPriority; - } else { - return NSLineBreakStrategyNone; - } - case facebook::react::LineBreakStrategy::Standard: - if (@available(iOS 14.0, *)) { - return NSLineBreakStrategyStandard; - } else { - return NSLineBreakStrategyNone; - } - } -} -inline static NSLineBreakMode RCTNSLineBreakModeFromLineBreakMode(facebook::react::LineBreakMode lineBreakMode) +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h}: +NS_ASSUME_NONNULL_BEGIN +NSString *const RCTAttributedStringIsHighlightedAttributeName = @"IsHighlighted"; +NSString *const RCTAttributedStringEventEmitterKey = @"EventEmitter"; +NSString *const RCTTextAttributesAccessibilityRoleAttributeName = @"AccessibilityRole"; +NSMutableDictionary *RCTNSTextAttributesFromTextAttributes( + const facebook::react::TextAttributes &textAttributes); +NSAttributedString *RCTNSAttributedStringFromAttributedString( + const facebook::react::AttributedString &attributedString); +NSAttributedString *RCTNSAttributedStringFromAttributedStringBox( + const facebook::react::AttributedStringBox &attributedStringBox); +facebook::react::AttributedStringBox RCTAttributedStringBoxFromNSAttributedString( + NSAttributedString *nsAttributedString); +NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook::react::TextTransform textTransform); +void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText); +BOOL RCTIsAttributedStringEffectivelySame( + NSAttributedString *text1, + NSAttributedString *text2, + NSDictionary *insensitiveAttributes, + const facebook::react::TextAttributes &baseTextAttributes); +static inline NSData *RCTWrapEventEmitter(const facebook::react::SharedEventEmitter &eventEmitter) { - switch (lineBreakMode) { - case facebook::react::LineBreakMode::Word: - return NSLineBreakByWordWrapping; - case facebook::react::LineBreakMode::Char: - return NSLineBreakByCharWrapping; - case facebook::react::LineBreakMode::Clip: - return NSLineBreakByClipping; - case facebook::react::LineBreakMode::Head: - return NSLineBreakByTruncatingHead; - case facebook::react::LineBreakMode::Middle: - return NSLineBreakByTruncatingMiddle; - case facebook::react::LineBreakMode::Tail: - return NSLineBreakByTruncatingTail; - } -} -inline static RCTFontStyle RCTFontStyleFromFontStyle(facebook::react::FontStyle fontStyle) + auto eventEmitterPtr = new std::weak_ptr(eventEmitter); + return [[NSData alloc] initWithBytesNoCopy:eventEmitterPtr + length:sizeof(eventEmitterPtr) + deallocator:^(void *ptrToDelete, NSUInteger) { + delete (std::weak_ptr *)ptrToDelete; + }]; +} +static inline facebook::react::SharedEventEmitter RCTUnwrapEventEmitter(NSData *data) { - switch (fontStyle) { - case facebook::react::FontStyle::Normal: - return RCTFontStyleNormal; - case facebook::react::FontStyle::Italic: - return RCTFontStyleItalic; - case facebook::react::FontStyle::Oblique: - return RCTFontStyleOblique; + if (data.length == 0) { + return nullptr; } -} -inline static RCTFontVariant RCTFontVariantFromFontVariant(facebook::react::FontVariant fontVariant) -{ - return (RCTFontVariant)fontVariant; -} -inline static NSUnderlineStyle RCTNSUnderlineStyleFromTextDecorationStyle( - facebook::react::TextDecorationStyle textDecorationStyle) -{ - switch (textDecorationStyle) { - case facebook::react::TextDecorationStyle::Solid: - return NSUnderlineStyleSingle; - case facebook::react::TextDecorationStyle::Double: - return NSUnderlineStyleDouble; - case facebook::react::TextDecorationStyle::Dashed: - return NSUnderlinePatternDash | NSUnderlineStyleSingle; - case facebook::react::TextDecorationStyle::Dotted: - return NSUnderlinePatternDot | NSUnderlineStyleSingle; + auto weakPtr = dynamic_cast *>( + (std::weak_ptr *)data.bytes); + if (weakPtr) { + return weakPtr->lock(); } + return nullptr; } -inline static UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::SharedColor &sharedColor) -{ - return RCTPlatformColorFromColor(*sharedColor); -} - -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h} +NS_ASSUME_NONNULL_END -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontProperties.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontProperties.h} +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontProperties.h}: +NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, RCTFontStyle) { + RCTFontStyleUndefined = -1, + RCTFontStyleNormal, + RCTFontStyleItalic, + RCTFontStyleOblique, +}; +typedef NS_OPTIONS(NSInteger, RCTFontVariant) { + RCTFontVariantUndefined = -1, + RCTFontVariantDefault = 0, + RCTFontVariantSmallCaps = 1 << 1, + RCTFontVariantOldstyleNums = 1 << 2, + RCTFontVariantLiningNums = 1 << 3, + RCTFontVariantTabularNums = 1 << 4, + RCTFontVariantProportionalNums = 1 << 5, + RCTFontVariantStylisticOne = 1 << 6, + RCTFontVariantStylisticTwo = 1 << 7, + RCTFontVariantStylisticThree = 1 << 8, + RCTFontVariantStylisticFour = 1 << 9, + RCTFontVariantStylisticFive = 1 << 10, + RCTFontVariantStylisticSix = 1 << 11, + RCTFontVariantStylisticSeven = 1 << 12, + RCTFontVariantStylisticEight = 1 << 13, + RCTFontVariantStylisticNine = 1 << 14, + RCTFontVariantStylisticTen = 1 << 15, + RCTFontVariantStylisticEleven = 1 << 16, + RCTFontVariantStylisticTwelve = 1 << 17, + RCTFontVariantStylisticThirteen = 1 << 18, + RCTFontVariantStylisticFourteen = 1 << 19, + RCTFontVariantStylisticFifteen = 1 << 20, + RCTFontVariantStylisticSixteen = 1 << 21, + RCTFontVariantStylisticSeventeen = 1 << 22, + RCTFontVariantStylisticEighteen = 1 << 23, + RCTFontVariantStylisticNineteen = 1 << 24, + RCTFontVariantStylisticTwenty = 1 << 25, +}; +struct RCTFontProperties { + NSString *family = nil; + CGFloat size = NAN; + UIFontWeight weight = NAN; + RCTFontStyle style = RCTFontStyleUndefined; + RCTFontVariant variant = RCTFontVariantUndefined; + CGFloat sizeMultiplier = NAN; +}; +NS_ASSUME_NONNULL_END -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontUtils.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.h} +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.h}: +/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontUtils.h} -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTTextLayoutManager.h}: -/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h} +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h}: +/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTTextLayoutManager.h} -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h}: +inline static NSTextAlignment RCTNSTextAlignmentFromTextAlignment(facebook::react::TextAlignment textAlignment) +{ + switch (textAlignment) { + case facebook::react::TextAlignment::Natural: + return NSTextAlignmentNatural; + case facebook::react::TextAlignment::Left: + return NSTextAlignmentLeft; + case facebook::react::TextAlignment::Right: + return NSTextAlignmentRight; + case facebook::react::TextAlignment::Center: + return NSTextAlignmentCenter; + case facebook::react::TextAlignment::Justified: + return NSTextAlignmentJustified; + } +} +inline static NSWritingDirection RCTNSWritingDirectionFromWritingDirection( + facebook::react::WritingDirection writingDirection) +{ + switch (writingDirection) { + case facebook::react::WritingDirection::Natural: + return NSWritingDirectionNatural; + case facebook::react::WritingDirection::LeftToRight: + return NSWritingDirectionLeftToRight; + case facebook::react::WritingDirection::RightToLeft: + return NSWritingDirectionRightToLeft; + } +} +inline static NSLineBreakStrategy RCTNSLineBreakStrategyFromLineBreakStrategy( + facebook::react::LineBreakStrategy lineBreakStrategy) +{ + switch (lineBreakStrategy) { + case facebook::react::LineBreakStrategy::None: + return NSLineBreakStrategyNone; + case facebook::react::LineBreakStrategy::PushOut: + return NSLineBreakStrategyPushOut; + case facebook::react::LineBreakStrategy::HangulWordPriority: + if (@available(iOS 14.0, *)) { + return NSLineBreakStrategyHangulWordPriority; + } else { + return NSLineBreakStrategyNone; + } + case facebook::react::LineBreakStrategy::Standard: + if (@available(iOS 14.0, *)) { + return NSLineBreakStrategyStandard; + } else { + return NSLineBreakStrategyNone; + } + } +} +inline static NSLineBreakMode RCTNSLineBreakModeFromLineBreakMode(facebook::react::LineBreakMode lineBreakMode) +{ + switch (lineBreakMode) { + case facebook::react::LineBreakMode::Word: + return NSLineBreakByWordWrapping; + case facebook::react::LineBreakMode::Char: + return NSLineBreakByCharWrapping; + case facebook::react::LineBreakMode::Clip: + return NSLineBreakByClipping; + case facebook::react::LineBreakMode::Head: + return NSLineBreakByTruncatingHead; + case facebook::react::LineBreakMode::Middle: + return NSLineBreakByTruncatingMiddle; + case facebook::react::LineBreakMode::Tail: + return NSLineBreakByTruncatingTail; + } +} +inline static RCTFontStyle RCTFontStyleFromFontStyle(facebook::react::FontStyle fontStyle) +{ + switch (fontStyle) { + case facebook::react::FontStyle::Normal: + return RCTFontStyleNormal; + case facebook::react::FontStyle::Italic: + return RCTFontStyleItalic; + case facebook::react::FontStyle::Oblique: + return RCTFontStyleOblique; + } +} +inline static RCTFontVariant RCTFontVariantFromFontVariant(facebook::react::FontVariant fontVariant) +{ + return (RCTFontVariant)fontVariant; +} +inline static NSUnderlineStyle RCTNSUnderlineStyleFromTextDecorationStyle( + facebook::react::TextDecorationStyle textDecorationStyle) +{ + switch (textDecorationStyle) { + case facebook::react::TextDecorationStyle::Solid: + return NSUnderlineStyleSingle; + case facebook::react::TextDecorationStyle::Double: + return NSUnderlineStyleDouble; + case facebook::react::TextDecorationStyle::Dashed: + return NSUnderlineStylePatternDash | NSUnderlineStyleSingle; + case facebook::react::TextDecorationStyle::Dotted: + return NSUnderlineStylePatternDot | NSUnderlineStyleSingle; + } +} +inline static UIColor *_Nullable RCTUIColorFromSharedColor(const facebook::react::SharedColor &sharedColor) +{ + return RCTPlatformColorFromColor(*sharedColor); +} + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h}: +namespace facebook::react { +class TextLayoutManager { + public: + TextLayoutManager(const ContextContainer::Shared& contextContainer); + TextLayoutManager(const TextLayoutManager&) = delete; + TextLayoutManager& operator=(const TextLayoutManager&) = delete; + TextLayoutManager(TextLayoutManager&&) = delete; + TextLayoutManager& operator=(TextLayoutManager&&) = delete; + TextMeasurement measure( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, + const LayoutConstraints& layoutConstraints) const; + LinesMeasurements measureLines( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const Size& size) const; + std::shared_ptr getNativeTextLayoutManager() const; + + protected: + std::shared_ptr contextContainer_; + std::shared_ptr nativeTextLayoutManager_; + TextMeasureCache textMeasureCache_; + LineMeasureCache lineMeasureCache_; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h}: +NS_ASSUME_NONNULL_BEGIN +NSString *const RCTAttributedStringIsHighlightedAttributeName = @"IsHighlighted"; +NSString *const RCTAttributedStringEventEmitterKey = @"EventEmitter"; +NSString *const RCTTextAttributesAccessibilityRoleAttributeName = @"AccessibilityRole"; +NSMutableDictionary *RCTNSTextAttributesFromTextAttributes( + const facebook::react::TextAttributes &textAttributes); +NSAttributedString *RCTNSAttributedStringFromAttributedString( + const facebook::react::AttributedString &attributedString); +NSAttributedString *RCTNSAttributedStringFromAttributedStringBox( + const facebook::react::AttributedStringBox &attributedStringBox); +facebook::react::AttributedStringBox RCTAttributedStringBoxFromNSAttributedString( + NSAttributedString *nsAttributedString); +NSString *RCTNSStringFromStringApplyingTextTransform(NSString *string, facebook::react::TextTransform textTransform); +void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText); +BOOL RCTIsAttributedStringEffectivelySame( + NSAttributedString *text1, + NSAttributedString *text2, + NSDictionary *insensitiveAttributes, + const facebook::react::TextAttributes &baseTextAttributes); +@interface RCTWeakEventEmitterWrapper : NSObject +@property (nonatomic, assign) facebook::react::SharedEventEmitter eventEmitter; +@end +NS_ASSUME_NONNULL_END + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontProperties.h}: +NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, RCTFontStyle) { + RCTFontStyleUndefined = -1, + RCTFontStyleNormal, + RCTFontStyleItalic, + RCTFontStyleOblique, +}; +typedef NS_OPTIONS(NSInteger, RCTFontVariant) { + RCTFontVariantUndefined = -1, + RCTFontVariantDefault = 0, + RCTFontVariantSmallCaps = 1 << 1, + RCTFontVariantOldstyleNums = 1 << 2, + RCTFontVariantLiningNums = 1 << 3, + RCTFontVariantTabularNums = 1 << 4, + RCTFontVariantProportionalNums = 1 << 5, +}; +struct RCTFontProperties { + NSString *family = nil; + CGFloat size = NAN; + UIFontWeight weight = NAN; + RCTFontStyle style = RCTFontStyleUndefined; + RCTFontVariant variant = RCTFontVariantUndefined; + CGFloat sizeMultiplier = NAN; +}; +NS_ASSUME_NONNULL_END + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTFontUtils.h}: +/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.h} + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTTextLayoutManager.h}: +/// @dep {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h} + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h}: inline static NSTextAlignment RCTNSTextAlignmentFromTextAlignment(facebook::react::TextAlignment textAlignment) { switch (textAlignment) { @@ -32689,16 +37433,15 @@ inline static RCTUIColor *_Nullable RCTUIColorFromSharedColor(const facebook::re return RCTPlatformColorFromColor(*sharedColor); } -/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/windows/third-party/TextLayoutManager.h}: -namespace facebook { -namespace react { -using SharedTextLayoutManager = std::shared_ptr; +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/macos/react/renderer/textlayoutmanager/TextLayoutManager.h}: +namespace facebook::react { class TextLayoutManager { public: - using Shared = std::shared_ptr; - TextLayoutManager(const ContextContainer::Shared& contextContainer) - : m_contextContainer(contextContainer) {}; - ~TextLayoutManager() = default; + TextLayoutManager(const ContextContainer::Shared& contextContainer); + TextLayoutManager(const TextLayoutManager&) = delete; + TextLayoutManager& operator=(const TextLayoutManager&) = delete; + TextLayoutManager(TextLayoutManager&&) = delete; + TextLayoutManager& operator=(TextLayoutManager&&) = delete; TextMeasurement measure( const AttributedStringBox& attributedStringBox, const ParagraphAttributes& paragraphAttributes, @@ -32708,15 +37451,71 @@ class TextLayoutManager { const AttributedStringBox& attributedStringBox, const ParagraphAttributes& paragraphAttributes, const Size& size) const; - Float baseline( + std::shared_ptr getNativeTextLayoutManager() const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/windows/third-party/TextLayoutManager.h}: +namespace facebook::react { +class TextLayoutManager { + public: + TextLayoutManager(const ContextContainer::Shared& contextContainer); + TextLayoutManager(const TextLayoutManager&) = delete; + TextLayoutManager& operator=(const TextLayoutManager&) = delete; + TextLayoutManager(TextLayoutManager&&) = delete; + TextLayoutManager& operator=(TextLayoutManager&&) = delete; + TextMeasurement measure( const AttributedStringBox& attributedStringBox, const ParagraphAttributes& paragraphAttributes, - const Size& size) const; - TextMeasurement measureCachedSpannableById( - int64_t cacheId, - const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const; - void* getNativeTextLayoutManager() const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/windows/third-party/TextLayoutUtil.h}: +namespace facebook::react { +class TextLayoutInlineObject : public Mso::UnknownObject { + public: + TextLayoutInlineObject(Float inWidth, Float inHeight) + : width{inWidth}, height{inHeight} {} + HRESULT Draw( + void* clientDrawingContext, + IDWriteTextRenderer* renderer, + FLOAT originX, + FLOAT originY, + BOOL isSideways, + BOOL isRightToLeft, + IUnknown* clientDrawingEffect) noexcept override { + return S_OK; + } + HRESULT GetBreakConditions( + DWRITE_BREAK_CONDITION* breakConditionBefore, + DWRITE_BREAK_CONDITION* breakConditionAfter) noexcept override { + *breakConditionBefore = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK; + *breakConditionAfter = DWRITE_BREAK_CONDITION_MAY_NOT_BREAK; + return S_OK; + } + HRESULT GetMetrics(DWRITE_INLINE_OBJECT_METRICS* metrics) noexcept override { + metrics->width = width; + metrics->height = height; + metrics->baseline = height; + metrics->supportsSideways = false; + return S_OK; + } + HRESULT GetOverhangMetrics( + DWRITE_OVERHANG_METRICS* overhangs) noexcept override { + *overhangs = DWRITE_OVERHANG_METRICS{}; + return S_OK; + } + facebook::react::Float width{}; + facebook::react::Float height{}; +}; +struct AttachmentItem { + Mso::CntPtr inlineObject; + uint32_t position; +}; +class TextLayoutUtil { + public: static void GetTextLayout( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, @@ -32732,10 +37531,28 @@ class TextLayoutManager { static Microsoft::ReactNative::TextTransform ConvertTextTransform( const std::optional& transform) noexcept; }; -#pragma warning(pop) +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/renderer/uimanager/AppRegistryBinding.h}: +namespace facebook::react { +class AppRegistryBinding final { + public: + AppRegistryBinding() = delete; + static void startSurface( + jsi::Runtime& runtime, + SurfaceId surfaceId, + const std::string& moduleName, + const folly::dynamic& initialProps, + DisplayMode displayMode); + static void setSurfaceProps( + jsi::Runtime& runtime, + SurfaceId surfaceId, + const std::string& moduleName, + const folly::dynamic& initialProps, + DisplayMode displayMode); + static void stopSurface(jsi::Runtime& runtime, SurfaceId surfaceId); }; -} // namespace react -} // namespace facebook +} // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/uimanager/LayoutAnimationStatusDelegate.h}: namespace facebook::react { @@ -32764,7 +37581,7 @@ using DispatchEvent = std::function; using PointerIdentifier = int32_t; using CaptureTargetOverrideRegistry = - std::unordered_map; + std::unordered_map>; using ActivePointerRegistry = std::unordered_map; using PointerHoverTrackerRegistry = @@ -32813,25 +37630,7 @@ class PointerHoverTracker { } // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/uimanager/SurfaceRegistryBinding.h}: -namespace facebook::react { -class SurfaceRegistryBinding final { - public: - SurfaceRegistryBinding() = delete; - static void startSurface( - jsi::Runtime& runtime, - SurfaceId surfaceId, - const std::string& moduleName, - const folly::dynamic& initialProps, - DisplayMode displayMode); - static void setSurfaceProps( - jsi::Runtime& runtime, - SurfaceId surfaceId, - const std::string& moduleName, - const folly::dynamic& initialProps, - DisplayMode displayMode); - static void stopSurface(jsi::Runtime& runtime, SurfaceId surfaceId); -}; -} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h}: namespace facebook::react { @@ -32847,7 +37646,10 @@ class UIManager final : public ShadowTreeDelegate { UIManagerDelegate* getDelegate(); void setAnimationDelegate(UIManagerAnimationDelegate* delegate); void stopSurfaceForAnimationDelegate(SurfaceId surfaceId) const; + void setNativeAnimatedDelegate( + std::weak_ptr delegate); void animationTick() const; + void synchronouslyUpdateViewOnUIThread(Tag tag, const folly::dynamic& props); void visitBinding( const std::function& callback, @@ -32865,13 +37667,13 @@ class UIManager final : public ShadowTreeDelegate { ShadowTree::Unique&& shadowTree, const std::string& moduleName, const folly::dynamic& props, - DisplayMode displayMode) const; - void startEmptySurface(ShadowTree::Unique&& shadowTree) const; + DisplayMode displayMode) const noexcept; + void startEmptySurface(ShadowTree::Unique&& shadowTree) const noexcept; void setSurfaceProps( SurfaceId surfaceId, const std::string& moduleName, const folly::dynamic& props, - DisplayMode displayMode) const; + DisplayMode displayMode) const noexcept; ShadowTree::Unique stopSurface(SurfaceId surfaceId) const; void shadowTreeDidFinishTransaction( std::shared_ptr mountingCoordinator, @@ -32879,7 +37681,8 @@ class UIManager final : public ShadowTreeDelegate { RootShadowNode::Unshared shadowTreeWillCommit( const ShadowTree& shadowTree, const RootShadowNode::Shared& oldRootShadowNode, - const RootShadowNode::Unshared& newRootShadowNode) const override; + const RootShadowNode::Unshared& newRootShadowNode, + const ShadowTree::CommitOptions& commitOptions) const override; std::shared_ptr createNode( Tag tag, const std::string& componentName, @@ -32922,8 +37725,16 @@ class UIManager final : public ShadowTreeDelegate { ShadowNode::Shared findShadowNodeByTag_DEPRECATED(Tag tag) const; const ShadowTreeRegistry& getShadowTreeRegistry() const; void reportMount(SurfaceId surfaceId) const; + void updateShadowTree( + const std::unordered_map& tagToProps); + void addEventListener(std::shared_ptr listener); + void removeEventListener( + const std::shared_ptr& listener); + void setOnSurfaceStartCallback( + UIManagerDelegate::OnSurfaceStartCallback&& callback); }; UIManagerAnimationDelegate* animationDelegate_{nullptr}; + std::weak_ptr nativeAnimatedDelegate_; const RuntimeExecutor runtimeExecutor_{}; ShadowTreeRegistry shadowTreeRegistry_{}; ContextContainer::Shared contextContainer_; @@ -32964,9 +37775,6 @@ class UIManagerBinding : public jsi::HostObject { static std::shared_ptr getBinding(jsi::Runtime& runtime); UIManagerBinding(std::shared_ptr uiManager); ~UIManagerBinding() override; - jsi::Value getInspectorDataForInstance( - jsi::Runtime& runtime, - const EventEmitter& eventEmitter) const; void dispatchEvent( jsi::Runtime& runtime, const EventTarget* eventTarget, @@ -32990,7 +37798,17 @@ class UIManagerCommitHook { virtual RootShadowNode::Unshared shadowTreeWillCommit( const ShadowTree& shadowTree, const RootShadowNode::Shared& oldRootShadowNode, - const RootShadowNode::Unshared& newRootShadowNode) noexcept = 0; + const RootShadowNode::Unshared& newRootShadowNode, + const ShadowTreeCommitOptions&) noexcept { + return shadowTreeWillCommit( + shadowTree, oldRootShadowNode, newRootShadowNode); + } + virtual RootShadowNode::Unshared shadowTreeWillCommit( + const ShadowTree&, + const RootShadowNode::Shared&, + const RootShadowNode::Unshared& newRootShadowNode) noexcept { + return newRootShadowNode; + } virtual ~UIManagerCommitHook() noexcept = default; }; } // namespace facebook::react @@ -33014,6 +37832,18 @@ class UIManagerDelegate { const ShadowNode::Shared& shadowNode, bool isJSResponder, bool blockNativeResponder) = 0; + virtual void uiManagerShouldSynchronouslyUpdateViewOnUIThread( + Tag tag, + const folly::dynamic& props) = 0; + virtual void uiManagerShouldAddEventListener( + std::shared_ptr listener) = 0; + virtual void uiManagerShouldRemoveEventListener( + const std::shared_ptr& listener) = 0; + virtual void uiManagerDidStartSurface(const ShadowTree& shadowTree) = 0; + using OnSurfaceStartCallback = + std::function; + virtual void uiManagerShouldSetOnSurfaceStartCallback( + OnSurfaceStartCallback&& callback) = 0; virtual ~UIManagerDelegate() noexcept = default; }; } // namespace facebook::react @@ -33026,20 +37856,20 @@ class UIManagerMountHook { public: virtual void shadowTreeDidMount( const RootShadowNode::Shared& rootShadowNode, - double mountTime) noexcept = 0; - virtual void shadowTreeDidUnmount(SurfaceId, double) noexcept {} + HighResTimeStamp mountTime) noexcept = 0; + virtual void shadowTreeDidUnmount(SurfaceId, HighResTimeStamp) noexcept {} virtual ~UIManagerMountHook() noexcept = default; }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/renderer/uimanager/bindingUtils.h}: +/// @src {packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerNativeAnimatedDelegate.h}: namespace facebook::react { -jsi::Value callMethodOfModule( - jsi::Runtime& runtime, - const std::string& moduleName, - const std::string& methodName, - std::initializer_list args); -} +class UIManagerNativeAnimatedDelegate { + public: + virtual ~UIManagerNativeAnimatedDelegate() = default; + virtual void runAnimationFrame() = 0; +}; +} // namespace facebook::react /// @src {packages/react-native/ReactCommon/react/renderer/uimanager/consistency/LazyShadowTreeRevisionConsistencyManager.h}: namespace facebook::react { @@ -33078,16 +37908,6 @@ struct ShadowNodeListWrapper : public jsi::NativeState { ~ShadowNodeListWrapper() override; ShadowNode::UnsharedListOfShared shadowNodeList; }; -inline static ShadowNode::Shared shadowNodeFromValue( - jsi::Runtime& runtime, - const jsi::Value& value) { - if (value.isNull()) { - return nullptr; - } - return value.getObject(runtime) - .getNativeState(runtime) - ->shadowNode; -} inline static jsi::Value valueFromShadowNode( jsi::Runtime& runtime, ShadowNode::Shared shadowNode, @@ -33113,8 +37933,8 @@ inline static ShadowNode::UnsharedListOfShared shadowNodeListFromValue( auto shadowNodeArray = std::make_shared(); shadowNodeArray->reserve(jsArrayLen); for (size_t i = 0; i < jsArrayLen; i++) { - shadowNodeArray->push_back( - shadowNodeFromValue(runtime, jsArray.getValueAtIndex(runtime, i))); + shadowNodeArray->push_back(Bridging::fromJs( + runtime, jsArray.getValueAtIndex(runtime, i))); } return shadowNodeArray; } else { @@ -33185,6 +38005,9 @@ inline static int displayModeToInt(const DisplayMode value) { return 2; case DisplayMode::Hidden: return 3; + default: + react_native_assert(0 && "displayModeToInt: Invalid DisplayMode"); + return -1; } } inline static std::string stringFromValue( @@ -33241,28 +38064,6 @@ class BufferedRuntimeExecutor { }; } // namespace facebook::react -/// @src {packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h}: -namespace facebook::react { -class JSRuntime { - public: - virtual jsi::Runtime& getRuntime() noexcept = 0; - virtual ~JSRuntime() = default; - virtual jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate(); - virtual void unstable_initializeOnJsThread() {} -}; -class JSRuntimeFactory { - public: - virtual std::unique_ptr createJSRuntime( - std::shared_ptr msgQueueThread) noexcept = 0; - virtual ~JSRuntimeFactory() = default; -}; -class JSIRuntimeHolder : public JSRuntime { - public: - jsi::Runtime& getRuntime() noexcept override; - explicit JSIRuntimeHolder(std::unique_ptr runtime); -}; -} // namespace facebook::react - /// @src {packages/react-native/ReactCommon/react/runtime/PlatformTimerRegistry.h}: namespace facebook::react { class PlatformTimerRegistry { @@ -33299,7 +38100,8 @@ class ReactInstance final : private jsinspector_modern::InstanceTargetDelegate { void loadScript( std::unique_ptr script, const std::string& sourceURL, - std::function&& completion = nullptr); + std::function&& beforeLoad = nullptr, + std::function&& afterLoad = nullptr); void registerSegment(uint32_t segmentId, const std::string& segmentPath); void callFunctionOnModule( const std::string& moduleName, @@ -33383,7 +38185,9 @@ void install( /// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/ObjCTimerRegistry.h} /// @src {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTContextContainerHandling.h}: -/// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTContextContainerHandling.h} +@protocol RCTContextContainerHandling +- (void)didCreateContextContainer:(std::shared_ptr)contextContainer; +@end /// @src {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h}: /// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTHermesInstance.h} @@ -33399,6 +38203,7 @@ RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *_Nullable flags); - (void)loadBundleAtURL:(NSURL *)sourceURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)loadCallback; +- (NSArray *)unstableModulesRequiringMainQueueSetup; - (BOOL)instance:(RCTInstance *)instance didReceiveJSErrorStack:(NSArray *> *)stack message:(NSString *)message @@ -33430,6 +38235,7 @@ typedef NSURL *_Nullable (^RCTHostBundleURLProvider)(void); @protocol RCTHostDelegate - (void)hostDidStart:(RCTHost *)host; @optional +- (NSArray *)unstableModulesRequiringMainQueueSetup; - (void)loadBundleAtURL:(NSURL *)sourceURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)loadCallback; @@ -33490,6 +38296,7 @@ RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *_Nullable flags); - (void)loadBundleAtURL:(NSURL *)sourceURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)loadCallback; +- (NSArray *)unstableModulesRequiringMainQueueSetup; - (BOOL)instance:(RCTInstance *)instance didReceiveJSErrorStack:(NSArray *> *)stack message:(NSString *)message @@ -33521,6 +38328,7 @@ typedef NSURL *_Nullable (^RCTHostBundleURLProvider)(void); @protocol RCTHostDelegate - (void)hostDidStart:(RCTHost *)host; @optional +- (NSArray *)unstableModulesRequiringMainQueueSetup; - (void)loadBundleAtURL:(NSURL *)sourceURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)loadCallback; @@ -33574,6 +38382,7 @@ RCT_EXTERN void RCTInstanceSetRuntimeDiagnosticFlags(NSString *_Nullable flags); - (void)loadBundleAtURL:(NSURL *)sourceURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)loadCallback; +- (NSArray *)unstableModulesRequiringMainQueueSetup; - (BOOL)instance:(RCTInstance *)instance didReceiveJSErrorStack:(NSArray *> *)stack message:(NSString *)message @@ -33612,17 +38421,37 @@ NS_ASSUME_NONNULL_END /// @src {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTPerformanceLoggerUtils.h}: /// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTPerformanceLoggerUtils.h} +/// @src {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/metainternal/RCTJermesInstance.h}: +namespace facebook::react { +using CrashManagerProvider = + std::function()>; +class RCTJermesInstance : public JSRuntimeFactory { + public: + RCTJermesInstance(); + RCTJermesInstance(CrashManagerProvider crashManagerProvider); + RCTJermesInstance( + CrashManagerProvider crashManagerProvider, + bool allocInOldGenBeforeTTI); + std::unique_ptr createJSRuntime( + std::shared_ptr msgQueueThread) noexcept override; + ~RCTJermesInstance() override {}; +}; +} // namespace facebook::react + /// @src {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/ObjCTimerRegistry.h}: /// @dep {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/ObjCTimerRegistry.h} /// @src {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTContextContainerHandling.h}: -/// @dep {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTContextContainerHandling.h} +@protocol RCTContextContainerHandling +@optional +- (void)didCreateContextContainer:(std::shared_ptr)contextContainer; +@end /// @src {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTHermesInstance.h}: /// @dep {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHermesInstance.h} /// @src {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTHost+Internal.h}: -/// @dep {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTContextContainerHandling.h} +/// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTContextContainerHandling.h} NS_ASSUME_NONNULL_BEGIN RCT_EXTERN NSString *RCTInstanceRuntimeDiagnosticFlags(void); @@ -33713,7 +38542,7 @@ NS_ASSUME_NONNULL_END @end /// @src {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTHost.h}: -/// @dep {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTContextContainerHandling.h} +/// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTContextContainerHandling.h} NS_ASSUME_NONNULL_BEGIN RCT_EXTERN NSString *RCTInstanceRuntimeDiagnosticFlags(void); @@ -33797,7 +38626,7 @@ typedef std::shared_ptr (^RCTHostJSEngineProv NS_ASSUME_NONNULL_END /// @src {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTInstance.h}: -/// @dep {packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTContextContainerHandling.h} +/// @dep {packages/react-native/ReactCommon/react/runtime/platform/macos/ReactCommon/RCTContextContainerHandling.h} NS_ASSUME_NONNULL_BEGIN RCT_EXTERN NSString *RCTInstanceRuntimeDiagnosticFlags(void); @@ -33873,19 +38702,232 @@ RCT_EXTERN_C_END /// @src {packages/react-native/ReactCommon/react/timing/primitives.h}: namespace facebook::react { -using DOMHighResTimeStamp = double; -constexpr DOMHighResTimeStamp DOM_HIGH_RES_TIME_STAMP_UNSET = -1.0; -inline DOMHighResTimeStamp chronoToDOMHighResTimeStamp( - std::chrono::steady_clock::duration duration) { - return static_cast>(duration) - .count(); +class HighResDuration { + friend + friend constexpr HighResDuration operator-( + const HighResTimeStamp& lhs, + const HighResTimeStamp& rhs); + friend constexpr HighResTimeStamp operator+( + const HighResTimeStamp& lhs, + const HighResDuration& rhs); + friend constexpr HighResTimeStamp operator-( + const HighResTimeStamp& lhs, + const HighResDuration& rhs); + + public: + constexpr HighResDuration() + : chronoDuration_(std::chrono::steady_clock::duration()) {} + static constexpr HighResDuration zero() { + return HighResDuration(std::chrono::steady_clock::duration::zero()); + } + static constexpr HighResDuration fromChrono( + std::chrono::steady_clock::duration chronoDuration) { + return HighResDuration(chronoDuration); + } + static constexpr HighResDuration fromNanoseconds(int64_t units) { + return HighResDuration(std::chrono::nanoseconds(units)); + } + static constexpr HighResDuration fromMilliseconds(int64_t units) { + return HighResDuration(std::chrono::milliseconds(units)); + } + constexpr int64_t toNanoseconds() const { + return std::chrono::duration_cast(chronoDuration_) + .count(); + } + static constexpr HighResDuration fromDOMHighResTimeStamp(double units) { + auto nanoseconds = static_cast(units * 1e6); + return fromNanoseconds(nanoseconds); + } + constexpr double toDOMHighResTimeStamp() const { + return static_cast>( + chronoDuration_) + .count(); + } + constexpr HighResDuration operator+(const HighResDuration& rhs) const { + return HighResDuration(chronoDuration_ + rhs.chronoDuration_); + } + constexpr HighResDuration operator+( + const std::chrono::steady_clock::duration& rhs) const { + return HighResDuration(chronoDuration_ + rhs); + } + constexpr HighResDuration operator-(const HighResDuration& rhs) const { + return HighResDuration(chronoDuration_ - rhs.chronoDuration_); + } + constexpr HighResDuration operator-( + const std::chrono::steady_clock::duration& rhs) const { + return HighResDuration(chronoDuration_ - rhs); + } + constexpr HighResDuration& operator+=(const HighResDuration& rhs) { + chronoDuration_ += rhs.chronoDuration_; + return *this; + } + constexpr HighResDuration& operator+=( + const std::chrono::steady_clock::duration& rhs) { + chronoDuration_ += rhs; + return *this; + } + constexpr HighResDuration& operator-=(const HighResDuration& rhs) { + chronoDuration_ -= rhs.chronoDuration_; + return *this; + } + constexpr HighResDuration& operator-=( + const std::chrono::steady_clock::duration& rhs) { + chronoDuration_ -= rhs; + return *this; + } + constexpr bool operator==(const HighResDuration& rhs) const { + return chronoDuration_ == rhs.chronoDuration_; + } + constexpr bool operator==( + const std::chrono::steady_clock::duration& rhs) const { + return chronoDuration_ == rhs; + } + constexpr bool operator!=(const HighResDuration& rhs) const { + return chronoDuration_ != rhs.chronoDuration_; + } + constexpr bool operator!=( + const std::chrono::steady_clock::duration& rhs) const { + return chronoDuration_ != rhs; + } + constexpr bool operator<(const HighResDuration& rhs) const { + return chronoDuration_ < rhs.chronoDuration_; + } + constexpr bool operator<( + const std::chrono::steady_clock::duration& rhs) const { + return chronoDuration_ < rhs; + } + constexpr bool operator<=(const HighResDuration& rhs) const { + return chronoDuration_ <= rhs.chronoDuration_; + } + constexpr bool operator<=( + const std::chrono::steady_clock::duration& rhs) const { + return chronoDuration_ <= rhs; + } + constexpr bool operator>(const HighResDuration& rhs) const { + return chronoDuration_ > rhs.chronoDuration_; + } + constexpr bool operator>( + const std::chrono::steady_clock::duration& rhs) const { + return chronoDuration_ > rhs; + } + constexpr bool operator>=(const HighResDuration& rhs) const { + return chronoDuration_ >= rhs.chronoDuration_; + } + constexpr bool operator>=( + const std::chrono::steady_clock::duration& rhs) const { + return chronoDuration_ >= rhs; + } + constexpr operator std::chrono::steady_clock::duration() const { + return chronoDuration_; + } +}; +class HighResTimeStamp { + friend constexpr HighResDuration operator-( + const HighResTimeStamp& lhs, + const HighResTimeStamp& rhs); + friend constexpr HighResTimeStamp operator+( + const HighResTimeStamp& lhs, + const HighResDuration& rhs); + friend constexpr HighResTimeStamp operator-( + const HighResTimeStamp& lhs, + const HighResDuration& rhs); + + public: + HighResTimeStamp() noexcept + : chronoTimePoint_(std::chrono::steady_clock::now()) {} + static constexpr HighResTimeStamp now() noexcept { + return HighResTimeStamp(std::chrono::steady_clock::now()); + } + static constexpr HighResTimeStamp min() noexcept { + return HighResTimeStamp(std::chrono::steady_clock::time_point::min()); + } + static constexpr HighResTimeStamp max() noexcept { + return HighResTimeStamp(std::chrono::steady_clock::time_point::max()); + } + static constexpr HighResTimeStamp fromDOMHighResTimeStamp(double units) { + auto nanoseconds = static_cast(units * 1e6); + return HighResTimeStamp(std::chrono::steady_clock::time_point( + std::chrono::nanoseconds(nanoseconds))); + } + constexpr double toDOMHighResTimeStamp() const { + return HighResDuration(chronoTimePoint_.time_since_epoch()) + .toDOMHighResTimeStamp(); + } + static constexpr HighResTimeStamp fromChronoSteadyClockTimePoint( + std::chrono::steady_clock::time_point chronoTimePoint) { + return HighResTimeStamp(chronoTimePoint); + } + constexpr std::chrono::steady_clock::time_point toChronoSteadyClockTimePoint() + const { + return chronoTimePoint_; + } + constexpr bool operator==(const HighResTimeStamp& rhs) const { + return chronoTimePoint_ == rhs.chronoTimePoint_; + } + constexpr bool operator!=(const HighResTimeStamp& rhs) const { + return chronoTimePoint_ != rhs.chronoTimePoint_; + } + constexpr bool operator<(const HighResTimeStamp& rhs) const { + return chronoTimePoint_ < rhs.chronoTimePoint_; + } + constexpr bool operator<=(const HighResTimeStamp& rhs) const { + return chronoTimePoint_ <= rhs.chronoTimePoint_; + } + constexpr bool operator>(const HighResTimeStamp& rhs) const { + return chronoTimePoint_ > rhs.chronoTimePoint_; + } + constexpr bool operator>=(const HighResTimeStamp& rhs) const { + return chronoTimePoint_ >= rhs.chronoTimePoint_; + } + constexpr HighResTimeStamp& operator+=(const HighResDuration& rhs) { + chronoTimePoint_ += rhs.chronoDuration_; + return *this; + } + constexpr HighResTimeStamp& operator-=(const HighResDuration& rhs) { + chronoTimePoint_ -= rhs.chronoDuration_; + return *this; + } +}; +inline constexpr HighResDuration operator-( + const HighResTimeStamp& lhs, + const HighResTimeStamp& rhs) { + return HighResDuration(lhs.chronoTimePoint_ - rhs.chronoTimePoint_); +} +inline constexpr HighResTimeStamp operator+( + const HighResTimeStamp& lhs, + const HighResDuration& rhs) { + return HighResTimeStamp(lhs.chronoTimePoint_ + rhs.chronoDuration_); } -inline DOMHighResTimeStamp chronoToDOMHighResTimeStamp( - std::chrono::steady_clock::time_point timePoint) { - return chronoToDOMHighResTimeStamp(timePoint.time_since_epoch()); +inline constexpr HighResTimeStamp operator-( + const HighResTimeStamp& lhs, + const HighResDuration& rhs) { + return HighResTimeStamp(lhs.chronoTimePoint_ - rhs.chronoDuration_); } } // namespace facebook::react +/// @src {packages/react-native/ReactCommon/react/utils/platform/android/react/utils/LowPriorityExecutor.h}: +/// @dep {packages/react-native/ReactCommon/react/utils/platform/ios/react/utils/LowPriorityExecutor.h} + +/// @src {packages/react-native/ReactCommon/react/utils/platform/cxx/react/utils/LowPriorityExecutor.h}: +namespace facebook::react::LowPriorityExecutor { +inline void execute(std::function&& workItem) { + workItem(); +} +} // namespace facebook::react::LowPriorityExecutor + +/// @src {packages/react-native/ReactCommon/react/utils/platform/ios/react/utils/FollyConvert.h}: +namespace facebook::react { +folly::dynamic convertIdToFollyDynamic(id json); +id convertFollyDynamicToId(const folly::dynamic &dyn); +NSArray *extractKeysFromFollyDynamic(const folly::dynamic &dyn); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/react/utils/platform/ios/react/utils/LowPriorityExecutor.h}: +/// @dep {packages/react-native/ReactCommon/react/utils/platform/android/react/utils/LowPriorityExecutor.h} + +/// @src {packages/react-native/ReactCommon/react/utils/platform/windows/third-party/react/utils/LowPriorityExecutor.h}: +/// @dep {packages/react-native/ReactCommon/react/utils/platform/android/react/utils/LowPriorityExecutor.h} + /// @src {packages/react-native/ReactCommon/reactperflogger/fusebox/FuseboxTracer.h}: namespace facebook::react { struct BufferEvent { @@ -34102,14 +39144,15 @@ class NativeModulePerfLogger { namespace facebook::react { class ReactPerfettoLogger { public: + static bool isTracing(); static void mark( const std::string_view& eventName, - double startTime, + HighResTimeStamp startTime, const std::optional& trackName); static void measure( const std::string_view& eventName, - double startTime, - double endTime, + HighResTimeStamp startTime, + HighResTimeStamp endTime, const std::optional& trackName); }; } // namespace facebook::react @@ -34118,43 +39161,41 @@ class ReactPerfettoLogger { namespace facebook::react { using RuntimeExecutor = std::function&& callback)>; -inline static void executeSynchronouslyOnSameThread_CAN_DEADLOCK( +} + +/// @src {packages/react-native/ReactCommon/runtimeexecutor/platform/cxx/ReactCommon/RuntimeExecutorSyncUIThreadUtils.h}: +namespace facebook::react { +void executeSynchronouslyOnSameThread_CAN_DEADLOCK( const RuntimeExecutor& runtimeExecutor, - std::function&& callback) noexcept { - std::mutex mutex1; - std::mutex mutex2; - std::mutex mutex3; - mutex1.lock(); - mutex2.lock(); - mutex3.lock(); - jsi::Runtime* runtimePtr; - auto threadId = std::this_thread::get_id(); - runtimeExecutor([&](jsi::Runtime& runtime) { - runtimePtr = &runtime; - if (threadId == std::this_thread::get_id()) { - mutex1.unlock(); - mutex3.unlock(); - return; - } - mutex1.unlock(); - mutex2.lock(); - mutex3.unlock(); - }); - mutex1.lock(); - callback(*runtimePtr); - mutex2.unlock(); - mutex3.lock(); + std::function&& runtimeWork); +template +inline static DataT executeSynchronouslyOnSameThread_CAN_DEADLOCK( + const RuntimeExecutor& runtimeExecutor, + std::function&& runtimeWork) { + DataT data; + executeSynchronouslyOnSameThread_CAN_DEADLOCK( + runtimeExecutor, + [&](jsi::Runtime& runtime) { data = runtimeWork(runtime); }); + return data; } +} // namespace facebook::react + +/// @src {packages/react-native/ReactCommon/runtimeexecutor/platform/ios/ReactCommon/RuntimeExecutorSyncUIThreadUtils.h}: +namespace facebook::react { +void executeSynchronouslyOnSameThread_CAN_DEADLOCK( + const RuntimeExecutor& runtimeExecutor, + std::function&& runtimeWork); template inline static DataT executeSynchronouslyOnSameThread_CAN_DEADLOCK( const RuntimeExecutor& runtimeExecutor, - std::function&& callback) noexcept { + std::function&& runtimeWork) { DataT data; executeSynchronouslyOnSameThread_CAN_DEADLOCK( runtimeExecutor, - [&](jsi::Runtime& runtime) { data = callback(runtime); }); + [&](jsi::Runtime& runtime) { data = runtimeWork(runtime); }); return data; } +void unsafeExecuteOnMainThreadSync(std::function work); } // namespace facebook::react /// @src {packages/react-native/ReactCommon/yoga/yoga/YGConfig.h}: @@ -34382,6 +39423,8 @@ YG_EXPORT bool YGNodeLayoutGetHadOverflow(YGNodeConstRef node); YG_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge); YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge); YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge); +YG_EXPORT float YGNodeLayoutGetRawHeight(YGNodeConstRef node); +YG_EXPORT float YGNodeLayoutGetRawWidth(YGNodeConstRef node); YG_EXTERN_C_END /// @src {packages/react-native/ReactCommon/yoga/yoga/YGNodeStyle.h}: @@ -35461,12 +40504,12 @@ enum struct LayoutPassReason : int { COUNT }; struct LayoutData { - int layouts; - int measures; - uint32_t maxMeasureCache; - int cachedLayouts; - int cachedMeasures; - int measureCallbacks; + int layouts = 0; + int measures = 0; + uint32_t maxMeasureCache = 0; + int cachedLayouts = 0; + int cachedMeasures = 0; + int measureCallbacks = 0; std::array(LayoutPassReason::COUNT)> measureCallbackReasonsCount; }; @@ -35599,9 +40642,15 @@ struct LayoutResults { float measuredDimension(Dimension axis) const { return measuredDimensions_[yoga::to_underlying(axis)]; } + float rawDimension(Dimension axis) const { + return rawDimensions_[yoga::to_underlying(axis)]; + } void setMeasuredDimension(Dimension axis, float dimension) { measuredDimensions_[yoga::to_underlying(axis)] = dimension; } + void setRawDimension(Dimension axis, float dimension) { + rawDimensions_[yoga::to_underlying(axis)] = dimension; + } float position(PhysicalEdge physicalEdge) const { return position_[yoga::to_underlying(physicalEdge)]; } @@ -35632,6 +40681,7 @@ struct LayoutResults { } }; std::array measuredDimensions_ = {{YGUndefined, YGUndefined}}; + std::array rawDimensions_ = {{YGUndefined, YGUndefined}}; std::array position_ = {}; std::array margin_ = {}; std::array border_ = {}; @@ -36893,3 +41943,2325 @@ class StyleValuePool { } }; } // namespace facebook::yoga + +/// @src {packages/react-native/ReactCxxPlatform/react/coremodules/AppStateModule.h}: +namespace facebook::react { +using AppStateConstants = NativeAppStateAppStateConstants; +template <> +struct Bridging + : NativeAppStateAppStateConstantsBridging {}; +using AppState = NativeAppStateAppState; +template <> +struct Bridging : NativeAppStateAppStateBridging {}; +class AppStateModule : public NativeAppStateCxxSpec { + public: + explicit AppStateModule(std::shared_ptr jsInvoker) + : NativeAppStateCxxSpec(jsInvoker) {} + AppStateConstants getConstants(jsi::Runtime& rt); + void getCurrentAppState( + jsi::Runtime& rt, + const AsyncCallback& success, + jsi::Function error); + void addListener(jsi::Runtime& rt, const std::string& eventName); + void removeListeners(jsi::Runtime& rt, double count); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/coremodules/DeviceInfoModule.h}: +namespace facebook::react { +using DisplayMetrics = + NativeDeviceInfoDisplayMetrics; +using DisplayMetricsAndroid = NativeDeviceInfoDisplayMetricsAndroid< + double, + double, + double, + double, + double>; +using DimensionsPayload = NativeDeviceInfoDimensionsPayload< + std::optional, + std::optional, + std::optional, + std::optional>; +using DeviceInfoConstants = + NativeDeviceInfoDeviceInfoConstants>; +template <> +struct Bridging + : NativeDeviceInfoDisplayMetricsBridging {}; +template <> +struct Bridging + : NativeDeviceInfoDisplayMetricsAndroidBridging {}; +template <> +struct Bridging + : NativeDeviceInfoDimensionsPayloadBridging {}; +template <> +struct Bridging + : NativeDeviceInfoDeviceInfoConstantsBridging {}; +class DeviceInfoModule : public NativeDeviceInfoCxxSpec { + public: + explicit DeviceInfoModule(std::shared_ptr jsInvoker) + : NativeDeviceInfoCxxSpec(jsInvoker) {} + DeviceInfoConstants getConstants(jsi::Runtime& rt); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/coremodules/PlatformConstantsModule.h}: +namespace facebook::react { +using ReactNativeVersionAndroid = + NativePlatformConstantsAndroidReactNativeVersionAndroid< + int, + int, + int, + std::optional>; +template <> +struct Bridging + : NativePlatformConstantsAndroidReactNativeVersionAndroidBridging< + ReactNativeVersionAndroid> {}; +using PlatformConstantsAndroid = + NativePlatformConstantsAndroidPlatformConstantsAndroid< + bool, + std::optional, + ReactNativeVersionAndroid, + int, + std::string, + std::string, + std::string, + std::string, + std::optional, + std::string, + std::string, + std::string>; +template <> +struct Bridging + : NativePlatformConstantsAndroidPlatformConstantsAndroidBridging< + PlatformConstantsAndroid> {}; +class PlatformConstantsModule + : public NativePlatformConstantsAndroidCxxSpec { + public: + explicit PlatformConstantsModule(std::shared_ptr jsInvoker) + : NativePlatformConstantsAndroidCxxSpec(jsInvoker) {} + std::string getAndroidID(jsi::Runtime&) { + return ""; + } + PlatformConstantsAndroid getConstants(jsi::Runtime& rt); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/DevLoadingViewModule.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/devsupport/IDevUIDelegate.h} +namespace facebook::react { +class DevLoadingViewModule + : public NativeDevLoadingViewCxxSpec { + public: + DevLoadingViewModule( + std::shared_ptr jsInvoker, + std::weak_ptr devUIDelegate); + ~DevLoadingViewModule() override; + void showMessage( + jsi::Runtime& rt, + const std::string& message, + std::optional textColor, + std::optional backgroundColor); + void hide(jsi::Runtime& rt); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/DevServerHelper.h}: +namespace facebook::react { +namespace { +constexpr std::string_view DEFAULT_DEV_SERVER_HOST = "localhost"; +constexpr uint32_t DEFAULT_DEV_SERVER_PORT = 8081; +} // namespace +class DevServerHelper { + public: + enum class DownloadProgressStatus : short { STARTED, FAILED, FINISHED }; + using DownloadProgressCallback = std::function; + DevServerHelper( + std::string appId, + std::string deviceName, + const HttpClientFactory& httpClientFactory, + JavaScriptModuleCallback javaScriptModuleCallback) noexcept; + ~DevServerHelper() noexcept = default; + std::future downloadBundleResourceSync( + const std::string& jsBundleUrl, + DownloadProgressCallback&& downloadProgressCallback = nullptr); + std::string getInspectorUrl() const; + std::string getBundleUrl() const; + std::string getPackagerConnectionUrl() const; + void openDebugger() const; + void setSourcePath(const std::string& sourcePath) { + sourcePath_ = sourcePath; + } + void setupHMRClient() const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/DevSettingsModule.h}: +namespace facebook::react { +class DevSettingsModule : public NativeDevSettingsCxxSpec { + using LiveReloadCallback = std::function; + + public: + DevSettingsModule( + std::shared_ptr jsInvoker, + std::weak_ptr devServerHelper, + LiveReloadCallback&& liveReloadCallback) + : NativeDevSettingsCxxSpec(jsInvoker), + devServerHelper_(std::move(devServerHelper)), + liveReloadCallback_(std::move(liveReloadCallback)) {} + void reload(jsi::Runtime& rt); + void reloadWithReason(jsi::Runtime& rt, const std::string& reason); + void onFastRefresh(jsi::Runtime& rt); + void setHotLoadingEnabled(jsi::Runtime& rt, bool isHotLoadingEnabled); + void setIsDebuggingRemotely( + jsi::Runtime& rt, + bool isDebuggingRemotelyEnabled); + void setProfilingEnabled(jsi::Runtime& rt, bool isProfilingEnabled); + void toggleElementInspector(jsi::Runtime& rt); + void addMenuItem(jsi::Runtime& rt, const std::string& title); + void setIsShakeToShowDevMenuEnabled(jsi::Runtime& rt, bool enabled); + void openDebugger(jsi::Runtime& rt); + void addListener(jsi::Runtime& rt, const std::string& eventName); + void removeListeners(jsi::Runtime& rt, double count); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/IDevUIDelegate.h}: +namespace facebook::react { +struct IDevUIDelegate { + virtual ~IDevUIDelegate() noexcept = default; + virtual void showDownloadBundleProgress() = 0; + virtual void hideDownloadBundleProgress() = 0; + virtual void showLoadingView( + const std::string& message, + SharedColor textColor, + SharedColor backgroundColor) = 0; + virtual void hideLoadingView() = 0; + virtual void showDebuggerOverlay( + std::function&& resumeDebuggerFn) = 0; + virtual void hideDebuggerOverlay() = 0; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/LogBoxModule.h}: +namespace facebook::react { +class LogBoxModule : public NativeLogBoxCxxSpec { + public: + LogBoxModule( + std::shared_ptr jsInvoker, + std::shared_ptr surfaceDelegate); + ~LogBoxModule() override; + void show(jsi::Runtime& rt); + void hide(jsi::Runtime& rt); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/PackagerConnection.h}: +namespace facebook::react { +class PackagerConnection { + using LiveReloadCallback = std::function; + using ShowDevMenuCallback = std::function; + + public: + PackagerConnection( + const WebSocketClientFactory& webSocketClientFactory, + const std::string& packagerConnectionUrl, + LiveReloadCallback&& liveReloadCallback, + ShowDevMenuCallback&& showDevMenuCallback); + ~PackagerConnection() noexcept; + PackagerConnection(const PackagerConnection& other) = delete; + PackagerConnection& operator=(PackagerConnection& other) = delete; + PackagerConnection(PackagerConnection&& other) = delete; + PackagerConnection& operator=(PackagerConnection&& other) = delete; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/SourceCodeModule.h}: +namespace facebook::react { +using SourceCodeConstants = NativeSourceCodeSourceCodeConstants; +template <> +struct Bridging + : NativeSourceCodeSourceCodeConstantsBridging {}; +class SourceCodeModule : public NativeSourceCodeCxxSpec { + public: + explicit SourceCodeModule( + std::shared_ptr jsInvoker, + std::shared_ptr devServerHelper = nullptr) + : NativeSourceCodeCxxSpec(jsInvoker), devServerHelper_(devServerHelper) {} + SourceCodeConstants getConstants(jsi::Runtime& rt); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/inspector/Inspector.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/devsupport/inspector/InspectorThread.h} +namespace facebook::react { +using ToggleDebuggerOverlayFn = + std::function&&)>; +using LiveReloadCallbackFn = std::function; +class Inspector : public InspectorThread, + public std::enable_shared_from_this { + public: + Inspector( + std::string appName, + std::string deviceName, + WebSocketClientFactory webSocketClientFactory, + HttpClientFactory httpClientFactory) noexcept; + ~Inspector() noexcept override; + Inspector(const Inspector& other) = delete; + Inspector& operator=(Inspector& other) = delete; + Inspector(Inspector&& other) = delete; + Inspector& operator=(Inspector&& other) = delete; + void connectDebugger(const std::string& inspectorUrl) noexcept; + void ensureHostTarget( + LiveReloadCallbackFn&& liveReloadCallbackFn, + ToggleDebuggerOverlayFn&& toggleDebuggerOverlayFn) noexcept; + std::shared_ptr inspectorTarget() const; +}; + std::string appName_; + std::string deviceName_; + WebSocketClientFactory webSocketClientFactory_; + HttpClientFactory httpClientFactory_; + std::shared_ptr hostDelegate_; + std::shared_ptr target_; + std::optional pageId_; + std::unique_ptr + packagerConnection_; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/inspector/InspectorPackagerConnectionDelegate.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/devsupport/inspector/InspectorThread.h} +namespace facebook::react { +class InspectorPackagerConnectionDelegate final + : public jsinspector_modern::InspectorPackagerConnectionDelegate { + class WebSocket : public jsinspector_modern::IWebSocket { + public: + WebSocket( + const std::string& url, + std::weak_ptr webSocketDelegate, + std::weak_ptr inspectorThread, + const WebSocketClientFactory& webSocketClientFactory); + ~WebSocket() override; + WebSocket(const WebSocket& other) = delete; + WebSocket& operator=(WebSocket& other) = delete; + WebSocket(WebSocket&& other) = delete; + WebSocket& operator=(WebSocket&& other) = delete; + void send(std::string_view message) override; + + private: + std::weak_ptr webSocketDelegate_; + std::weak_ptr inspectorThread_; + std::unique_ptr websocket_; + }; + + public: + InspectorPackagerConnectionDelegate( + std::weak_ptr inspectorThread, + WebSocketClientFactory webSocketClientFactory) noexcept; + std::unique_ptr connectWebSocket( + const std::string& url, + std::weak_ptr delegate) override; + void scheduleCallback( + std::function callback, + std::chrono::milliseconds delayMs = + std::chrono::milliseconds::zero()) override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/devsupport/inspector/InspectorThread.h}: +namespace facebook::react { +class InspectorThread { + public: + InspectorThread() noexcept = default; + virtual ~InspectorThread() = default; + InspectorThread(const InspectorThread& other) = delete; + InspectorThread& operator=(InspectorThread& other) = delete; + InspectorThread(InspectorThread&& other) = delete; + InspectorThread& operator=(InspectorThread&& other) = delete; + virtual void invokeElsePost( + TaskDispatchThread::TaskFn&& callback, + std::chrono::milliseconds delayMs = std::chrono::milliseconds(0)) = 0; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/http/IHttpClient.h}: +namespace facebook::react { +namespace http { +using Headers = std::vector>; +struct FormDataField { + std::string fieldName; + Headers headers; + std::optional string; + std::optional uri; +}; +using FormData = std::vector; +struct Body { + std::optional string; + std::optional blob; + std::optional formData; + std::optional base64; +}; +using OnUploadProgress = std::function; +using OnResponse = std::function; +using OnBody = std::function body)>; +using OnBodyIncremental = std::function body)>; +using OnBodyProgress = std::function; +using OnResponseComplete = + std::function; +struct NetworkCallbacks { + OnUploadProgress onUploadProgress{nullptr}; + OnResponse onResponse{nullptr}; + OnBody onBody{nullptr}; + OnBodyIncremental onBodyIncremental{nullptr}; + OnBodyProgress onBodyProgress{nullptr}; + OnResponseComplete onResponseComplete{nullptr}; + bool sendIncrementalUpdates{false}; + bool sendProgressUpdates{false}; +}; +struct IRequestToken { + virtual ~IRequestToken() = default; + virtual void cancel() noexcept = 0; +}; +} // namespace http +struct IHttpClient { + virtual ~IHttpClient() = default; + virtual std::unique_ptr sendRequest( + http::NetworkCallbacks&& callback, + const std::string& method, + const std::string& url, + const http::Headers& headers = {}, + const http::Body& body = {}, + uint32_t timeout = 0, + std::optional loggingId = std::nullopt) = 0; +}; +extern const char HttpClientFactoryKey[]; +using HttpClientFactory = std::function()>; +HttpClientFactory getHttpClientFactory(); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/http/IWebSocketClient.h}: +namespace facebook::react { +class IWebSocketClient { + public: + using OnConnectCallback = std::function; + using OnClosedCallback = std::function; + using OnMessageCallback = std::function; + virtual ~IWebSocketClient() = default; + virtual void setOnClosedCallback(OnClosedCallback&& callback) noexcept = 0; + virtual void setOnMessageCallback(OnMessageCallback&& callback) noexcept = 0; + virtual void connect( + const std::string& url, + OnConnectCallback&& = nullptr) = 0; + virtual void close(const std::string& reason) = 0; + virtual void send(const std::string& message) = 0; + virtual void ping() = 0; +}; +extern const char WebSocketClientFactoryKey[]; +using WebSocketClientFactory = + std::function()>; +WebSocketClientFactory getWebSocketClientFactory(); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/io/ImageLoaderModule.h}: +namespace facebook::react { +using ImageSize = NativeImageLoaderAndroidImageSize; +template <> +struct Bridging + : NativeImageLoaderAndroidImageSizeBridging {}; +class ImageLoaderModule + : public NativeImageLoaderAndroidCxxSpec { + public: + explicit ImageLoaderModule(std::shared_ptr jsInvoker) + : NativeImageLoaderAndroidCxxSpec(jsInvoker) {} + jsi::Object getConstants(jsi::Runtime& rt); + void abortRequest(jsi::Runtime& rt, int32_t requestId); + AsyncPromise getSize(jsi::Runtime& rt, const std::string& uri); + AsyncPromise getSizeWithHeaders( + jsi::Runtime& rt, + const std::string& uri, + jsi::Object headers); + AsyncPromise + prefetchImage(jsi::Runtime& rt, const std::string& uri, int32_t requestId); + jsi::Object queryCache( + jsi::Runtime& rt, + const std::vector& uris); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/io/NetworkingModule.h}: +namespace facebook::react { +template <> +struct Bridging { + static http::FormDataField fromJs( + jsi::Runtime& rt, + const jsi::Object& value, + const std::shared_ptr& jsInvoker) { + auto fieldName = bridging::fromJs( + rt, value.getProperty(rt, "fieldName"), jsInvoker); + auto headers = bridging::fromJs( + rt, value.getProperty(rt, "headers"), jsInvoker); + auto string = bridging::fromJs>( + rt, value.getProperty(rt, "string"), jsInvoker); + auto uri = bridging::fromJs>( + rt, value.getProperty(rt, "uri"), jsInvoker); + return http::FormDataField{ + .fieldName = fieldName, + .headers = headers, + .string = string, + .uri = uri}; + } +}; +template <> +struct Bridging { + static http::Body fromJs( + jsi::Runtime& rt, + const jsi::Object& value, + const std::shared_ptr& jsInvoker) { + return http::Body{ + .string = bridging::fromJs>( + rt, value.getProperty(rt, "string"), jsInvoker), + .blob = bridging::fromJs>( + rt, value.getProperty(rt, "blob"), jsInvoker), + .formData = bridging::fromJs>( + rt, value.getProperty(rt, "formData"), jsInvoker), + .base64 = bridging::fromJs>( + rt, value.getProperty(rt, "base64"), jsInvoker), + }; + } +}; +class Requests { + public: + Requests() noexcept = default; + ~Requests(); + Requests(Requests& other) = delete; + Requests& operator=(Requests& other) = delete; + Requests(Requests&& other) = delete; + Requests& operator=(Requests&& other) = delete; + bool reserve(uint32_t id); + void store(uint32_t id, std::unique_ptr token); + bool erase(uint32_t id); + void cancel(uint32_t id); + void stop(); + bool isStopped(); +}; +}; +class NetworkingModule + : public NativeNetworkingAndroidCxxSpec, + public std::enable_shared_from_this { + public: + NetworkingModule( + std::shared_ptr jsInvoker, + const HttpClientFactory& httpClientFactory); + ~NetworkingModule() override; + void sendRequest( + jsi::Runtime& rt, + const std::string& method, + const std::string& url, + uint32_t requestId, + const http::Headers& headers, + const http::Body& body, + const std::string& responseType, + bool useIncrementalUpdates, + uint32_t timeout, + bool withCredentials); + void abortRequest(jsi::Runtime& rt, uint32_t requestId); + void clearCookies(jsi::Runtime& rt, const AsyncCallback& callback); + void addListener(jsi::Runtime& rt, const std::string& eventName); + void removeListeners(jsi::Runtime& rt, uint32_t count); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/io/ResourceLoader.h}: +namespace facebook::react { +class ResourceLoader { + public: + static bool isDirectory(const std::string& path); + static bool isFile(const std::string& path); + static bool isAbsolutePath(const std::string& path); + static std::string getFileContents(const std::string& path); + static std::filesystem::path getCacheDirectory( + const std::string& path = std::string()); + + protected: + static bool isResourceDirectory(const std::string& path); + static bool isResourceFile(const std::string& path); + static std::string getResourceFileContents(const std::string& path); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/io/WebSocketModule.h}: +namespace facebook::react { +class WebSocketModule : public NativeWebSocketModuleCxxSpec, + public std::enable_shared_from_this { + public: + WebSocketModule( + std::shared_ptr jsInvoker, + WebSocketClientFactory webSocketClientFactory); + ~WebSocketModule() override; + WebSocketModule(const WebSocketModule& other) = delete; + WebSocketModule& operator=(WebSocketModule& other) = delete; + WebSocketModule(WebSocketModule&& other) = delete; + WebSocketModule& operator=(WebSocketModule&& other) = delete; + void connect( + jsi::Runtime& rt, + const std::string& url, + const std::optional>& protocols, + jsi::Object options, + int32_t socketID); + void send(jsi::Runtime& rt, const std::string& message, int32_t socketID); + void sendBinary( + jsi::Runtime& rt, + const std::string& base64String, + int32_t socketID); + void ping(jsi::Runtime& rt, int32_t socketID); + void close( + jsi::Runtime& rt, + int32_t code, + const std::string& reason, + int32_t socketID); + void addListener(jsi::Runtime& rt, const std::string& eventName); + void removeListeners(jsi::Runtime& rt, int32_t count); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/io/platform/android/AssetManagerHelpers.h}: +namespace facebook::react { +AAssetManager* getJavaAssetManager(); +bool isDirectoryNotEmpty(const std::string& path); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/jni/JniHelper.h}: +namespace facebook::react { +jobject getApplication(JNIEnv* env); +jni::alias_ref getContext(); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/logging/DefaultLogger.h}: +namespace facebook::react { +using Logger = + std::function; +Logger getDefaultLogger(); +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/logging/DefaultOnJsErrorHandler.h}: +namespace facebook::react { +static inline JsErrorHandler::OnJsError getDefaultOnJsErrorFunc() { + return [](jsi::Runtime&, const JsErrorHandler::ProcessedError& error) { + LOG(ERROR) << "[onJsError called]: " << error << std::endl; + }; +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/logging/LogOnce.h}: +namespace facebook::react { +class LogOnceWrapper : public std::stringstream { + public: + enum class Severity { Info, Warning, Error, Fatal }; + LogOnceWrapper(Severity severity = Severity::Info) : severity_(severity) {} + ~LogOnceWrapper(); +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/logging/NativeExceptionsManager.h}: +namespace facebook::react { +using StackFrame = NativeExceptionsManagerStackFrame< + std::optional, + std::optional, + std::optional, + std::string, + std::optional>; +template <> +struct Bridging + : NativeExceptionsManagerStackFrameBridging {}; +using ExceptionData = NativeExceptionsManagerExceptionData< + std::string, + std::optional, + std::optional, + std::optional, + std::vector, + int32_t, + bool, + std::optional>>; +template <> +struct Bridging + : NativeExceptionsManagerExceptionDataBridging {}; +class NativeExceptionsManager + : public NativeExceptionsManagerCxxSpec { + public: + NativeExceptionsManager( + JsErrorHandler::OnJsError onJsError, + std::shared_ptr jsInvoker) + : NativeExceptionsManagerCxxSpec(jsInvoker), + onJsError_(std::move(onJsError)) {} + void reportFatalException( + jsi::Runtime& rt, + std::string message, + std::vector stack, + int32_t exceptionId); + void reportSoftException( + jsi::Runtime& rt, + std::string message, + std::vector stack, + int32_t exceptionId); + void reportException(jsi::Runtime& runtime, const ExceptionData& data); + void updateExceptionMessage( + jsi::Runtime& rt, + jsi::String message, + jsi::Array stack, + double exceptionId) {} + void dismissRedbox(jsi::Runtime& rt) {} +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/nativemodule/JavaScriptModule.h}: +namespace facebook::react { +using JavaScriptModuleCallback = std::function; +} + +/// @src {packages/react-native/ReactCxxPlatform/react/nativemodule/TurboModuleManager.h}: +namespace facebook::react { +using TurboModuleManagerDelegate = std::function( + const std::string& name, + const std::shared_ptr& jsInvoker)>; +using TurboModuleManagerDelegates = std::vector; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/profiling/FrameStats.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/profiling/perfetto.h} +namespace facebook::react { +void enableFrameStatsPrinting(bool enable = true); +void logFrameStats(double timeStampMs, double durationMs); +inline double getTimeStampMs() { + return std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()) + .count() / + 1000000.0; +} +class FrameStatsBlock { + public: + FrameStatsBlock() : startTimeStamp_(getTimeStampMs()) {} + ~FrameStatsBlock() { + logFrameStats(startTimeStamp_, getTimeStampMs() - startTimeStamp_); + } +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/profiling/RuntimeHeapInfoCollector.h}: +namespace facebook::react { +struct HeapInfo { + int64_t allocatedBytes{0}; + int64_t heapSize{0}; + int64_t numCollections{0}; +}; +inline std::ostream& operator<<(std::ostream& os, HeapInfo& heapInfo) { + os << "[heapInfo: allocatedBytes: " << heapInfo.allocatedBytes + << ", heapSize: " << heapInfo.heapSize + << ", numCollections: " << heapInfo.numCollections << "]"; + return os; +} +class RuntimeHeapInfoCollector { + public: + RuntimeHeapInfoCollector(std::chrono::milliseconds intervalMs); + static std::unique_ptr create( + std::chrono::milliseconds intervalMs); + void collectHeapInfo(jsi::Runtime& runtime); + HeapInfo getHeapInfo() { + return heapInfo_; + } +}; + std::chrono::milliseconds intervalMs_; + std::chrono::steady_clock::time_point lastCollectionTime_; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/profiling/TimeSeries.h}: +namespace facebook::react { +class TimeSeries { + struct Range { + int idxFrom1{0}; + int idxTo1{0}; + int idxFrom2{0}; + int idxTo2{0}; + int size() const { + return (idxTo1 - idxFrom1) + (idxTo2 - idxFrom2); + } + bool isEmpty() const { + return size() == 0; + } + bool isContinuous() const { + return idxTo2 - idxFrom2 == 0; + } + }; + + public: + static constexpr int DEFAULT_CAPACITY = 100; + enum class Bound { Upper = 0, Lower = 1 }; + TimeSeries(int capacity = DEFAULT_CAPACITY); + bool operator==(const TimeSeries& rhs) const; + int getCapacity() const { + return static_cast(times_.capacity()); + } + void setCapacity(int capacity); + void reset(); + int findHistoryPointIndex(double t, Bound bound = Bound::Lower) const; + int getNumPoints() const { + return static_cast(times_.size()); + } + double& valueAtIndex(int idx) { + const int numPoints = getNumPoints(); + return values_[(idx + position_) % numPoints]; + } + double& timeAtIndex(int idx) { + const int numPoints = getNumPoints(); + return times_[(idx + position_) % numPoints]; + } + double valueAtIndex(int idx) const { + const int numPoints = getNumPoints(); + return values_[(idx + position_) % numPoints]; + } + double timeAtIndex(int idx) const { + const int numPoints = getNumPoints(); + return times_[(idx + position_) % numPoints]; + } + void appendValue(double time, double value); + void accumulateValue(double timeFrom, double timeTo, double value); + double getValue(double time) const; + double getPercentile(unsigned int percentile) const; + double getPercentile(unsigned int percentile, double timeFrom, double timeTo) + const; + double getAverage() const; + double getAverage(double timeFrom, double timeTo) const; + double getMax() const; + double getMax(double timeFrom, double timeTo) const; + double getMin() const; + double getMin(double timeFrom, double timeTo) const; + double getSum() const; + double getSum(double timeFrom, double timeTo) const; + int getCount(double timeFrom, double timeTo) const; + double getMaxTime() const; + double getMinTime() const; + friend std::ostream& operator<<(std::ostream& os, const TimeSeries& ts); + friend std::ostream& operator<<( + std::ostream& os, + const TimeSeries::Range& range); +}; + Range findHistoryPointRange(double timeFrom, double timeTo) const; + Range wholeRange() const; + double getPercentile(unsigned int percentile, const Range& range) const; + double getAverage(const Range& range) const; + double getMax(const Range& range) const; + double getMin(const Range& range) const; + double getSum(const Range& range) const; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/profiling/perfetto.h}: +inline void initializePerfetto() {} + +/// @src {packages/react-native/ReactCxxPlatform/react/profiling/tracy_noop.h}: + + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/AnimatedModule.h}: +namespace facebook::react { +class AnimatedModule : public NativeAnimatedModuleCxxSpec, + public TurboModuleWithJSIBindings { + struct CreateAnimatedNodeOp { + Tag tag{}; + folly::dynamic config; + }; + struct GetValueOp { + Tag tag{}; + AsyncCallback callback; + }; + struct StartListeningToAnimatedNodeValueOp { + Tag tag{}; + }; + struct StopListeningToAnimatedNodeValueOp { + Tag tag{}; + }; + struct ConnectAnimatedNodesOp { + Tag parentTag{}; + Tag childTag{}; + }; + struct DisconnectAnimatedNodesOp { + Tag parentTag{}; + Tag childTag{}; + }; + struct StartAnimatingNodeOp { + int animationId{}; + Tag nodeTag{}; + folly::dynamic config; + AnimationEndCallback endCallback; + }; + struct StopAnimationOp { + int animationId{}; + }; + struct SetAnimatedNodeValueOp { + Tag nodeTag{}; + double value{}; + }; + struct SetAnimatedNodeOffsetOp { + Tag nodeTag{}; + double offset{}; + }; + struct ConnectAnimatedNodeToViewOp { + Tag nodeTag{}; + Tag viewTag{}; + }; + struct DisconnectAnimatedNodeFromViewOp { + Tag nodeTag{}; + Tag viewTag{}; + }; + struct RestoreDefaultValuesOp { + Tag nodeTag{}; + }; + struct DropAnimatedNodeOp { + Tag tag{}; + }; + struct AddAnimatedEventToViewOp { + Tag viewTag{}; + std::string eventName; + folly::dynamic eventMapping; + }; + struct RemoveAnimatedEventFromViewOp { + Tag viewTag{}; + std::string eventName; + Tag animatedNodeTag{}; + }; + using Operation = std::variant< + CreateAnimatedNodeOp, + GetValueOp, + StartListeningToAnimatedNodeValueOp, + StopListeningToAnimatedNodeValueOp, + ConnectAnimatedNodesOp, + DisconnectAnimatedNodesOp, + StartAnimatingNodeOp, + StopAnimationOp, + SetAnimatedNodeOffsetOp, + SetAnimatedNodeValueOp, + ConnectAnimatedNodeToViewOp, + DisconnectAnimatedNodeFromViewOp, + RestoreDefaultValuesOp, + DropAnimatedNodeOp, + AddAnimatedEventToViewOp, + RemoveAnimatedEventFromViewOp>; + + public: + AnimatedModule( + std::shared_ptr jsInvoker, + std::shared_ptr nodesManagerProvider); + void startOperationBatch(jsi::Runtime& rt); + void finishOperationBatch(jsi::Runtime& rt); + void createAnimatedNode(jsi::Runtime& rt, Tag tag, jsi::Object config); + void updateAnimatedNodeConfig(jsi::Runtime& rt, Tag tag, jsi::Object config); + void + getValue(jsi::Runtime& rt, Tag tag, AsyncCallback saveValueCallback); + void startListeningToAnimatedNodeValue(jsi::Runtime& rt, Tag tag); + void stopListeningToAnimatedNodeValue(jsi::Runtime& rt, Tag tag); + void connectAnimatedNodes(jsi::Runtime& rt, Tag parentTag, Tag childTag); + void disconnectAnimatedNodes(jsi::Runtime& rt, Tag parentTag, Tag childTag); + void startAnimatingNode( + jsi::Runtime& rt, + int animationId, + Tag nodeTag, + jsi::Object config, + AnimationEndCallback endCallback); + void stopAnimation(jsi::Runtime& rt, int animationId); + void setAnimatedNodeValue(jsi::Runtime& rt, Tag nodeTag, double value); + void setAnimatedNodeOffset(jsi::Runtime& rt, Tag nodeTag, double offset); + void flattenAnimatedNodeOffset(jsi::Runtime& rt, Tag nodeTag); + void extractAnimatedNodeOffset(jsi::Runtime& rt, Tag nodeTag); + void connectAnimatedNodeToView(jsi::Runtime& rt, Tag nodeTag, Tag viewTag); + void + disconnectAnimatedNodeFromView(jsi::Runtime& rt, Tag nodeTag, Tag viewTag); + void restoreDefaultValues(jsi::Runtime& rt, Tag nodeTag); + void dropAnimatedNode(jsi::Runtime& rt, Tag tag); + void addAnimatedEventToView( + jsi::Runtime& rt, + Tag viewTag, + std::string eventName, + jsi::Object eventMapping); + void removeAnimatedEventFromView( + jsi::Runtime& rt, + Tag viewTag, + std::string eventName, + Tag animatedNodeTag); + void addListener(jsi::Runtime& rt, const std::string& eventName); + void removeListeners(jsi::Runtime& rt, int count); + void queueAndExecuteBatchedOperations( + jsi::Runtime& rt, + jsi::Array operationsAndArgs); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/AnimatedMountingOverrideDelegate.h}: +namespace facebook::react { +class AnimatedMountingOverrideDelegate : public MountingOverrideDelegate { + public: + AnimatedMountingOverrideDelegate( + std::function getAnimatedManagedProps, + const Scheduler& scheduler); + bool shouldOverridePullTransaction() const override; + std::optional pullTransaction( + SurfaceId surfaceId, + MountingTransaction::Number transactionNumber, + const TransactionTelemetry& telemetry, + ShadowViewMutationList mutations) const override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/EventEmitterListener.h}: +namespace facebook::react { +template +using EventListenerT = std::function; +template +class EventListenerContainerT { + public: + bool willDispatchEvent(TArgs... args) { + std::shared_lock lock(mutex_); + bool handled = false; + for (const auto& listener : eventListeners_) { + handled = (*listener)(args...); + if (handled) { + break; + } + } + return handled; + } + void addListener(std::shared_ptr> listener) { + std::unique_lock lock(mutex_); + eventListeners_.push_back(std::move(listener)); + } + void removeListener( + const std::shared_ptr>& listener) { + std::unique_lock lock(mutex_); + auto it = + std::find(eventListeners_.begin(), eventListeners_.end(), listener); + if (it != eventListeners_.end()) { + eventListeners_.erase(it); + } + } +}; +using EventEmitterListener = + EventListenerT; +using EventEmitterListenerContainer = + EventListenerContainerT; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/NativeAnimatedAllowlist.h}: +namespace facebook::react { +inline static std::unordered_set getDirectManipulationAllowlist() { + static std::unordered_set DIRECT_MANIPULATION_STYLES{ + "backgroundColor", + "borderBottomColor", + "borderColor", + "borderEndColor", + "borderLeftColor", + "borderRightColor", + "borderStartColor", + "borderTopColor", + "color", + "tintColor", + "borderBottomEndRadius", + "borderBottomLeftRadius", + "borderBottomRightRadius", + "borderBottomStartRadius", + "borderEndEndRadius", + "borderEndStartRadius", + "borderRadius", + "borderTopEndRadius", + "borderTopLeftRadius", + "borderTopRightRadius", + "borderTopStartRadius", + "borderStartEndRadius", + "borderStartStartRadius", + "elevation", + "opacity", + "transform", + "zIndex", + "shadowOpacity", + "shadowRadius", + "scaleX", + "scaleY", + "translateX", + "translateY", + }; + return DIRECT_MANIPULATION_STYLES; +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/NativeAnimatedNodesManager.h}: +namespace facebook::react { +using TimePointFunction = std::chrono::steady_clock::time_point (*)(); +void g_setNativeAnimatedNowTimestampFunction(TimePointFunction nowFunction); +using ValueListenerCallback = std::function; +using UiTask = std::function; +using EndResult = NativeAnimatedTurboModuleEndResult< + bool, + std::optional, + std::optional>; +using AnimationEndCallback = AsyncCallback; +template <> +struct Bridging + : NativeAnimatedTurboModuleEndResultBridging {}; +class NativeAnimatedNodesManager { + public: + using DirectManipulationCallback = + std::function; + using FabricCommitCallback = + std::function&)>; + using StartOnRenderCallback = std::function&&)>; + using StopOnRenderCallback = std::function; + explicit NativeAnimatedNodesManager( + DirectManipulationCallback&& directManipulationCallback, + FabricCommitCallback&& fabricCommitCallback, + StartOnRenderCallback&& startOnRenderCallback = nullptr, + StopOnRenderCallback&& stopOnRenderCallback = nullptr) noexcept; + ~NativeAnimatedNodesManager() noexcept; + template < + typename T, + typename = std::enable_if_t>> + T* getAnimatedNode(Tag tag) const + requires(std::is_base_of_v) + { + if (auto it = animatedNodes_.find(tag); it != animatedNodes_.end()) { + return static_cast(it->second.get()); + } + return nullptr; + } + std::optional getValue(Tag tag) noexcept; + void createAnimatedNode(Tag tag, const folly::dynamic& config) noexcept; + void connectAnimatedNodes(Tag parentTag, Tag childTag) noexcept; + void connectAnimatedNodeToView(Tag propsNodeTag, Tag viewTag) noexcept; + void disconnectAnimatedNodes(Tag parentTag, Tag childTag) noexcept; + void disconnectAnimatedNodeFromView(Tag propsNodeTag, Tag viewTag) noexcept; + void restoreDefaultValues(Tag tag) noexcept; + void dropAnimatedNode(Tag tag) noexcept; + void setAnimatedNodeValue(Tag tag, double value); + void setAnimatedNodeOffset(Tag tag, double offset); + void startAnimatingNode( + int animationId, + Tag animatedNodeTag, + folly::dynamic config, + std::optional endCallback) noexcept; + void stopAnimation( + int animationId, + bool isTrackingAnimation = false) noexcept; + void addAnimatedEventToView( + Tag viewTag, + const std::string& eventName, + const folly::dynamic& eventMapping) noexcept; + void removeAnimatedEventFromView( + Tag viewTag, + const std::string& eventName, + Tag animatedValueTag) noexcept; + std::shared_ptr getEventEmitterListener() noexcept { + return ensureEventEmitterListener(); + } + void startListeningToAnimatedNodeValue( + Tag tag, + ValueListenerCallback&& callback) noexcept; + void stopListeningToAnimatedNodeValue(Tag tag) noexcept; + void schedulePropsCommit( + Tag viewTag, + const folly::dynamic& props, + bool layoutStyleUpdated, + bool forceFabricCommit) noexcept; + bool commitProps(); + void scheduleOnUI(UiTask&& task) { + { + std::lock_guard lock(uiTasksMutex_); + operations_.push_back(std::move(task)); + } + startRenderCallbackIfNeeded(); + } + void onRender(); + void startRenderCallbackIfNeeded(); + void updateNodes( + const std::set& finishedAnimationValueNodes = {}) noexcept; + folly::dynamic managedProps(Tag tag) noexcept; + bool isOnRenderThread() const noexcept; +}; + DirectManipulationCallback directManipulationCallback_; + FabricCommitCallback fabricCommitCallback_; + StartOnRenderCallback startOnRenderCallback_; + StopOnRenderCallback stopOnRenderCallback_; + std::shared_ptr eventEmitterListener_{nullptr}; + std::unordered_map updateViewProps_{}; + std::unordered_map updateViewPropsDirect_{}; + int animatedGraphBFSColor_ = 0; + friend + friend + friend +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/NativeAnimatedNodesManagerProvider.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/NativeAnimatedNodesManager.h} + +namespace facebook::react { +class UIManagerNativeAnimatedDelegateImpl + : public UIManagerNativeAnimatedDelegate { + public: + explicit UIManagerNativeAnimatedDelegateImpl( + std::weak_ptr nativeAnimatedNodesManager); + void runAnimationFrame() override; +}; +class NativeAnimatedNodesManagerProvider { + public: + NativeAnimatedNodesManagerProvider( + NativeAnimatedNodesManager::StartOnRenderCallback startOnRenderCallback = + nullptr, + NativeAnimatedNodesManager::StopOnRenderCallback stopOnRenderCallback = + nullptr); + std::shared_ptr getOrCreate( + jsi::Runtime& runtime); + void addEventEmitterListener( + const std::shared_ptr& listener); + std::shared_ptr getEventEmitterListener(); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/AnimationDriver.h}: +namespace facebook::react { +enum class AnimationDriverType { + Frames, + Spring, + Decay, +}; +class AnimationDriver { + public: + AnimationDriver( + int id, + Tag animatedValueTag, + std::optional endCallback, + folly::dynamic config, + NativeAnimatedNodesManager* manager); + virtual ~AnimationDriver() = default; + void startAnimation(); + void stopAnimation(bool ignoreCompletedHandlers = false); + inline int getId() const noexcept { + return id_; + } + inline Tag getAnimatedValueTag() const noexcept { + return animatedValueTag_; + } + bool getIsComplete() const noexcept { + return isComplete_; + } + void runAnimationStep(double renderingTime); + virtual void updateConfig(folly::dynamic config); + static std::optional getDriverTypeByName( + const std::string& driverTypeName); + + protected: + virtual bool update(double, bool) { + return true; + } + void markNodeUpdated(Tag tag) { + manager_->updatedNodeTags_.insert(tag); + } + std::optional endCallback_; + int id_{0}; + Tag animatedValueTag_{}; + int iterations_{0}; + NativeAnimatedNodesManager* manager_; + bool isComplete_{false}; + int currentIteration_{0}; + double startFrameTimeMs_{-1}; + bool isStarted_{false}; + bool ignoreCompletedHandlers_{false}; + folly::dynamic config_{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/AnimationDriverUtils.h}: +namespace facebook::react { +static constexpr std::string_view ExtrapolateTypeIdentity = "identity"; +static constexpr std::string_view ExtrapolateTypeClamp = "clamp"; +static constexpr std::string_view ExtrapolateTypeExtend = "extend"; +static constexpr double SingleFrameIntervalMs = 1000.0 / 60.0; +static constexpr double TicksPerMs = 10000.0; +inline double interpolate( + double inputValue, + double inputMin, + double inputMax, + double outputMin, + double outputMax, + std::string_view extrapolateLeft, + std::string_view extrapolateRight) { + auto result = inputValue; + if (result < inputMin) { + if (extrapolateLeft == ExtrapolateTypeIdentity) { + return result; + } else if (extrapolateLeft == ExtrapolateTypeClamp) { + result = inputMin; + } + } + if (result > inputMax) { + if (extrapolateRight == ExtrapolateTypeIdentity) { + return result; + } else if (extrapolateRight == ExtrapolateTypeClamp) { + result = inputMax; + } + } + if (inputMin == inputMax) { + if (inputValue <= inputMin) { + return outputMin; + } + return outputMax; + } + return outputMin + + (outputMax - outputMin) * (result - inputMin) / (inputMax - inputMin); +} +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/DecayAnimationDriver.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/AnimationDriver.h} + +namespace facebook::react { +class DecayAnimationDriver : public AnimationDriver { + public: + DecayAnimationDriver( + int id, + Tag animatedValueTag, + std::optional endCallback, + folly::dynamic config, + NativeAnimatedNodesManager* manager); + + protected: + bool update(double timeDeltaMs, bool restarting) override; +}; + double deceleration_{0}; + std::optional fromValue_{std::nullopt}; + std::optional lastValue_{0}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/FrameAnimationDriver.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/AnimationDriver.h} + +namespace facebook::react { +class FrameAnimationDriver : public AnimationDriver { + public: + FrameAnimationDriver( + int id, + Tag animatedValueTag, + std::optional endCallback, + folly::dynamic config, + NativeAnimatedNodesManager* manager); + + protected: + bool update(double timeDeltaMs, bool restarting) override; + void updateConfig(folly::dynamic config) override; +}; + double toValue_{0}; + std::optional startValue_{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/SpringAnimationDriver.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/drivers/AnimationDriver.h} + +namespace facebook::react { +class SpringAnimationDriver : public AnimationDriver { + public: + SpringAnimationDriver( + int id, + Tag animatedValueTag, + std::optional endCallback, + folly::dynamic config, + NativeAnimatedNodesManager* manager); + + protected: + bool update(double timeDeltaMs, bool restarting) override; +}; + double springDamping_{0}; + double springMass_{0}; + double initialVelocity_{0}; + std::optional fromValue_{std::nullopt}; + double endValue_{0}; + double restSpeedThreshold_{0}; + double displacementFromRestThreshold_{0}; + bool overshootClampingEnabled_{false}; + double lastTime_{0}; + double timeAccumulator_{0}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/event_drivers/EventAnimationDriver.h}: +namespace facebook::react { +class EventAnimationDriver { + public: + EventAnimationDriver( + const std::vector& eventPath, + Tag animatedValueTag); + ~EventAnimationDriver() = default; + std::optional getValueFromPayload(const EventPayload& eventPayload); + Tag getAnimatedNodeTag() const { + return animatedValueTag_; + } + + protected: + std::vector eventPath_; + Tag animatedValueTag_; +}; +struct EventAnimationDriverKey { + Tag viewTag; + std::string eventName; + bool operator==( + const facebook::react::EventAnimationDriverKey& rhs) const noexcept { + return viewTag == rhs.viewTag && eventName == rhs.eventName; + } +}; +} // namespace facebook::react +namespace std { +template <> +struct hash { + size_t operator()(const facebook::react::EventAnimationDriverKey& key) const { + return std::hash()(key.viewTag) ^ + std::hash()(key.eventName); + } +}; +} // namespace std + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AdditionAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +namespace facebook::react { +class AdditionAnimatedNode final : public OperatorAnimatedNode { + public: + AdditionAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager) + : OperatorAnimatedNode(tag, config, manager) {} + void update() override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h}: +namespace facebook::react { +enum class AnimatedNodeType { + Style, + Value, + Props, + Interpolation, + Addition, + Subtraction, + Division, + Multiplication, + Modulus, + Diffclamp, + Transform, + Tracking, + Color, + Round, +}; +class AnimatedNode { + public: + AnimatedNode( + Tag tag, + folly::dynamic config, + NativeAnimatedNodesManager& manager, + AnimatedNodeType type); + virtual ~AnimatedNode() = default; + AnimatedNode(AnimatedNode&&) noexcept = default; + AnimatedNode& operator=(AnimatedNode&&) noexcept = default; + AnimatedNode(const AnimatedNode&) = default; + AnimatedNode& operator=(const AnimatedNode&) = default; + Tag tag() const noexcept { + return tag_; + } + void addChild(Tag tag); + void removeChild(Tag tag); + const std::unordered_set& getChildren() const noexcept { + return children_; + } + AnimatedNodeType type() const noexcept { + return type_; + } + const folly::dynamic& getConfig() const noexcept { + return config_; + } + virtual void update() {} + virtual void onDetachedFromNode(Tag) {} + virtual void onAttachToNode(Tag) {} + static std::optional getNodeTypeByName( + const std::string& nodeTypeName); + int activeIncomingNodes = 0; + int bfsColor = 0; + static constexpr int INITIAL_BFS_COLOR = 0; + + protected: + AnimatedNode* getChildNode(Tag tag); + Tag tag_{0}; + NativeAnimatedNodesManager* manager_; + AnimatedNodeType type_; + std::unordered_set children_{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/ColorAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +class ColorAnimatedNode final : public AnimatedNode { + public: + ColorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; + Color getColor(); +}; + Tag gNodeTag_{}; + Tag bNodeTag_{}; + Tag aNodeTag_{}; + Color color_{0}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/DiffClampAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +namespace facebook::react { +class DiffClampAnimatedNode final : public ValueAnimatedNode { + public: + DiffClampAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/DivisionAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +namespace facebook::react { +class DivisionAnimatedNode final : public OperatorAnimatedNode { + public: + DivisionAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager) + : OperatorAnimatedNode(tag, config, manager) {} + void update() override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/InterpolationAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react +namespace facebook::react { +class InterpolationAnimatedNode final : public ValueAnimatedNode { + public: + InterpolationAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; + void onDetachedFromNode(Tag animatedNodeTag) override; + void onAttachToNode(Tag animatedNodeTag) override; +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/ModulusAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +namespace facebook::react { +class ModulusAnimatedNode final : public ValueAnimatedNode { + public: + ModulusAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; +}; + double modulus_{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/MultiplicationAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +namespace facebook::react { +class MultiplicationAnimatedNode final : public OperatorAnimatedNode { + public: + MultiplicationAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager) + : OperatorAnimatedNode(tag, config, manager) {} + void update() override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/PropsAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +class PropsAnimatedNode final : public AnimatedNode { + public: + PropsAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void connectToView(Tag viewTag); + void disconnectFromView(Tag viewTag); + void restoreDefaultValues(); + Tag connectedViewTag() const { + return connectedViewTag_; + } + folly::dynamic props() { + std::lock_guard lock(propsMutex_); + return props_; + } + void update() override; + void update(bool forceFabricCommit); +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/RoundAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react +namespace facebook::react { +class RoundAnimatedNode : public ValueAnimatedNode { + public: + RoundAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/StyleAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +class StyleAnimatedNode final : public AnimatedNode { + public: + StyleAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; + const folly::dynamic& getProps() const noexcept { + return props_; + } +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/SubtractionAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +namespace facebook::react { +class SubtractionAnimatedNode final : public OperatorAnimatedNode { + public: + SubtractionAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager) + : OperatorAnimatedNode(tag, config, manager) {} + void update() override; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/TrackingAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} + +namespace facebook::react { +class TrackingAnimatedNode final : public AnimatedNode { + public: + TrackingAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; +}; + Tag toValueNodeId_{}; + Tag valueNodeId_{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/TransformAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} + +namespace facebook::react { +struct TransformConfig { + public: + std::string property; + Tag nodeTag; + double value; +}; +class TransformAnimatedNode final : public AnimatedNode { + public: + TransformAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + void update() override; + const folly::dynamic& getProps(); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/ValueAnimatedNode.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/renderer/animated/nodes/AnimatedNode.h} +namespace facebook::react { +using ValueListenerCallback = std::function; +class ValueAnimatedNode : public AnimatedNode { + public: + ValueAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + double getValue() const noexcept; + double getRawValue() const noexcept; + bool setRawValue(double value) noexcept; + double getOffset() const noexcept; + bool setOffset(double offset) noexcept; + void flattenOffset() noexcept; + void extractOffset() noexcept; + void setValueListener(ValueListenerCallback&& callback) noexcept; + bool getIsColorValue() const noexcept { + return isColorValue_; + } + + protected: + bool isColorValue_{false}; +}; + double offset_{0.0}; + ValueListenerCallback valueListener_{}; +}; +class OperatorAnimatedNode : public ValueAnimatedNode { + public: + OperatorAnimatedNode( + Tag tag, + const folly::dynamic& config, + NativeAnimatedNodesManager& manager); + + protected: + std::vector inputNodes_{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/primitives.h}: +namespace facebook::react::animated { +constexpr static Tag undefinedAnimatedNodeIdentifier = 0; +} + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/animated/tests/AnimationTestsBase.h}: +namespace facebook::react { +class AnimationTestsBase : public testing::Test { + public: + AnimationTestsBase() = default; + + protected: + void initNodesManager() noexcept { + nodesManager_.reset(); + nodesManager_ = std::make_shared( + [this](Tag reactTag, const folly::dynamic& changedProps) { + lastUpdatedNodeTag = reactTag; + lastCommittedProps = changedProps; + }, + [this](const std::unordered_map& nodesProps) { + if (!nodesProps.empty()) { + lastUpdatedNodeTag = nodesProps.begin()->first; + lastCommittedProps = nodesProps.begin()->second; + } + }); + } + bool nodeNeedsUpdate(Tag nodeTag) const { + return nodesManager_->updatedNodeTags_.contains(nodeTag); + } + void runAnimationFrame(double timestamp) { + nodesManager_->onAnimationFrame(timestamp); + } + std::shared_ptr nodesManager_; + folly::dynamic lastCommittedProps{folly::dynamic::object()}; + Tag lastUpdatedNodeTag{}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/scheduler/SchedulerDelegateImpl.h}: +namespace facebook::react { +class SchedulerDelegateImpl : public SchedulerDelegate { + public: + SchedulerDelegateImpl( + std::shared_ptr mountingManager) noexcept; + ~SchedulerDelegateImpl() noexcept override = default; + SchedulerDelegateImpl(SchedulerDelegateImpl&&) noexcept = default; + SchedulerDelegateImpl& operator=(SchedulerDelegateImpl&&) noexcept = default; + SchedulerDelegateImpl(const SchedulerDelegateImpl&) = delete; + SchedulerDelegateImpl& operator=(const SchedulerDelegateImpl&) = delete; +}; +}; // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/scheduler/SurfaceDelegate.h}: +namespace facebook::react { +class SurfaceDelegate { + public: + virtual ~SurfaceDelegate() = default; + virtual void createContentView(std::string appKey) = 0; + virtual bool isContentViewReady() = 0; + virtual void destroyContentView() = 0; + virtual void show() = 0; + virtual void hide() = 0; + virtual bool isShowing() = 0; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/renderer/uimanager/IMountingManager.h}: +namespace facebook::react { +using SchedulerTask = std::function; +using SchedulerTaskExecutor = std::function; +using EventEmitterListener = std::function; +class IMountingManager { + public: + IMountingManager() noexcept = default; + virtual ~IMountingManager() noexcept = default; + IMountingManager(IMountingManager&&) noexcept = default; + IMountingManager& operator=(IMountingManager&&) noexcept = default; + IMountingManager(const IMountingManager&) = delete; + IMountingManager& operator=(const IMountingManager&) = delete; + virtual void executeMount( + SurfaceId surfaceId, + MountingTransaction&& mountingTransaction) = 0; + virtual void dispatchCommand( + const ShadowView& shadowView, + const std::string& commandName, + const folly::dynamic& args) = 0; + virtual void setIsJSResponder( + const ShadowView& shadowView, + bool isJSResponder, + bool blockNativeResponder) {}; + virtual void synchronouslyUpdateViewOnUIThread( + Tag reactTag, + const folly::dynamic& changedProps) {}; + virtual void initializeAccessibilityManager() {}; + virtual void setAccessibilityFocusedView(Tag viewTag) {}; + virtual void setFocusedView(Tag viewTag) {}; + virtual void clearAccessibilityFocusedView(Tag viewTag) {}; + virtual void accessibleClickAction(Tag viewTag) {}; + virtual void accessibleScrollInDirection(Tag viewTag, int direction) {}; + virtual void accessibleSetText(Tag viewTag, const std::string& text) {}; + virtual void clearFocusedView(Tag viewTag) {}; + virtual void setAfterMountCallback( + std::function&& onAfterMount) {}; + virtual ComponentRegistryFactory getComponentRegistryFactory() { + return nullptr; + } + virtual bool hasComponent(const std::string&) { + return false; + } + virtual void setSchedulerTaskExecutor( + SchedulerTaskExecutor&& schedulerTaskExecutor) noexcept {}; + virtual void setEventEmitterListener( + std::shared_ptr listener) noexcept {}; + virtual void setUIManager(std::weak_ptr uiManager) noexcept {}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/runtime/ReactHost.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/runtime/ReactInstanceConfig.h} +namespace facebook::react { +class ReactHost { + public: + ReactHost( + ReactInstanceConfig reactInstanceConfig, + std::shared_ptr mountingManager, + std::shared_ptr runLoopObserverManager, + std::shared_ptr contextContainer, + JsErrorHandler::OnJsError onJsError, + Logger logger, + std::shared_ptr devUIDelegate = nullptr, + TurboModuleManagerDelegates turboModuleManagerDelegates = {}, + std::shared_ptr logBoxSurfaceDelegate = nullptr, + std::shared_ptr + animatedNodesManagerProvider = nullptr, + ReactInstance::BindingsInstallFunc bindingsInstallFunc = + nullptr) noexcept; + ReactHost(const ReactHost&) = delete; + ReactHost& operator=(const ReactHost&) = delete; + ReactHost(ReactHost&&) noexcept = delete; + ReactHost& operator=(ReactHost&&) noexcept = delete; + ~ReactHost() noexcept; + bool loadScript(const std::string& bundlePath, const std::string& sourcePath); + void startSurface( + SurfaceId surfaceId, + const std::string& moduleName, + const folly::dynamic& initialProps, + const LayoutConstraints& layoutConstraints, + const LayoutContext& layoutContext = {}); + void setSurfaceConstraints( + SurfaceId surfaceId, + const LayoutConstraints& layoutConstraints, + const LayoutContext& layoutContext); + void stopSurface(SurfaceId surfaceId); + void stopAllSurfaces(); + bool isSurfaceRunning(SurfaceId surfaceId) const noexcept; + std::unordered_set getRunningSurfaces() const noexcept; + void runOnScheduler(std::function&& task) const; + void runOnRuntimeScheduler( + std::function&& task, + SchedulerPriority priority = SchedulerPriority::NormalPriority) const; + void emitDeviceEvent(folly::dynamic&& args); +}; + std::unique_ptr schedulerDelegate_; + std::unique_ptr scheduler_; + std::unique_ptr surfaceManager_; + std::shared_ptr devServerHelper_; + std::shared_ptr inspector_; + std::unique_ptr packagerConnection_; + std::shared_ptr + animatedMountingOverrideDelegate_; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/runtime/ReactInstanceConfig.h}: +namespace facebook::react { +struct ReactInstanceConfig { + bool enableDebugging{false}; + std::string appId; + std::string deviceName; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/runtime/platform/cxx/PlatformTimerRegistryImpl.h}: +namespace facebook::react { +class PlatformTimerRegistryImpl : public PlatformTimerRegistry { + public: + PlatformTimerRegistryImpl() noexcept = default; + PlatformTimerRegistryImpl(const PlatformTimerRegistryImpl&) = delete; + PlatformTimerRegistryImpl& operator=(const PlatformTimerRegistryImpl&) = + delete; + PlatformTimerRegistryImpl(PlatformTimerRegistryImpl&&) noexcept = delete; + PlatformTimerRegistryImpl& operator=(PlatformTimerRegistryImpl&&) noexcept = + delete; + ~PlatformTimerRegistryImpl() noexcept override; + void createTimer(uint32_t timerId, double delayMs) override; + void deleteTimer(uint32_t timerId) override; + void createRecurringTimer(uint32_t timerID, double delayMs) override; + void setTimerManager(std::weak_ptr timerManager); +}; + double durationMs{0.0}; + bool isRecurring{false}; + }; + TaskDispatchThread taskDispatchThread_{"PlatformTimerRegistry"}; + std::weak_ptr timerManager_; + std::unordered_map timers_; + std::mutex timersMutex_; + void createTimerInternal( + uint32_t timerID, + double delayMs, + bool isRecurring = false); + void startTimer(uint32_t timerId, double delayMs); +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/threading/MessageQueueThreadImpl.h}: +namespace facebook::react { +using MessageQueueThreadFactory = + std::function()>; +constexpr char MessageQueueThreadFactoryKey[] = "MessageQueueThreadFactoryKey"; +class MessageQueueThreadImpl : public MessageQueueThread { + public: + MessageQueueThreadImpl() noexcept = default; + explicit MessageQueueThreadImpl(int priorityOffset) noexcept + : taskDispatchThread_("MessageQueue", priorityOffset) {} + ~MessageQueueThreadImpl() noexcept override = default; + void runOnQueue(std::function&& runnable) override; + void runOnQueueSync(std::function&& runnable) override; + void quitSynchronous() override; +}; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/threading/TaskDispatchThread.h}: +namespace facebook::react { +class TaskDispatchThread { + public: + using TaskFn = std::function; + using TimePoint = std::chrono::time_point; + TaskDispatchThread( + std::string threadName = "", + int priorityOffset = 0) noexcept; + ~TaskDispatchThread() noexcept; + bool isOnThread() noexcept; + bool isRunning() noexcept; + void runAsync( + TaskFn&& task, + std::chrono::milliseconds delayMs = + std::chrono::milliseconds::zero()) noexcept; + void runSync(TaskFn&& task) noexcept; + void quit() noexcept; + + protected: + struct Task { + TimePoint dispatchTime; + TaskFn fn; + Task(TimePoint dispatchTime, TaskFn&& fn) + : dispatchTime(dispatchTime), fn(std::move(fn)) {} + bool operator<(const Task& other) const { + return dispatchTime > other.dispatchTime; + } + }; + void loop() noexcept; + std::mutex queueLock_; + std::condition_variable loopCv_; + std::priority_queue queue_; + std::atomic running_{true}; + std::string threadName_; + std::thread thread_; +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/utils/EnumHelper.h}: +namespace std { +template +constexpr auto to_underlying(Enum e) noexcept { + return static_cast>(e); +} +} // namespace std + +/// @src {packages/react-native/ReactCxxPlatform/react/utils/PlatformRunLoopObserver.h}: +namespace facebook::react { +class PlatformRunLoopObserver : public RunLoopObserver { + public: + PlatformRunLoopObserver( + RunLoopObserver::Activity activities, + const RunLoopObserver::WeakOwner& owner) + : RunLoopObserver(activities, owner) {} + ~PlatformRunLoopObserver() override = default; + PlatformRunLoopObserver(PlatformRunLoopObserver& other) = delete; + PlatformRunLoopObserver& operator=(PlatformRunLoopObserver& other) = delete; + PlatformRunLoopObserver(PlatformRunLoopObserver&& other) = delete; + PlatformRunLoopObserver& operator=(PlatformRunLoopObserver&& other) = delete; + bool isOnRunLoopThread() const noexcept override { + return false; + } + void onRender() const noexcept { + if (auto owner = owner_.lock()) { + activityDidChange(activities_); + } + } +}; +} // namespace facebook::react + +/// @src {packages/react-native/ReactCxxPlatform/react/utils/RunLoopObserverManager.h}: +/// @dep {packages/react-native/ReactCxxPlatform/react/utils/PlatformRunLoopObserver.h} +namespace facebook::react { +class RunLoopObserverManager + : std::enable_shared_from_this { + public: + std::unique_ptr createEventBeat( + std::shared_ptr ownerBox, + RuntimeScheduler& runtimeScheduler); + void onRender() const noexcept; + void induce() const noexcept; +}; +} // namespace facebook::react