Skip to content

Under RN_STRICT_API no feature-flag header is public, so a library cannot read a flag and an app cannot override one #59982

Open

Description

@YevheniiKotyrlo

Description

Every header in react/featureflags/ but ReactNativePublicFeatureFlags.h includes react/cxxstableapi/PrivateGuard.h, which is an #error once a build defines RN_STRICT_API. ReactNativePublicFeatureFlags.h declares ReactNativeFeatureFlags_DO_NOT_USE with seven flags and no way to override one. So with the strict C++ API on:

  • a library whose Fabric code must agree with a flag (preventShadowTreeCommitExhaustion, enableFabricCommitBranching, updateRuntimeShadowNodeReferencesOnCommit, cxxNativeAnimatedEnabled, enableFlexboxAutoMinSizeInStrictMode) has no header it may include to read it;
  • an app has no header it may include to override a flag through ReactNativeFeatureFlagsOverridesOSSExperimental or ReactNativeFeatureFlags::override.

0.88.1 has the <React/FeatureFlags.h> umbrella for both; #58744 removed it and made the module private, from 0.89.0-rc.0.

Expected: a consumer that defines RN_STRICT_API can read every flag and override flags through a header the guards accept. Builds without RN_STRICT_API stay as they are.

Steps to reproduce

  1. Clone the reproducer below. ReproducerApp/cpp/FlagReader.cpp reads the five flags above through <react/featureflags/ReactNativeFeatureFlags.h>; ReproducerApp/cpp/FlagOverrides.cpp overrides one with a ReactNativeFeatureFlagsOverridesOSSExperimental subclass and ReactNativeFeatureFlags::override.
  2. Run its repro.sh:
    docker run --rm -v "$PWD:/repro:ro" gcc:15 bash /repro/repro.sh
    It sparse-clones react/react-native at main and compiles both files against its ReactCommon with -fsyntax-only, once plain and once with -DRN_STRICT_API. bash repro.sh v0.89.0-rc.1 does the same on the release candidate.
  3. Expected: both files compile with -DRN_STRICT_API, or a public header offers the same reads and the override. Actual: both compile without it and stop on the private-header #error with it, and the public header declares none of the five flags:
    react/react-native de7e643aa30b4e87376898b74037bd9712e9d4d6
    == which flags ReactNativePublicFeatureFlags.h declares
    class ReactNativeFeatureFlags_DO_NOT_USE {
    preventShadowTreeCommitExhaustion: not declared
    enableFabricCommitBranching: not declared
    updateRuntimeShadowNodeReferencesOnCommit: not declared
    cxxNativeAnimatedEnabled: not declared
    enableFlexboxAutoMinSizeInStrictMode: not declared
    == FlagReader.cpp without RN_STRICT_API
    compiles
    == FlagReader.cpp with -DRN_STRICT_API
    react/cxxstableapi/PrivateGuard.h:32:2: error: #error "This is a private React Native header and is not part of the public API. Do not include it directly; it has no stability guarantee."
    == FlagOverrides.cpp without RN_STRICT_API
    compiles
    == FlagOverrides.cpp with -DRN_STRICT_API
    react/cxxstableapi/PrivateGuard.h:32:2: error: #error "This is a private React Native header and is not part of the public API. Do not include it directly; it has no stability guarantee."
    SUMMARY: under RN_STRICT_API 2 of 2 files stop on the private-header #error: no feature-flag header is public (react/react-native de7e643aa3)
    
    The script exits 1 while a strict compile stops on that #error and 0 once both compile.

React Native Version

0.89.0-rc.1

Affected Platforms

Build - Linux, Build - Windows

Areas

Fabric - The New Renderer

Output of npx @react-native-community/cli info

System:
  OS: Linux 6.18 Debian GNU/Linux 13 (trixie) 13 (trixie)
  CPU: (24) x64 AMD Ryzen 9 9950X3D 16-Core Processor
  Memory: 120.35 GB / 125.63 GB
  Shell:
    version: 5.2.37
    path: /bin/bash
Binaries:
  Node:
    version: 24.22.3
    path: /usr/bin/node
  Yarn: Not Found
  npm:
    version: 11.19.1
    path: /usr/bin/npm
  Watchman: Not Found
SDKs:
  Android SDK: Not Found
IDEs:
  Android Studio: Not Found
Languages:
  Java: Not Found
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli":
    installed: 21.0.0
    wanted: ^21.0.0
  react: Not Found
  react-native:
    installed: 0.89.0-rc.1
    wanted: ^0.89.0-rc.1
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: Not found
  newArchEnabled: Not found
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

Stacktrace or Logs

react/cxxstableapi/PrivateGuard.h:32:2: error: #error "This is a private React Native header and is not part of the public API. Do not include it directly; it has no stability guarantee."

MANDATORY Reproducer

https://github.com/YevheniiKotyrlo/react-native-feature-flags-under-strict-cxx-api

Screenshots and Videos

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions