diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativePublicFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativePublicFeatureFlags.cpp new file mode 100644 index 000000000000..ee4ccaf72737 --- /dev/null +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativePublicFeatureFlags.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<<95f86b3476aeff097f532b10cabf067e>> + */ + +/** + * IMPORTANT: Do NOT modify this file directly. + * + * To change the definition of the flags, edit + * packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js. + * + * To regenerate this code, run the following script from the repo root: + * yarn featureflags --update + */ + +#include "ReactNativeFeatureFlags.h" +#include "ReactNativePublicFeatureFlags.h" + +namespace facebook::react { + +bool ReactNativeFeatureFlags_DO_NOT_USE::enableAccumulatedUpdatesInRawPropsAndroid() { + return ReactNativeFeatureFlags::enableAccumulatedUpdatesInRawPropsAndroid(); +} + +bool ReactNativeFeatureFlags_DO_NOT_USE::enableCppPropsIteratorSetter() { + return ReactNativeFeatureFlags::enableCppPropsIteratorSetter(); +} + +bool ReactNativeFeatureFlags_DO_NOT_USE::enableExclusivePropsUpdateAndroid() { + return ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid(); +} + +bool ReactNativeFeatureFlags_DO_NOT_USE::enableNativeCSSParsing() { + return ReactNativeFeatureFlags::enableNativeCSSParsing(); +} + +bool ReactNativeFeatureFlags_DO_NOT_USE::enablePropsUpdateReconciliationAndroid() { + return ReactNativeFeatureFlags::enablePropsUpdateReconciliationAndroid(); +} + +bool ReactNativeFeatureFlags_DO_NOT_USE::useSharedAnimatedBackend() { + return ReactNativeFeatureFlags::useSharedAnimatedBackend(); +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativePublicFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativePublicFeatureFlags.h new file mode 100644 index 000000000000..f8c27e60c167 --- /dev/null +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativePublicFeatureFlags.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<<39037a69a47b86d0c6643d90f4058002>> + */ + +/** + * IMPORTANT: Do NOT modify this file directly. + * + * To change the definition of the flags, edit + * packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js. + * + * To regenerate this code, run the following script from the repo root: + * yarn featureflags --update + */ + +#pragma once + +#include + +#ifndef RN_EXPORT +#define RN_EXPORT __attribute__((visibility("default"))) +#endif + +namespace facebook::react { + +/** + * This class provides public access to select internal React Native feature flags. + */ +class ReactNativeFeatureFlags_DO_NOT_USE { + public: + /** + * When enabled, Android will accumulate updates in rawProps to reduce the number of mounting instructions for cascading re-renders. + */ + RN_EXPORT static bool enableAccumulatedUpdatesInRawPropsAndroid(); + + /** + * Enable prop iterator setter-style construction of Props in C++ (this flag is not used in Java). + */ + RN_EXPORT static bool enableCppPropsIteratorSetter(); + + /** + * When enabled, Android will disable Props 1.5 raw value merging when Props 2.0 is available. + */ + RN_EXPORT static bool enableExclusivePropsUpdateAndroid(); + + /** + * Parse CSS strings using the Fabric CSS parser instead of ViewConfig processing + */ + RN_EXPORT static bool enableNativeCSSParsing(); + + /** + * When enabled, Android will receive prop updates based on the differences between the last rendered shadow node and the last committed shadow node. + */ + RN_EXPORT static bool enablePropsUpdateReconciliationAndroid(); + + /** + * Use shared animation backend in C++ Animated + */ + RN_EXPORT static bool useSharedAnimatedBackend(); +}; + +} // namespace facebook::react diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index b7e56a770ebe..9d776f20b10e 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -181,6 +181,7 @@ const definitions: FeatureFlagDefinitions = { ossReleaseStage: 'canary', }, enableAccumulatedUpdatesInRawPropsAndroid: { + dangerouslyExposeInPublicCppHeaders: true, defaultValue: false, metadata: { dateAdded: '2024-12-10', @@ -233,6 +234,7 @@ const definitions: FeatureFlagDefinitions = { ossReleaseStage: 'none', }, enableCppPropsIteratorSetter: { + dangerouslyExposeInPublicCppHeaders: true, defaultValue: false, metadata: { dateAdded: '2024-09-13', @@ -287,6 +289,7 @@ const definitions: FeatureFlagDefinitions = { ossReleaseStage: 'none', }, enableExclusivePropsUpdateAndroid: { + dangerouslyExposeInPublicCppHeaders: true, defaultValue: false, metadata: { dateAdded: '2025-11-11', @@ -517,6 +520,7 @@ const definitions: FeatureFlagDefinitions = { ossReleaseStage: 'none', }, enableNativeCSSParsing: { + dangerouslyExposeInPublicCppHeaders: true, defaultValue: false, metadata: { dateAdded: '2025-02-07', @@ -538,6 +542,7 @@ const definitions: FeatureFlagDefinitions = { ossReleaseStage: 'none', }, enablePropsUpdateReconciliationAndroid: { + dangerouslyExposeInPublicCppHeaders: true, defaultValue: false, metadata: { dateAdded: '2024-07-12', @@ -923,6 +928,7 @@ const definitions: FeatureFlagDefinitions = { ossReleaseStage: 'none', }, useSharedAnimatedBackend: { + dangerouslyExposeInPublicCppHeaders: true, defaultValue: false, metadata: { dateAdded: '2025-08-02', diff --git a/packages/react-native/scripts/featureflags/generateCommonCxxModules.js b/packages/react-native/scripts/featureflags/generateCommonCxxModules.js index d46aceb40a45..c6530b23c772 100644 --- a/packages/react-native/scripts/featureflags/generateCommonCxxModules.js +++ b/packages/react-native/scripts/featureflags/generateCommonCxxModules.js @@ -18,6 +18,8 @@ import ReactNativeFeatureFlagsDefaultsH from './templates/common-cxx/ReactNative import ReactNativeFeatureFlagsDynamicProviderH from './templates/common-cxx/ReactNativeFeatureFlagsDynamicProvider.h-template'; import ReactNativeFeatureFlagsOverrides from './templates/common-cxx/ReactNativeFeatureFlagsOverridesOSS_Stage_.h-template'; import ReactNativeFeatureFlagsProviderH from './templates/common-cxx/ReactNativeFeatureFlagsProvider.h-template'; +import ReactNativePublicFeatureFlagsCPP from './templates/common-cxx/ReactNativePublicFeatureFlags.cpp-template'; +import ReactNativePublicFeatureFlagsH from './templates/common-cxx/ReactNativePublicFeatureFlags.h-template'; import path from 'node:path'; export default function generateCommonCxxModules( @@ -30,6 +32,10 @@ export default function generateCommonCxxModules( ReactNativeFeatureFlagsH(featureFlagDefinitions), [path.join(commonCxxPath, 'ReactNativeFeatureFlags.cpp')]: ReactNativeFeatureFlagsCPP(featureFlagDefinitions), + [path.join(commonCxxPath, 'ReactNativePublicFeatureFlags.h')]: + ReactNativePublicFeatureFlagsH(featureFlagDefinitions), + [path.join(commonCxxPath, 'ReactNativePublicFeatureFlags.cpp')]: + ReactNativePublicFeatureFlagsCPP(featureFlagDefinitions), [path.join(commonCxxPath, 'ReactNativeFeatureFlagsAccessor.h')]: ReactNativeFeatureFlagsAccessorH(featureFlagDefinitions), [path.join(commonCxxPath, 'ReactNativeFeatureFlagsAccessor.cpp')]: diff --git a/packages/react-native/scripts/featureflags/generateFiles.js b/packages/react-native/scripts/featureflags/generateFiles.js index ead6d67e2288..ddcccbb94594 100644 --- a/packages/react-native/scripts/featureflags/generateFiles.js +++ b/packages/react-native/scripts/featureflags/generateFiles.js @@ -34,7 +34,18 @@ export default function generateFiles( ...generatorConfig.featureFlagDefinitions, common: Object.fromEntries( Object.entries(generatorConfig.featureFlagDefinitions.common).filter( - ([_, definition]) => !definition.skipNativeAPI, + ([name, definition]) => { + if ( + definition.skipNativeAPI && + definition.dangerouslyExposeInPublicCppHeaders + ) { + throw new Error( + `${name} cannot have both skipNativeAPI and dangerouslyExposeInPublicCppHeaders enabled at the same time.`, + ); + } + + return !definition.skipNativeAPI; + }, ), ), }, diff --git a/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativePublicFeatureFlags.cpp-template.js b/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativePublicFeatureFlags.cpp-template.js new file mode 100644 index 000000000000..cc5934aa6769 --- /dev/null +++ b/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativePublicFeatureFlags.cpp-template.js @@ -0,0 +1,47 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import type {FeatureFlagDefinitions} from '../../types'; + +import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils'; +import signedsource from 'signedsource'; + +export default function (definitions: FeatureFlagDefinitions): string { + return signedsource.signFile(`/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * ${signedsource.getSigningToken()} + */ + +${DO_NOT_MODIFY_COMMENT} + +#include "ReactNativeFeatureFlags.h" +#include "ReactNativePublicFeatureFlags.h" + +namespace facebook::react { + +${Object.entries(definitions.common) + .filter(([_, flagConfig]) => flagConfig.dangerouslyExposeInPublicCppHeaders) + .map( + ([flagName, flagConfig]) => + `${getCxxTypeFromDefaultValue( + flagConfig.defaultValue, + )} ReactNativeFeatureFlags_DO_NOT_USE::${flagName}() { + return ReactNativeFeatureFlags::${flagName}(); +}`, + ) + .join('\n\n')} + +} // namespace facebook::react +`); +} diff --git a/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativePublicFeatureFlags.h-template.js b/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativePublicFeatureFlags.h-template.js new file mode 100644 index 000000000000..920405706b2e --- /dev/null +++ b/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativePublicFeatureFlags.h-template.js @@ -0,0 +1,57 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import type {FeatureFlagDefinitions} from '../../types'; + +import {DO_NOT_MODIFY_COMMENT, getCxxTypeFromDefaultValue} from '../../utils'; +import signedsource from 'signedsource'; + +export default function (definitions: FeatureFlagDefinitions): string { + return signedsource.signFile(`/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * ${signedsource.getSigningToken()} + */ + +${DO_NOT_MODIFY_COMMENT} + +#pragma once + +#include + +#ifndef RN_EXPORT +#define RN_EXPORT __attribute__((visibility("default"))) +#endif + +namespace facebook::react { + +/** + * This class provides public access to select internal React Native feature flags. + */ +class ReactNativeFeatureFlags_DO_NOT_USE { + public: +${Object.entries(definitions.common) + .filter(([_, flagConfig]) => flagConfig.dangerouslyExposeInPublicCppHeaders) + .map( + ([flagName, flagConfig]) => + ` /** + * ${flagConfig.metadata.description} + */ + RN_EXPORT static ${getCxxTypeFromDefaultValue(flagConfig.defaultValue)} ${flagName}();`, + ) + .join('\n\n')} +}; + +} // namespace facebook::react +`); +} diff --git a/packages/react-native/scripts/featureflags/types.js b/packages/react-native/scripts/featureflags/types.js index acec7193a8ae..b072a8e05555 100644 --- a/packages/react-native/scripts/featureflags/types.js +++ b/packages/react-native/scripts/featureflags/types.js @@ -34,6 +34,8 @@ export type CommonFeatureFlagConfig< // Indicates if this API should only be defined in JavaScript, only to // preserve backwards compatibility with existing native code temporarily. skipNativeAPI?: true, + // Whether this flag should be exposed by the public feature flags entrypoint. + dangerouslyExposeInPublicCppHeaders?: true, }>; export type CommonFeatureFlagList = Readonly<{