Files
react-native/packages/react-native/scripts/featureflags
Benoit Girard a5dd1be889 Fix setImmediate/clearTimeout mismatch in NativeAnimatedHelper (#46525)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46525

While debugging I noticed that my setTimout was being cleared by someone else. Upon further inspection I found NativeAnimatedHelper which was mismatching setImmediate timer handle with a clearTimeout. This isn't safe and needs to be fixed.

I used this to rename the timer to be more clear to reduce the changes of mismatches.

Changelog:
[General][Fixed] - Fix setImmediate/clearTimeout mismatch in NativeAnimatedHelper that could clear an unrelated setTimeout.

Reviewed By: javache, yungsters

Differential Revision: D62775703

fbshipit-source-id: c1669c60bd08f13a59dd6159be2f471a6c1beebd
2024-09-17 20:33:43 -07:00
..

Feature Flags

Feature flags are values that determine the behavior of specific parts of React Native. This directory contains the configuration for those values, and scripts to generate files for different languages to access and customize them.

There are 2 types of feature flags:

  • Common: can be accessed from any language and they provide consistent values everywhere.
  • JS-only: they can only be accessed and customized from JavaScript.

Definition

The source of truth for the definition of the flags is the file ReactNativeFeatureFlags.config.js in this directory.

Example contents:

module.exports = {
  common: {
    enableMicrotasks: {
      description: 'Enable the use of microtasks in the JS runtime.',
      defaultValue: false
    }
  },
  jsOnly: {
    enableAccessToHostTreeInFabric: {
      description: 'Enables access to the host tree in Fabric using DOM-compatible APIs.',
      defaultValue: false
    }
  }
};

After any change to these definitions, the code that provides access to them must be regenerated running this from the react-native repository:

yarn featureflags-update

Access

You can access the common feature flags from anywhere in your application using the ReactNativeFeatureFlags interface (available in C++/Objective-C++, Kotlin/Java and JavaScript). JS-only feature flags can only be accessed from JavaScript.

Accessing feature flags should be considered fast for all use cases. Feature flags are cached at every layer, which prevents having to go through JNI when accessing the values from Kotlin and through JSI when accessing the values from JavaScript.

C++ / Objective-C

#include <react/featureflags/ReactNativeFeatureFlags.h>

if (ReactNativeFeatureFlags::enableMicrotasks()) {
  // do something
}

Kotlin

import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags

fun someMethod() {
  if (ReactNativeFeatureFlags.enableMicrotasks()) {
    // do something
  }
}

JavaScript

import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';

if (ReactNativeFeatureFlags.enableMicrotasks()) {
  // Native flag
}

if (ReactNativeFeatureFlags.enableAccessToHostTreeInFabric()) {
  // JS-only flag
}

Customization

Feature flags provide the default values defined in the configuration unless overrides are applied at the application level. Overrides for common feature flags can only be defined in native, while overrides for JS-ony flags can only be defined in JavaScript.

Overrides must be applied before any of the available feature flags has been accessed. This prevents having inconsistent behavior during the lifecycle of the application.

C++/Objective-C

#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/featureflags/ReactNativeFeatureFlagsDefaults.h>

class CustomReactNativeFeatureFlags : public ReactNativeFeatureFlagsDefaults {
 public:
  CustomReactNativeFeatureFlags();

  bool enableMicrotasks() override {
    return true;
  }
}

ReactNativeFeatureFlags::override(std::make_unique<CustomReactNativeFeatureFlags>());

Kotlin

import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlagsDefaults

fun overrideFeatureFlags() {
  ReactNativeFeatureFlags.override(object : ReactNativeFeatureFlagsDefaults() {
    override fun useMicrotasks(): Boolean = true
  })
}

JavaScript

import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';

ReactNativeFeatureFlags.override({
  enableAccessToHostTreeInFabric: () => true,
});

Architecture

The architecture of this feature flags system can be described as follows:

  • A shared C++ core, where we provide access to the flags and allow customizations.
  • A Kotlin/Java interface that allows accessing and customizing the values in the C++ core (via JNI).
  • A JavaScript interface that allows accessing the common values (via a native module) and accessing and customizing the JS-only values.

Diagram of the architecture of feature flags in React Native

This image has an embedded Excalidraw diagram, so you can upload it there if you need to make further modifications.