Back out "Implement new feature flag system"
Summary: Original commit changeset: 0ba95803f61e Original Phabricator Diff: D52806730 bypass-github-export-checks changelog: [internal] internal Reviewed By: yungsters Differential Revision: D53113947 fbshipit-source-id: ace1222a861a739fcd3f4b0e12c135db47a93344
This commit is contained in:
Родитель
31a8bc9644
Коммит
ffaeaba213
|
@ -21,8 +21,6 @@
|
|||
"flow": "flow",
|
||||
"format-check": "prettier --list-different \"./**/*.{js,md,yml,ts,tsx}\"",
|
||||
"format": "npm run prettier && npm run clang-format",
|
||||
"featureflags-check": "cd packages/react-native && yarn featureflags-check",
|
||||
"featureflags-update": "cd packages/react-native && yarn featureflags-update",
|
||||
"lint-ci": "./scripts/circleci/analyze_code.sh && yarn shellcheck",
|
||||
"lint-java": "node ./scripts/lint-java.js",
|
||||
"lint": "eslint .",
|
||||
|
|
|
@ -129,7 +129,6 @@ Pod::Spec.new do |s|
|
|||
s.dependency "React-jsi"
|
||||
s.dependency "React-jsiexecutor"
|
||||
s.dependency "React-utils"
|
||||
s.dependency "React-featureflags"
|
||||
s.dependency "SocketRocket", socket_rocket_version
|
||||
s.dependency "React-runtimescheduler"
|
||||
s.dependency "Yoga"
|
||||
|
|
|
@ -526,7 +526,6 @@ android {
|
|||
"runtimeexecutor",
|
||||
"react_codegen_rncore",
|
||||
"react_debug",
|
||||
"react_featureflags",
|
||||
"react_utils",
|
||||
"react_render_componentregistry",
|
||||
"react_newarchdefaults",
|
||||
|
@ -541,7 +540,6 @@ android {
|
|||
"jsi",
|
||||
"glog",
|
||||
"fabricjni",
|
||||
"featureflagsjni",
|
||||
"react_render_mapbuffer",
|
||||
"yoga",
|
||||
"folly_runtime",
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* 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<<c201b2b577ab4aa4bf6071d6b99b43c9>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
/**
|
||||
* This object provides access to internal React Native feature flags.
|
||||
*
|
||||
* All the methods are thread-safe if you handle `override` correctly.
|
||||
*/
|
||||
object ReactNativeFeatureFlags {
|
||||
private var accessorProvider: () -> ReactNativeFeatureFlagsAccessor = { ReactNativeFeatureFlagsCxxAccessor() }
|
||||
private var accessor: ReactNativeFeatureFlagsAccessor = accessorProvider()
|
||||
|
||||
/**
|
||||
* Common flag for testing. Do NOT modify.
|
||||
*/
|
||||
fun commonTestFlag() = accessor.commonTestFlag()
|
||||
|
||||
/**
|
||||
* Overrides the feature flags with the ones provided by the given provider
|
||||
* (generally one that extends `ReactNativeFeatureFlagsDefaults`).
|
||||
*
|
||||
* This method must be called before you initialize the React Native runtime.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```
|
||||
* ReactNativeFeatureFlags.override(object : ReactNativeFeatureFlagsDefaults() {
|
||||
* override fun someFlag(): Boolean = true // or a dynamic value
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
fun override(provider: ReactNativeFeatureFlagsProvider) = accessor.override(provider)
|
||||
|
||||
/**
|
||||
* Removes the overridden feature flags and makes the API return default
|
||||
* values again.
|
||||
*
|
||||
* This should only be called if you destroy the React Native runtime and
|
||||
* need to create a new one with different overrides. In that case,
|
||||
* call `dangerouslyReset` after destroying the runtime and `override`
|
||||
* again before initializing the new one.
|
||||
*/
|
||||
fun dangerouslyReset() {
|
||||
// This is necessary when the accessor interops with C++ and we need to
|
||||
// remove the overrides set there.
|
||||
accessor.dangerouslyReset()
|
||||
|
||||
// This discards the cached values and the overrides set in the JVM.
|
||||
accessor = accessorProvider()
|
||||
}
|
||||
|
||||
/**
|
||||
* This is just used to replace the default ReactNativeFeatureFlagsCxxAccessor
|
||||
* that uses JNI with a version that doesn't, to simplify testing.
|
||||
*/
|
||||
internal fun setAccessorProvider(newAccessorProvider: () -> ReactNativeFeatureFlagsAccessor) {
|
||||
accessorProvider = newAccessorProvider
|
||||
accessor = accessorProvider()
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
interface ReactNativeFeatureFlagsAccessor : ReactNativeFeatureFlagsProvider {
|
||||
fun override(provider: ReactNativeFeatureFlagsProvider)
|
||||
|
||||
fun dangerouslyReset()
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* 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<<961f1fb0a7ad802a492437f15b1f2dcb>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor {
|
||||
private var commonTestFlagCache: Boolean? = null
|
||||
|
||||
override fun commonTestFlag(): Boolean {
|
||||
var cached = commonTestFlagCache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.commonTestFlag()
|
||||
commonTestFlagCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun override(provider: ReactNativeFeatureFlagsProvider) =
|
||||
ReactNativeFeatureFlagsCxxInterop.override(provider as Any)
|
||||
|
||||
override fun dangerouslyReset() = ReactNativeFeatureFlagsCxxInterop.dangerouslyReset()
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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<<c2e41ac8c3d9471b4cb79f6147cc2bf2>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
@DoNotStrip
|
||||
object ReactNativeFeatureFlagsCxxInterop {
|
||||
init {
|
||||
SoLoader.loadLibrary("reactfeatureflagsjni")
|
||||
}
|
||||
|
||||
@DoNotStrip @JvmStatic external fun commonTestFlag(): Boolean
|
||||
|
||||
@DoNotStrip @JvmStatic external fun override(provider: Any)
|
||||
|
||||
@DoNotStrip @JvmStatic external fun dangerouslyReset()
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* 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<<aa1eaeee7b715e5b1d3cbcf9b7a7062e>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvider {
|
||||
// We could use JNI to get the defaults from C++,
|
||||
// but that is more expensive than just duplicating the defaults here.
|
||||
|
||||
override fun commonTestFlag(): Boolean = false
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
object ReactNativeFeatureFlagsForTests {
|
||||
fun setUp() {
|
||||
ReactNativeFeatureFlags.setAccessorProvider({ ReactNativeFeatureFlagsLocalAccessor() })
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* 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<<8bbd7e8cc2c50cfbf44ba6671d095f23>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAccessor {
|
||||
private var currentProvider: ReactNativeFeatureFlagsProvider = ReactNativeFeatureFlagsDefaults()
|
||||
|
||||
private val accessedFeatureFlags = mutableSetOf<String>()
|
||||
|
||||
private var commonTestFlagCache: Boolean? = null
|
||||
|
||||
override fun commonTestFlag(): Boolean {
|
||||
var cached = commonTestFlagCache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.commonTestFlag()
|
||||
accessedFeatureFlags.add("commonTestFlag")
|
||||
commonTestFlagCache = cached
|
||||
}
|
||||
return cached
|
||||
}
|
||||
|
||||
override fun override(provider: ReactNativeFeatureFlagsProvider) {
|
||||
if (accessedFeatureFlags.isNotEmpty()) {
|
||||
val accessedFeatureFlagsStr = accessedFeatureFlags.joinToString(separator = ", ") { it }
|
||||
throw IllegalStateException(
|
||||
"Feature flags were accessed before being overridden: $accessedFeatureFlagsStr")
|
||||
}
|
||||
currentProvider = provider
|
||||
}
|
||||
|
||||
override fun dangerouslyReset() {
|
||||
// We don't need to do anything here because `ReactNativeFeatureFlags` will
|
||||
// just create a new instance of this class.
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* 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<<babb2b7b32c88b1767ac53ae97dddf10>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
interface ReactNativeFeatureFlagsProvider {
|
||||
fun commonTestFlag(): Boolean
|
||||
}
|
|
@ -70,7 +70,6 @@ add_react_common_subdir(hermes/inspector-modern)
|
|||
add_react_common_subdir(react/renderer/runtimescheduler)
|
||||
add_react_common_subdir(react/debug)
|
||||
add_react_common_subdir(react/config)
|
||||
add_react_common_subdir(react/featureflags)
|
||||
add_react_common_subdir(react/renderer/animations)
|
||||
add_react_common_subdir(react/renderer/attributedstring)
|
||||
add_react_common_subdir(react/renderer/componentregistry)
|
||||
|
@ -119,7 +118,6 @@ add_react_android_subdir(src/main/jni/react/uimanager)
|
|||
add_react_android_subdir(src/main/jni/react/mapbuffer)
|
||||
add_react_android_subdir(src/main/jni/react/reactnativeblob)
|
||||
add_react_android_subdir(src/main/jni/react/fabric)
|
||||
add_react_android_subdir(src/main/jni/react/featureflags)
|
||||
add_react_android_subdir(src/main/jni/react/newarchdefaults)
|
||||
add_react_android_subdir(src/main/jni/react/hermes/reactexecutor)
|
||||
add_react_android_subdir(src/main/jni/react/hermes/instrumentation/)
|
||||
|
|
|
@ -26,7 +26,6 @@ target_link_libraries(
|
|||
mapbufferjni
|
||||
react_codegen_rncore
|
||||
react_debug
|
||||
react_featureflags
|
||||
react_render_animations
|
||||
react_render_attributedstring
|
||||
react_render_componentregistry
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
file(GLOB featureflagsjni_SRCS CONFIGURE_DEPENDS *.cpp)
|
||||
|
||||
add_library(
|
||||
featureflagsjni
|
||||
SHARED
|
||||
${featureflagsjni_SRCS}
|
||||
)
|
||||
|
||||
target_include_directories(featureflagsjni PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_link_libraries(
|
||||
featureflagsjni
|
||||
fb
|
||||
fbjni
|
||||
react_featureflags
|
||||
reactnativejni
|
||||
)
|
||||
|
||||
target_compile_options(
|
||||
featureflagsjni
|
||||
PRIVATE
|
||||
-DLOG_TAG=\"ReactNative\"
|
||||
-fexceptions
|
||||
-frtti
|
||||
-std=c++20
|
||||
-Wall
|
||||
)
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* 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<<ad6d2d1c24334995ba197c7cc0a74dc9>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#include "JReactNativeFeatureFlagsCxxInterop.h"
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsProviderHolder.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
bool JReactNativeFeatureFlagsCxxInterop::commonTestFlag(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::commonTestFlag();
|
||||
}
|
||||
|
||||
void JReactNativeFeatureFlagsCxxInterop::override(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/,
|
||||
jni::alias_ref<jobject> provider) {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsProviderHolder>(provider));
|
||||
}
|
||||
|
||||
void JReactNativeFeatureFlagsCxxInterop::dangerouslyReset(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
ReactNativeFeatureFlags::dangerouslyReset();
|
||||
}
|
||||
|
||||
void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
javaClassLocal()->registerNatives({
|
||||
makeNativeMethod(
|
||||
"override", JReactNativeFeatureFlagsCxxInterop::override),
|
||||
makeNativeMethod("dangerouslyReset", JReactNativeFeatureFlagsCxxInterop::dangerouslyReset),
|
||||
makeNativeMethod(
|
||||
"commonTestFlag",
|
||||
JReactNativeFeatureFlagsCxxInterop::commonTestFlag),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* 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<<c759720f6c5f9b884f3eee8f3c104526>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class JReactNativeFeatureFlagsCxxInterop
|
||||
: public jni::JavaClass<JReactNativeFeatureFlagsCxxInterop> {
|
||||
public:
|
||||
constexpr static auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop;";
|
||||
|
||||
static bool commonTestFlag(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static void override(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>,
|
||||
jni::alias_ref<jobject> provider);
|
||||
|
||||
static void dangerouslyReset(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static void registerNatives();
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include "JReactNativeFeatureFlagsCxxInterop.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
|
||||
return facebook::jni::initialize(vm, [] {
|
||||
facebook::react::JReactNativeFeatureFlagsCxxInterop::registerNatives();
|
||||
});
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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<<7a019bd967a22f93cd9e2e0ddb5201e3>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#include "ReactNativeFeatureFlagsProviderHolder.h"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
bool ReactNativeFeatureFlagsProviderHolder::commonTestFlag() {
|
||||
static const auto method =
|
||||
facebook::jni::findClassStatic(
|
||||
"com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider")
|
||||
->getMethod<jboolean()>("commonTestFlag");
|
||||
return method(javaProvider_);
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* 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<<9a2d162cbd83f3b5122d0eb86f6f9177>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* Implementation of ReactNativeFeatureFlagsProvider that wraps a
|
||||
* ReactNativeFeatureFlagsProvider Java object.
|
||||
*/
|
||||
class ReactNativeFeatureFlagsProviderHolder
|
||||
: public ReactNativeFeatureFlagsProvider {
|
||||
public:
|
||||
explicit ReactNativeFeatureFlagsProviderHolder(
|
||||
jni::alias_ref<jobject> javaProvider)
|
||||
: javaProvider_(make_global(javaProvider)){};
|
||||
|
||||
bool commonTestFlag() override;
|
||||
|
||||
private:
|
||||
jni::global_ref<jobject> javaProvider_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -17,7 +17,6 @@ target_include_directories(react_newarchdefaults PUBLIC .)
|
|||
target_link_libraries(react_newarchdefaults
|
||||
fbjni
|
||||
fabricjni
|
||||
featureflagsjni
|
||||
react_nativemodule_core
|
||||
react_codegen_rncore
|
||||
react_cxxreactpackage
|
||||
|
|
|
@ -23,7 +23,6 @@ target_include_directories(rninstance PUBLIC .)
|
|||
target_link_libraries(
|
||||
rninstance
|
||||
fabricjni
|
||||
featureflagsjni
|
||||
turbomodulejsijni
|
||||
fb
|
||||
jsi
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
add_compile_options(
|
||||
-fexceptions
|
||||
-frtti
|
||||
-std=c++20
|
||||
-Wall
|
||||
-Wpedantic
|
||||
-DLOG_TAG=\"ReactNative\")
|
||||
|
||||
file(GLOB react_featureflags_SRC CONFIGURE_DEPENDS *.cpp)
|
||||
add_library(react_featureflags SHARED ${react_featureflags_SRC})
|
||||
|
||||
target_include_directories(react_featureflags PUBLIC ${REACT_COMMON_DIR})
|
|
@ -1,44 +0,0 @@
|
|||
# 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.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1")
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
header_search_paths = []
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../..\"" # this is needed to allow the feature flags access its own files
|
||||
end
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-featureflags"
|
||||
s.version = version
|
||||
s.summary = "React Native internal feature flags"
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Meta Platforms, Inc. and its affiliates"
|
||||
s.platforms = min_supported_versions
|
||||
s.source = source
|
||||
s.source_files = "*.{cpp,h}"
|
||||
s.header_dir = "react/featureflags"
|
||||
s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
|
||||
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
|
||||
"DEFINES_MODULE" => "YES" }
|
||||
|
||||
if ENV['USE_FRAMEWORKS']
|
||||
s.module_name = "React_featureflags"
|
||||
s.header_mappings_dir = "../.."
|
||||
end
|
||||
end
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* 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<<85960128b845159e7de70d0e85910dd9>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#include "ReactNativeFeatureFlags.h"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
bool ReactNativeFeatureFlags::commonTestFlag() {
|
||||
return getAccessor().commonTestFlag();
|
||||
}
|
||||
|
||||
void ReactNativeFeatureFlags::override(
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
|
||||
getAccessor().override(std::move(provider));
|
||||
}
|
||||
|
||||
void ReactNativeFeatureFlags::dangerouslyReset() {
|
||||
getAccessor(true);
|
||||
}
|
||||
|
||||
ReactNativeFeatureFlagsAccessor& ReactNativeFeatureFlags::getAccessor(
|
||||
bool reset) {
|
||||
static std::unique_ptr<ReactNativeFeatureFlagsAccessor> accessor;
|
||||
if (accessor == nullptr || reset) {
|
||||
accessor = std::make_unique<ReactNativeFeatureFlagsAccessor>();
|
||||
}
|
||||
return *accessor;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* 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<<a4d59ac4d6a845349ffff6ba463fdf80>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsAccessor.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsProvider.h>
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* This class provides access to internal React Native feature flags.
|
||||
*
|
||||
* All the methods are thread-safe if you handle `override` correctly.
|
||||
*/
|
||||
class ReactNativeFeatureFlags {
|
||||
public:
|
||||
/**
|
||||
* Common flag for testing. Do NOT modify.
|
||||
*/
|
||||
static bool commonTestFlag();
|
||||
|
||||
/**
|
||||
* Overrides the feature flags with the ones provided by the given provider
|
||||
* (generally one that extends `ReactNativeFeatureFlagsDefaults`).
|
||||
*
|
||||
* This method must be called before you initialize the React Native runtime.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```
|
||||
* class MyReactNativeFeatureFlags : public ReactNativeFeatureFlagsDefaults {
|
||||
* public:
|
||||
* bool someFlag() override;
|
||||
* };
|
||||
*
|
||||
* ReactNativeFeatureFlags.override(
|
||||
* std::make_unique<MyReactNativeFeatureFlags>());
|
||||
* ```
|
||||
*/
|
||||
static void override(
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
|
||||
|
||||
/**
|
||||
* Removes the overridden feature flags and makes the API return default
|
||||
* values again.
|
||||
*
|
||||
* This is **dangerous**. Use it only if you really understand the
|
||||
* implications of this method.
|
||||
*
|
||||
* This should only be called if you destroy the React Native runtime and
|
||||
* need to create a new one with different overrides. In that case,
|
||||
* call `dangerouslyReset` after destroying the runtime and `override` again
|
||||
* before initializing the new one.
|
||||
*/
|
||||
static void dangerouslyReset();
|
||||
|
||||
private:
|
||||
ReactNativeFeatureFlags() = delete;
|
||||
static ReactNativeFeatureFlagsAccessor& getAccessor(bool reset = false);
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* 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<<7f8b2ae5c0b18aceeaac0ee60e53bdbb>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsDefaults.h>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include "ReactNativeFeatureFlags.h"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
ReactNativeFeatureFlagsAccessor::ReactNativeFeatureFlagsAccessor()
|
||||
: currentProvider_(std::make_unique<ReactNativeFeatureFlagsDefaults>()) {}
|
||||
|
||||
bool ReactNativeFeatureFlagsAccessor::commonTestFlag() {
|
||||
if (!commonTestFlag_.has_value()) {
|
||||
// Mark the flag as accessed.
|
||||
static const char* flagName = "commonTestFlag";
|
||||
if (std::find(
|
||||
accessedFeatureFlags_.begin(),
|
||||
accessedFeatureFlags_.end(),
|
||||
flagName) == accessedFeatureFlags_.end()) {
|
||||
accessedFeatureFlags_.push_back(flagName);
|
||||
}
|
||||
|
||||
commonTestFlag_.emplace(currentProvider_->commonTestFlag());
|
||||
}
|
||||
|
||||
return commonTestFlag_.value();
|
||||
}
|
||||
|
||||
void ReactNativeFeatureFlagsAccessor::override(
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
|
||||
if (!accessedFeatureFlags_.empty()) {
|
||||
std::ostringstream featureFlagListBuilder;
|
||||
for (const auto& featureFlagName : accessedFeatureFlags_) {
|
||||
featureFlagListBuilder << featureFlagName << ", ";
|
||||
}
|
||||
std::string accessedFeatureFlagNames = featureFlagListBuilder.str();
|
||||
if (!accessedFeatureFlagNames.empty()) {
|
||||
accessedFeatureFlagNames = accessedFeatureFlagNames.substr(
|
||||
0, accessedFeatureFlagNames.size() - 2);
|
||||
}
|
||||
|
||||
throw std::runtime_error(
|
||||
"Feature flags were accessed before being overridden: " +
|
||||
accessedFeatureFlagNames);
|
||||
}
|
||||
|
||||
currentProvider_ = std::move(provider);
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* 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<<3fa0171b372cf6aae150b2ec159fc41e>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsProvider.h>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class ReactNativeFeatureFlagsAccessor {
|
||||
public:
|
||||
ReactNativeFeatureFlagsAccessor();
|
||||
|
||||
bool commonTestFlag();
|
||||
|
||||
void override(std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
|
||||
|
||||
private:
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
|
||||
std::vector<const char*> accessedFeatureFlags_;
|
||||
|
||||
std::optional<bool> commonTestFlag_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* 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<<76033e9fb87174da88e0ee922df28701>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsProvider.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
public:
|
||||
ReactNativeFeatureFlagsDefaults() = default;
|
||||
|
||||
bool commonTestFlag() override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* 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<<20dfc971dddc23a6d0cc55938b0d65b7>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class ReactNativeFeatureFlagsProvider {
|
||||
public:
|
||||
virtual ~ReactNativeFeatureFlagsProvider() = default;
|
||||
|
||||
virtual bool commonTestFlag() = 0;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsDefaults.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
uint overrideAccessCount = 0;
|
||||
|
||||
class ReactNativeFeatureFlagsTestOverrides
|
||||
: public ReactNativeFeatureFlagsDefaults {
|
||||
public:
|
||||
bool commonTestFlag() override {
|
||||
overrideAccessCount++;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class ReactNativeFeatureFlagsTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
overrideAccessCount = 0;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ReactNativeFeatureFlagsTest, providesDefaults) {
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false);
|
||||
}
|
||||
|
||||
TEST_F(ReactNativeFeatureFlagsTest, providesOverriddenValues) {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsTestOverrides>());
|
||||
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true);
|
||||
}
|
||||
|
||||
TEST_F(ReactNativeFeatureFlagsTest, preventsOverridingAfterAccess) {
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false);
|
||||
|
||||
try {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsTestOverrides>());
|
||||
FAIL()
|
||||
<< "Expected ReactNativeFeatureFlags::override() to throw an exception";
|
||||
} catch (const std::runtime_error& e) {
|
||||
EXPECT_STREQ(
|
||||
"Feature flags were accessed before being overridden: commonTestFlag",
|
||||
e.what());
|
||||
}
|
||||
|
||||
// Overrides shouldn't be applied after they've been accessed
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false);
|
||||
}
|
||||
|
||||
TEST_F(ReactNativeFeatureFlagsTest, cachesValuesFromOverride) {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsTestOverrides>());
|
||||
|
||||
EXPECT_EQ(overrideAccessCount, 0);
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true);
|
||||
EXPECT_EQ(overrideAccessCount, 1);
|
||||
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true);
|
||||
EXPECT_EQ(overrideAccessCount, 1);
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
ReactNativeFeatureFlagsTest,
|
||||
providesDefaulValuesAgainWhenResettingAfterAnOverride) {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsTestOverrides>());
|
||||
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true);
|
||||
|
||||
ReactNativeFeatureFlags::dangerouslyReset();
|
||||
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), false);
|
||||
}
|
||||
|
||||
TEST_F(ReactNativeFeatureFlagsTest, allowsOverridingAgainAfterReset) {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsTestOverrides>());
|
||||
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true);
|
||||
|
||||
ReactNativeFeatureFlags::dangerouslyReset();
|
||||
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsTestOverrides>());
|
||||
|
||||
EXPECT_EQ(ReactNativeFeatureFlags::commonTestFlag(), true);
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* 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<<f80c7362c3d377edfcbd5cc0642c2464>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#include "NativeReactNativeFeatureFlags.h"
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
|
||||
#include "Plugins.h"
|
||||
|
||||
std::shared_ptr<facebook::react::TurboModule>
|
||||
NativeReactNativeFeatureFlagsModuleProvider(
|
||||
std::shared_ptr<facebook::react::CallInvoker> jsInvoker) {
|
||||
return std::make_shared<facebook::react::NativeReactNativeFeatureFlags>(
|
||||
std::move(jsInvoker));
|
||||
}
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
NativeReactNativeFeatureFlags::NativeReactNativeFeatureFlags(
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: NativeReactNativeFeatureFlagsCxxSpec(std::move(jsInvoker)) {}
|
||||
|
||||
bool NativeReactNativeFeatureFlags::commonTestFlag(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::commonTestFlag();
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* 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<<18a3543b75c44e00bdf73ca2f12d230c>>
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <FBReactNativeSpec/FBReactNativeSpecJSI.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class NativeReactNativeFeatureFlags
|
||||
: public NativeReactNativeFeatureFlagsCxxSpec<
|
||||
NativeReactNativeFeatureFlags>,
|
||||
std::enable_shared_from_this<NativeReactNativeFeatureFlags> {
|
||||
public:
|
||||
NativeReactNativeFeatureFlags(std::shared_ptr<CallInvoker> jsInvoker);
|
||||
|
||||
bool commonTestFlag(jsi::Runtime& runtime);
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
|
@ -30,7 +30,6 @@ target_link_libraries(
|
|||
bridgeless
|
||||
jserrorhandler
|
||||
fabricjni
|
||||
featureflagsjni
|
||||
turbomodulejsijni
|
||||
fb
|
||||
jsi
|
||||
|
|
|
@ -89,9 +89,7 @@
|
|||
"types"
|
||||
],
|
||||
"scripts": {
|
||||
"prepack": "cp ../../README.md .",
|
||||
"featureflags-check": "node ./scripts/featureflags/update.js --verify-unchanged",
|
||||
"featureflags-update": "node ./scripts/featureflags/update.js"
|
||||
"prepack": "cp ../../README.md ."
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "18.2.0"
|
||||
|
|
|
@ -556,7 +556,6 @@ class CodegenUtilsTests < Test::Unit::TestCase
|
|||
'React-Fabric': [],
|
||||
'React-FabricImage': [],
|
||||
'React-utils': [],
|
||||
'React-featureflags': [],
|
||||
'React-debug': [],
|
||||
'React-rendererdebug': [],
|
||||
})
|
||||
|
@ -570,14 +569,13 @@ class CodegenUtilsTests < Test::Unit::TestCase
|
|||
specs = get_podspec_no_fabric_no_script()
|
||||
|
||||
specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat([])
|
||||
specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers\"")
|
||||
specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\"")
|
||||
|
||||
specs[:dependencies].merge!({
|
||||
'React-graphics': [],
|
||||
'React-Fabric': [],
|
||||
'React-FabricImage': [],
|
||||
'React-utils': [],
|
||||
'React-featureflags': [],
|
||||
'React-debug': [],
|
||||
'React-rendererdebug': [],
|
||||
})
|
||||
|
|
|
@ -151,7 +151,7 @@ class NewArchitectureTests < Test::Unit::TestCase
|
|||
folly_compiler_flags = folly_config[:compiler_flags]
|
||||
|
||||
assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags)
|
||||
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fmt/include\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\"")
|
||||
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fmt/include\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\"")
|
||||
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++20")
|
||||
assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 "+ folly_compiler_flags)
|
||||
assert_equal(
|
||||
|
@ -171,7 +171,6 @@ class NewArchitectureTests < Test::Unit::TestCase
|
|||
{ :dependency_name => "React-Fabric" },
|
||||
{ :dependency_name => "React-graphics" },
|
||||
{ :dependency_name => "React-utils" },
|
||||
{ :dependency_name => "React-featureflags" },
|
||||
{ :dependency_name => "React-debug" },
|
||||
{ :dependency_name => "React-ImageManager" },
|
||||
{ :dependency_name => "React-rendererdebug" },
|
||||
|
@ -194,7 +193,7 @@ class NewArchitectureTests < Test::Unit::TestCase
|
|||
|
||||
# Assert
|
||||
assert_equal(Helpers::Constants.folly_config[:compiler_flags], "#{NewArchitectureHelper.folly_compiler_flags}")
|
||||
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fmt/include\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-featureflags/React_featureflags.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\"")
|
||||
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/Headers/Private/Yoga\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fmt/include\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-FabricImage/React_FabricImage.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers\"")
|
||||
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++20")
|
||||
assert_equal(
|
||||
spec.dependencies,
|
||||
|
@ -213,7 +212,6 @@ class NewArchitectureTests < Test::Unit::TestCase
|
|||
{ :dependency_name => "React-Fabric" },
|
||||
{ :dependency_name => "React-graphics" },
|
||||
{ :dependency_name => "React-utils" },
|
||||
{ :dependency_name => "React-featureflags" },
|
||||
{ :dependency_name => "React-debug" },
|
||||
{ :dependency_name => "React-ImageManager" },
|
||||
{ :dependency_name => "React-rendererdebug" },
|
||||
|
|
|
@ -101,7 +101,6 @@ class CodegenUtils
|
|||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-debug", "React_debug", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-rendererdebug", "React_rendererdebug", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-utils", "React_utils", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-featureflags", "React_featureflags", []))
|
||||
.each { |search_path|
|
||||
header_search_paths << "\"#{search_path}\""
|
||||
}
|
||||
|
@ -141,7 +140,6 @@ class CodegenUtils
|
|||
'React-FabricImage': [],
|
||||
'React-debug': [],
|
||||
'React-utils': [],
|
||||
'React-featureflags': [],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,6 @@ class NewArchitectureHelper
|
|||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-NativeModulesApple", "React_NativeModulesApple", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-RCTFabric", "RCTFabric", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-utils", "React_utils", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-featureflags", "React_featureflags", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-debug", "React_debug", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-ImageManager", "React_ImageManager", []))
|
||||
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-rendererdebug", "React_rendererdebug", []))
|
||||
|
@ -125,7 +124,6 @@ class NewArchitectureHelper
|
|||
spec.dependency "React-Fabric"
|
||||
spec.dependency "React-graphics"
|
||||
spec.dependency "React-utils"
|
||||
spec.dependency "React-featureflags"
|
||||
spec.dependency "React-debug"
|
||||
spec.dependency "React-ImageManager"
|
||||
spec.dependency "React-rendererdebug"
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
# 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.json`
|
||||
in this directory. That JSON file should have the following structure:
|
||||
|
||||
```flow
|
||||
type Config = {
|
||||
common: FeatureFlagsList,
|
||||
jsOnly: FeatureFlagsList,
|
||||
};
|
||||
|
||||
type FeatureFlagsList = {
|
||||
[flagName: string]: {
|
||||
description: string,
|
||||
defaultValue: boolean | number | string,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"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 changes to this definitions, the code that provides access to them
|
||||
must be regenerated executing the `update` script in this directory.
|
||||
|
||||
## Access
|
||||
|
||||
### C++ / Objective-C
|
||||
|
||||
```c++
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
|
||||
if (ReactNativeFeatureFlags::enableMicrotasks()) {
|
||||
// do something
|
||||
}
|
||||
```
|
||||
|
||||
### Kotlin
|
||||
|
||||
```kotlin
|
||||
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
||||
|
||||
fun someMethod() {
|
||||
if (ReactNativeFeatureFlags.enableMicrotasks()) {
|
||||
// do something
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### JavaScript
|
||||
|
||||
```javascript
|
||||
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
|
||||
|
||||
if (ReactNativeFeatureFlags.enableMicrotasks()) {
|
||||
// Native flag
|
||||
}
|
||||
|
||||
if (ReactNativeFeatureFlags.enableAccessToHostTreeInFabric()) {
|
||||
// JS-only flag
|
||||
}
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
### C++/Objective-C
|
||||
|
||||
```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
|
||||
|
||||
```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
|
||||
|
||||
```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](./assets/react-native-feature-flags-architecture.excalidraw-embedded.png)
|
||||
|
||||
_This image has an embedded [Excalidraw](https://www.excalidraw.com) diagram,
|
||||
so you can upload it there if you need to make further modifications._
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"common": {
|
||||
"commonTestFlag": {
|
||||
"description": "Common flag for testing. Do NOT modify.",
|
||||
"defaultValue": false
|
||||
}
|
||||
},
|
||||
"jsOnly": {
|
||||
"jsOnlyTestFlag": {
|
||||
"description": "JS-only flag for testing. Do NOT modify.",
|
||||
"defaultValue": false
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 1.0 MiB |
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const JReactNativeFeatureFlagsCxxInteropCPP = require('./templates/android/JReactNativeFeatureFlagsCxxInterop.cpp-template');
|
||||
const JReactNativeFeatureFlagsCxxInteropH = require('./templates/android/JReactNativeFeatureFlagsCxxInterop.h-template');
|
||||
const ReactNativeFeatureFlagsKt = require('./templates/android/ReactNativeFeatureFlags.kt-template');
|
||||
const ReactNativeFeatureFlagsCxxAccessorKt = require('./templates/android/ReactNativeFeatureFlagsCxxAccessor.kt-template');
|
||||
const ReactNativeFeatureFlagsCxxInteropKt = require('./templates/android/ReactNativeFeatureFlagsCxxInterop.kt-template');
|
||||
const ReactNativeFeatureFlagsDefaultsKt = require('./templates/android/ReactNativeFeatureFlagsDefaults.kt-template');
|
||||
const ReactNativeFeatureFlagsLocalAccessorKt = require('./templates/android/ReactNativeFeatureFlagsLocalAccessor.kt-template');
|
||||
const ReactNativeFeatureFlagsProviderKt = require('./templates/android/ReactNativeFeatureFlagsProvider.kt-template');
|
||||
const ReactNativeFeatureFlagsProviderHolderCPP = require('./templates/android/ReactNativeFeatureFlagsProviderHolder.cpp-template');
|
||||
const ReactNativeFeatureFlagsProviderHolderH = require('./templates/android/ReactNativeFeatureFlagsProviderHolder.h-template');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function generateandroidModules(
|
||||
generatorConfig,
|
||||
featureFlagsConfig,
|
||||
) {
|
||||
return {
|
||||
[path.join(generatorConfig.androidPath, 'ReactNativeFeatureFlags.kt')]:
|
||||
ReactNativeFeatureFlagsKt(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidPath,
|
||||
'ReactNativeFeatureFlagsCxxAccessor.kt',
|
||||
)]: ReactNativeFeatureFlagsCxxAccessorKt(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidPath,
|
||||
'ReactNativeFeatureFlagsLocalAccessor.kt',
|
||||
)]: ReactNativeFeatureFlagsLocalAccessorKt(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidPath,
|
||||
'ReactNativeFeatureFlagsCxxInterop.kt',
|
||||
)]: ReactNativeFeatureFlagsCxxInteropKt(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidPath,
|
||||
'ReactNativeFeatureFlagsDefaults.kt',
|
||||
)]: ReactNativeFeatureFlagsDefaultsKt(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidPath,
|
||||
'ReactNativeFeatureFlagsProvider.kt',
|
||||
)]: ReactNativeFeatureFlagsProviderKt(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidJniPath,
|
||||
'ReactNativeFeatureFlagsProviderHolder.h',
|
||||
)]: ReactNativeFeatureFlagsProviderHolderH(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidJniPath,
|
||||
'ReactNativeFeatureFlagsProviderHolder.cpp',
|
||||
)]: ReactNativeFeatureFlagsProviderHolderCPP(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidJniPath,
|
||||
'JReactNativeFeatureFlagsCxxInterop.h',
|
||||
)]: JReactNativeFeatureFlagsCxxInteropH(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.androidJniPath,
|
||||
'JReactNativeFeatureFlagsCxxInterop.cpp',
|
||||
)]: JReactNativeFeatureFlagsCxxInteropCPP(featureFlagsConfig),
|
||||
};
|
||||
};
|
|
@ -1,46 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const ReactNativeFeatureFlagsCPP = require('./templates/common-cxx/ReactNativeFeatureFlags.cpp-template');
|
||||
const ReactNativeFeatureFlagsH = require('./templates/common-cxx/ReactNativeFeatureFlags.h-template');
|
||||
const ReactNativeFeatureFlagsAccessorCPP = require('./templates/common-cxx/ReactNativeFeatureFlagsAccessor.cpp-template');
|
||||
const ReactNativeFeatureFlagsAccessorH = require('./templates/common-cxx/ReactNativeFeatureFlagsAccessor.h-template');
|
||||
const ReactNativeFeatureFlagsDefaultsH = require('./templates/common-cxx/ReactNativeFeatureFlagsDefaults.h-template');
|
||||
const ReactNativeFeatureFlagsProviderH = require('./templates/common-cxx/ReactNativeFeatureFlagsProvider.h-template');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function generateCommonCxxModules(
|
||||
generatorConfig,
|
||||
featureFlagsConfig,
|
||||
) {
|
||||
return {
|
||||
[path.join(generatorConfig.commonCxxPath, 'ReactNativeFeatureFlags.h')]:
|
||||
ReactNativeFeatureFlagsH(featureFlagsConfig),
|
||||
[path.join(generatorConfig.commonCxxPath, 'ReactNativeFeatureFlags.cpp')]:
|
||||
ReactNativeFeatureFlagsCPP(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.commonCxxPath,
|
||||
'ReactNativeFeatureFlagsAccessor.h',
|
||||
)]: ReactNativeFeatureFlagsAccessorH(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.commonCxxPath,
|
||||
'ReactNativeFeatureFlagsAccessor.cpp',
|
||||
)]: ReactNativeFeatureFlagsAccessorCPP(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.commonCxxPath,
|
||||
'ReactNativeFeatureFlagsDefaults.h',
|
||||
)]: ReactNativeFeatureFlagsDefaultsH(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.commonCxxPath,
|
||||
'ReactNativeFeatureFlagsProvider.h',
|
||||
)]: ReactNativeFeatureFlagsProviderH(featureFlagsConfig),
|
||||
};
|
||||
};
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
const generateAndroidModules = require('./generateAndroidModules');
|
||||
const generateCommonCxxModules = require('./generateCommonCxxModules');
|
||||
const generateJavaScriptModules = require('./generateJavaScriptModules');
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = function generateFiles(generatorConfig, generatorOptions) {
|
||||
const userDefinedFeatureFlagsConfig = JSON.parse(
|
||||
fs.readFileSync(generatorConfig.configPath, 'utf8'),
|
||||
);
|
||||
|
||||
const featureFlagsConfig = Object.assign(
|
||||
{jsOnly: {}, common: {}},
|
||||
userDefinedFeatureFlagsConfig,
|
||||
);
|
||||
|
||||
fs.mkdirSync(generatorConfig.jsPath, {recursive: true});
|
||||
fs.mkdirSync(generatorConfig.commonCxxPath, {recursive: true});
|
||||
fs.mkdirSync(generatorConfig.commonNativeModuleCxxPath, {recursive: true});
|
||||
fs.mkdirSync(generatorConfig.androidPath, {recursive: true});
|
||||
fs.mkdirSync(generatorConfig.androidJniPath, {recursive: true});
|
||||
|
||||
const jsModules = generateJavaScriptModules(
|
||||
generatorConfig,
|
||||
featureFlagsConfig,
|
||||
);
|
||||
|
||||
const commonCxxModules = generateCommonCxxModules(
|
||||
generatorConfig,
|
||||
featureFlagsConfig,
|
||||
);
|
||||
|
||||
const androidModules = generateAndroidModules(
|
||||
generatorConfig,
|
||||
featureFlagsConfig,
|
||||
);
|
||||
|
||||
const generatedFiles = {...jsModules, ...commonCxxModules, ...androidModules};
|
||||
|
||||
if (generatorOptions.verifyUnchanged) {
|
||||
const existingModules = {};
|
||||
for (const moduleName of Object.keys(generatedFiles)) {
|
||||
const existingModule = fs.readFileSync(moduleName, 'utf8');
|
||||
existingModules[moduleName] = existingModule;
|
||||
}
|
||||
|
||||
const changedFiles = [];
|
||||
for (const moduleName of Object.keys(generatedFiles)) {
|
||||
const module = generatedFiles[moduleName];
|
||||
const existingModule = existingModules[moduleName];
|
||||
|
||||
if (module !== existingModule) {
|
||||
changedFiles.push(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
if (changedFiles.length > 0) {
|
||||
const changedFilesStr = changedFiles
|
||||
.map(changedFile => ' ' + changedFile)
|
||||
.join('\n');
|
||||
|
||||
throw new Error(
|
||||
`Detected changes in generated files for feature flags:\n${changedFilesStr}\n\n` +
|
||||
'Please rerun `yarn featureflags-update` and commit the changes.',
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [modulePath, moduleContents] of Object.entries(generatedFiles)) {
|
||||
fs.writeFileSync(modulePath, moduleContents, 'utf8');
|
||||
}
|
||||
};
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const NativeReactNativeFeatureFlagsCPP = require('./templates/js/NativeReactNativeFeatureFlags.cpp-template');
|
||||
const NativeReactNativeFeatureFlagsH = require('./templates/js/NativeReactNativeFeatureFlags.h-template');
|
||||
const NativeReactNativeFeatureFlagsJS = require('./templates/js/NativeReactNativeFeatureFlags.js-template');
|
||||
const ReactNativeFeatureFlagsJS = require('./templates/js/ReactNativeFeatureFlags.js-template');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function generateCommonCxxModules(
|
||||
generatorConfig,
|
||||
featureFlagsConfig,
|
||||
) {
|
||||
return {
|
||||
[path.join(generatorConfig.jsPath, 'ReactNativeFeatureFlags.js')]:
|
||||
ReactNativeFeatureFlagsJS(featureFlagsConfig),
|
||||
[path.join(generatorConfig.jsPath, 'NativeReactNativeFeatureFlags.js')]:
|
||||
NativeReactNativeFeatureFlagsJS(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.commonNativeModuleCxxPath,
|
||||
'NativeReactNativeFeatureFlags.h',
|
||||
)]: NativeReactNativeFeatureFlagsH(featureFlagsConfig),
|
||||
[path.join(
|
||||
generatorConfig.commonNativeModuleCxxPath,
|
||||
'NativeReactNativeFeatureFlags.cpp',
|
||||
)]: NativeReactNativeFeatureFlagsCPP(featureFlagsConfig),
|
||||
};
|
||||
};
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 "JReactNativeFeatureFlagsCxxInterop.h"
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsProviderHolder.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} JReactNativeFeatureFlagsCxxInterop::${flagName}(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
return ReactNativeFeatureFlags::${flagName}();
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
void JReactNativeFeatureFlagsCxxInterop::override(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/,
|
||||
jni::alias_ref<jobject> provider) {
|
||||
ReactNativeFeatureFlags::override(
|
||||
std::make_unique<ReactNativeFeatureFlagsProviderHolder>(provider));
|
||||
}
|
||||
|
||||
void JReactNativeFeatureFlagsCxxInterop::dangerouslyReset(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
|
||||
ReactNativeFeatureFlags::dangerouslyReset();
|
||||
}
|
||||
|
||||
void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
|
||||
javaClassLocal()->registerNatives({
|
||||
makeNativeMethod(
|
||||
"override", JReactNativeFeatureFlagsCxxInterop::override),
|
||||
makeNativeMethod("dangerouslyReset", JReactNativeFeatureFlagsCxxInterop::dangerouslyReset),
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` makeNativeMethod(
|
||||
"${flagName}",
|
||||
JReactNativeFeatureFlagsCxxInterop::${flagName}),`,
|
||||
)
|
||||
.join('\n')}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,64 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <fbjni/fbjni.h>
|
||||
#include <jni.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class JReactNativeFeatureFlagsCxxInterop
|
||||
: public jni::JavaClass<JReactNativeFeatureFlagsCxxInterop> {
|
||||
public:
|
||||
constexpr static auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop;";
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` static ${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ${flagName}(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
static void override(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>,
|
||||
jni::alias_ref<jobject> provider);
|
||||
|
||||
static void dangerouslyReset(
|
||||
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);
|
||||
|
||||
static void registerNatives();
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,91 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {DO_NOT_MODIFY_COMMENT} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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}
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
/**
|
||||
* This object provides access to internal React Native feature flags.
|
||||
*
|
||||
* All the methods are thread-safe if you handle \`override\` correctly.
|
||||
*/
|
||||
object ReactNativeFeatureFlags {
|
||||
private var accessorProvider: () -> ReactNativeFeatureFlagsAccessor = { ReactNativeFeatureFlagsCxxAccessor() }
|
||||
private var accessor: ReactNativeFeatureFlagsAccessor = accessorProvider()
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` /**
|
||||
* ${flagConfig.description}
|
||||
*/
|
||||
fun ${flagName}() = accessor.${flagName}()`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
/**
|
||||
* Overrides the feature flags with the ones provided by the given provider
|
||||
* (generally one that extends \`ReactNativeFeatureFlagsDefaults\`).
|
||||
*
|
||||
* This method must be called before you initialize the React Native runtime.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* \`\`\`
|
||||
* ReactNativeFeatureFlags.override(object : ReactNativeFeatureFlagsDefaults() {
|
||||
* override fun someFlag(): Boolean = true // or a dynamic value
|
||||
* })
|
||||
* \`\`\`
|
||||
*/
|
||||
fun override(provider: ReactNativeFeatureFlagsProvider) = accessor.override(provider)
|
||||
|
||||
/**
|
||||
* Removes the overridden feature flags and makes the API return default
|
||||
* values again.
|
||||
*
|
||||
* This should only be called if you destroy the React Native runtime and
|
||||
* need to create a new one with different overrides. In that case,
|
||||
* call \`dangerouslyReset\` after destroying the runtime and \`override\`
|
||||
* again before initializing the new one.
|
||||
*/
|
||||
fun dangerouslyReset() {
|
||||
// This is necessary when the accessor interops with C++ and we need to
|
||||
// remove the overrides set there.
|
||||
accessor.dangerouslyReset()
|
||||
|
||||
// This discards the cached values and the overrides set in the JVM.
|
||||
accessor = accessorProvider()
|
||||
}
|
||||
|
||||
/**
|
||||
* This is just used to replace the default ReactNativeFeatureFlagsCxxAccessor
|
||||
* that uses JNI with a version that doesn't, to simplify testing.
|
||||
*/
|
||||
internal fun setAccessorProvider(newAccessorProvider: () -> ReactNativeFeatureFlagsAccessor) {
|
||||
accessorProvider = newAccessorProvider
|
||||
accessor = accessorProvider()
|
||||
}
|
||||
}
|
||||
`);
|
|
@ -1,60 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getKotlinTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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}
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor {
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` private var ${flagName}Cache: ${getKotlinTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)}? = null`,
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) => ` override fun ${flagName}(): Boolean {
|
||||
var cached = ${flagName}Cache
|
||||
if (cached == null) {
|
||||
cached = ReactNativeFeatureFlagsCxxInterop.${flagName}()
|
||||
${flagName}Cache = cached
|
||||
}
|
||||
return cached
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
override fun override(provider: ReactNativeFeatureFlagsProvider) =
|
||||
ReactNativeFeatureFlagsCxxInterop.override(provider as Any)
|
||||
|
||||
override fun dangerouslyReset() = ReactNativeFeatureFlagsCxxInterop.dangerouslyReset()
|
||||
}
|
||||
`);
|
|
@ -1,54 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getKotlinTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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}
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip
|
||||
import com.facebook.soloader.SoLoader
|
||||
|
||||
@DoNotStrip
|
||||
object ReactNativeFeatureFlagsCxxInterop {
|
||||
init {
|
||||
SoLoader.loadLibrary("reactfeatureflagsjni")
|
||||
}
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` @DoNotStrip @JvmStatic external fun ${flagName}(): ${getKotlinTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)}`,
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
@DoNotStrip @JvmStatic external fun override(provider: Any)
|
||||
|
||||
@DoNotStrip @JvmStatic external fun dangerouslyReset()
|
||||
}
|
||||
`);
|
|
@ -1,45 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getKotlinTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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}
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvider {
|
||||
// We could use JNI to get the defaults from C++,
|
||||
// but that is more expensive than just duplicating the defaults here.
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` override fun ${flagName}(): ${getKotlinTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} = ${JSON.stringify(flagConfig.defaultValue)}`,
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
`);
|
|
@ -1,74 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getKotlinTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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}
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAccessor {
|
||||
private var currentProvider: ReactNativeFeatureFlagsProvider = ReactNativeFeatureFlagsDefaults()
|
||||
|
||||
private val accessedFeatureFlags = mutableSetOf<String>()
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` private var ${flagName}Cache: ${getKotlinTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)}? = null`,
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) => ` override fun ${flagName}(): Boolean {
|
||||
var cached = ${flagName}Cache
|
||||
if (cached == null) {
|
||||
cached = currentProvider.${flagName}()
|
||||
accessedFeatureFlags.add("${flagName}")
|
||||
${flagName}Cache = cached
|
||||
}
|
||||
return cached
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
override fun override(provider: ReactNativeFeatureFlagsProvider) {
|
||||
if (accessedFeatureFlags.isNotEmpty()) {
|
||||
val accessedFeatureFlagsStr = accessedFeatureFlags.joinToString(separator = ", ") { it }
|
||||
throw IllegalStateException(
|
||||
"Feature flags were accessed before being overridden: $accessedFeatureFlagsStr")
|
||||
}
|
||||
currentProvider = provider
|
||||
}
|
||||
|
||||
override fun dangerouslyReset() {
|
||||
// We don't need to do anything here because \`ReactNativeFeatureFlags\` will
|
||||
// just create a new instance of this class.
|
||||
}
|
||||
}
|
||||
`);
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getKotlinTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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}
|
||||
|
||||
package com.facebook.react.internal.featureflags
|
||||
|
||||
interface ReactNativeFeatureFlagsProvider {
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` fun ${flagName}(): ${getKotlinTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)}`,
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
`);
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 "ReactNativeFeatureFlagsProviderHolder.h"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ReactNativeFeatureFlagsProviderHolder::${flagName}() {
|
||||
static const auto method =
|
||||
facebook::jni::findClassStatic(
|
||||
"com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider")
|
||||
->getMethod<jboolean()>("${flagName}");
|
||||
return method(javaProvider_);
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,62 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <fbjni/fbjni.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* Implementation of ReactNativeFeatureFlagsProvider that wraps a
|
||||
* ReactNativeFeatureFlagsProvider Java object.
|
||||
*/
|
||||
class ReactNativeFeatureFlagsProviderHolder
|
||||
: public ReactNativeFeatureFlagsProvider {
|
||||
public:
|
||||
explicit ReactNativeFeatureFlagsProviderHolder(
|
||||
jni::alias_ref<jobject> javaProvider)
|
||||
: javaProvider_(make_global(javaProvider)){};
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` ${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ${flagName}() override;`,
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
private:
|
||||
jni::global_ref<jobject> javaProvider_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,64 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ReactNativeFeatureFlags::${flagName}() {
|
||||
return getAccessor().${flagName}();
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
void ReactNativeFeatureFlags::override(
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
|
||||
getAccessor().override(std::move(provider));
|
||||
}
|
||||
|
||||
void ReactNativeFeatureFlags::dangerouslyReset() {
|
||||
getAccessor(true);
|
||||
}
|
||||
|
||||
ReactNativeFeatureFlagsAccessor& ReactNativeFeatureFlags::getAccessor(
|
||||
bool reset) {
|
||||
static std::unique_ptr<ReactNativeFeatureFlagsAccessor> accessor;
|
||||
if (accessor == nullptr || reset) {
|
||||
accessor = std::make_unique<ReactNativeFeatureFlagsAccessor>();
|
||||
}
|
||||
return *accessor;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,96 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <react/featureflags/ReactNativeFeatureFlagsAccessor.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlagsProvider.h>
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/**
|
||||
* This class provides access to internal React Native feature flags.
|
||||
*
|
||||
* All the methods are thread-safe if you handle \`override\` correctly.
|
||||
*/
|
||||
class ReactNativeFeatureFlags {
|
||||
public:
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` /**
|
||||
* ${flagConfig.description}
|
||||
*/
|
||||
static ${getCxxTypeFromDefaultValue(flagConfig.defaultValue)} ${flagName}();`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
/**
|
||||
* Overrides the feature flags with the ones provided by the given provider
|
||||
* (generally one that extends \`ReactNativeFeatureFlagsDefaults\`).
|
||||
*
|
||||
* This method must be called before you initialize the React Native runtime.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* \`\`\`
|
||||
* class MyReactNativeFeatureFlags : public ReactNativeFeatureFlagsDefaults {
|
||||
* public:
|
||||
* bool someFlag() override;
|
||||
* };
|
||||
*
|
||||
* ReactNativeFeatureFlags.override(
|
||||
* std::make_unique<MyReactNativeFeatureFlags>());
|
||||
* \`\`\`
|
||||
*/
|
||||
static void override(
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
|
||||
|
||||
/**
|
||||
* Removes the overridden feature flags and makes the API return default
|
||||
* values again.
|
||||
*
|
||||
* This is **dangerous**. Use it only if you really understand the
|
||||
* implications of this method.
|
||||
*
|
||||
* This should only be called if you destroy the React Native runtime and
|
||||
* need to create a new one with different overrides. In that case,
|
||||
* call \`dangerouslyReset\` after destroying the runtime and \`override\` again
|
||||
* before initializing the new one.
|
||||
*/
|
||||
static void dangerouslyReset();
|
||||
|
||||
private:
|
||||
ReactNativeFeatureFlags() = delete;
|
||||
static ReactNativeFeatureFlagsAccessor& getAccessor(bool reset = false);
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,87 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <react/featureflags/ReactNativeFeatureFlagsDefaults.h>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include "ReactNativeFeatureFlags.h"
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
ReactNativeFeatureFlagsAccessor::ReactNativeFeatureFlagsAccessor()
|
||||
: currentProvider_(std::make_unique<ReactNativeFeatureFlagsDefaults>()) {}
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ReactNativeFeatureFlagsAccessor::${flagName}() {
|
||||
if (!${flagName}_.has_value()) {
|
||||
// Mark the flag as accessed.
|
||||
static const char* flagName = "${flagName}";
|
||||
if (std::find(
|
||||
accessedFeatureFlags_.begin(),
|
||||
accessedFeatureFlags_.end(),
|
||||
flagName) == accessedFeatureFlags_.end()) {
|
||||
accessedFeatureFlags_.push_back(flagName);
|
||||
}
|
||||
|
||||
${flagName}_.emplace(currentProvider_->${flagName}());
|
||||
}
|
||||
|
||||
return ${flagName}_.value();
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
void ReactNativeFeatureFlagsAccessor::override(
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> provider) {
|
||||
if (!accessedFeatureFlags_.empty()) {
|
||||
std::ostringstream featureFlagListBuilder;
|
||||
for (const auto& featureFlagName : accessedFeatureFlags_) {
|
||||
featureFlagListBuilder << featureFlagName << ", ";
|
||||
}
|
||||
std::string accessedFeatureFlagNames = featureFlagListBuilder.str();
|
||||
if (!accessedFeatureFlagNames.empty()) {
|
||||
accessedFeatureFlagNames = accessedFeatureFlagNames.substr(
|
||||
0, accessedFeatureFlagNames.size() - 2);
|
||||
}
|
||||
|
||||
throw std::runtime_error(
|
||||
"Feature flags were accessed before being overridden: " +
|
||||
accessedFeatureFlagNames);
|
||||
}
|
||||
|
||||
currentProvider_ = std::move(provider);
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,67 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <react/featureflags/ReactNativeFeatureFlagsProvider.h>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class ReactNativeFeatureFlagsAccessor {
|
||||
public:
|
||||
ReactNativeFeatureFlagsAccessor();
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` ${getCxxTypeFromDefaultValue(flagConfig.defaultValue)} ${flagName}();`,
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
void override(std::unique_ptr<ReactNativeFeatureFlagsProvider> provider);
|
||||
|
||||
private:
|
||||
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
|
||||
std::vector<const char*> accessedFeatureFlags_;
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` std::optional<${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)}> ${flagName}_;`,
|
||||
)
|
||||
.join('\n')}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <react/featureflags/ReactNativeFeatureFlagsProvider.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider {
|
||||
public:
|
||||
ReactNativeFeatureFlagsDefaults() = default;
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` ${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ${flagName}() override {
|
||||
return ${JSON.stringify(flagConfig.defaultValue)};
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class ReactNativeFeatureFlagsProvider {
|
||||
public:
|
||||
virtual ~ReactNativeFeatureFlagsProvider() = default;
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` virtual ${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ${flagName}() = 0;`,
|
||||
)
|
||||
.join('\n')}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,61 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 "NativeReactNativeFeatureFlags.h"
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
|
||||
#include "Plugins.h"
|
||||
|
||||
std::shared_ptr<facebook::react::TurboModule>
|
||||
NativeReactNativeFeatureFlagsModuleProvider(
|
||||
std::shared_ptr<facebook::react::CallInvoker> jsInvoker) {
|
||||
return std::make_shared<facebook::react::NativeReactNativeFeatureFlags>(
|
||||
std::move(jsInvoker));
|
||||
}
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
NativeReactNativeFeatureFlags::NativeReactNativeFeatureFlags(
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: NativeReactNativeFeatureFlagsCxxSpec(std::move(jsInvoker)) {}
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} NativeReactNativeFeatureFlags::${flagName}(
|
||||
jsi::Runtime& /*runtime*/) {
|
||||
return ReactNativeFeatureFlags::${flagName}();
|
||||
}`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,54 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
DO_NOT_MODIFY_COMMENT,
|
||||
getCxxTypeFromDefaultValue,
|
||||
} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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 <FBReactNativeSpec/FBReactNativeSpecJSI.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class NativeReactNativeFeatureFlags
|
||||
: public NativeReactNativeFeatureFlagsCxxSpec<
|
||||
NativeReactNativeFeatureFlags>,
|
||||
std::enable_shared_from_this<NativeReactNativeFeatureFlags> {
|
||||
public:
|
||||
NativeReactNativeFeatureFlags(std::shared_ptr<CallInvoker> jsInvoker);
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` ${getCxxTypeFromDefaultValue(
|
||||
flagConfig.defaultValue,
|
||||
)} ${flagName}(jsi::Runtime& runtime);`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
`);
|
|
@ -1,46 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {DO_NOT_MODIFY_COMMENT} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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()}
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
${DO_NOT_MODIFY_COMMENT}
|
||||
|
||||
import type {TurboModule} from '../../../Libraries/TurboModule/RCTExport';
|
||||
|
||||
import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` +${flagName}?: () => ${typeof flagConfig.defaultValue};`,
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
|
||||
const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get<Spec>(
|
||||
'NativeReactNativeFeatureFlagsCxx',
|
||||
);
|
||||
|
||||
export default NativeReactNativeFeatureFlags;
|
||||
`);
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const {DO_NOT_MODIFY_COMMENT} = require('../../utils');
|
||||
const signedsource = require('signedsource');
|
||||
|
||||
module.exports = config =>
|
||||
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()}
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
${DO_NOT_MODIFY_COMMENT}
|
||||
|
||||
import {
|
||||
type Getter,
|
||||
createJavaScriptFlagGetter,
|
||||
createNativeFlagGetter,
|
||||
setOverrides,
|
||||
} from './ReactNativeFeatureFlagsBase';
|
||||
|
||||
export type ReactNativeFeatureFlagsJsOnly = {
|
||||
${Object.entries(config.jsOnly)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` ${flagName}: Getter<${typeof flagConfig.defaultValue}>,`,
|
||||
)
|
||||
.join('\n')}
|
||||
};
|
||||
|
||||
export type ReactNativeFeatureFlagsJsOnlyOverrides = Partial<ReactNativeFeatureFlagsJsOnly>;
|
||||
|
||||
export type ReactNativeFeatureFlags = {
|
||||
...ReactNativeFeatureFlagsJsOnly,
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
` ${flagName}: Getter<${typeof flagConfig.defaultValue}>,`,
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
|
||||
${Object.entries(config.jsOnly)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`/**
|
||||
* ${flagConfig.description}
|
||||
*/
|
||||
export const ${flagName}: Getter<${typeof flagConfig.defaultValue}> = createJavaScriptFlagGetter('${flagName}', ${JSON.stringify(
|
||||
flagConfig.defaultValue,
|
||||
)});`,
|
||||
)
|
||||
.join('\n\n')}
|
||||
|
||||
${Object.entries(config.common)
|
||||
.map(
|
||||
([flagName, flagConfig]) =>
|
||||
`/**
|
||||
* ${flagConfig.description}
|
||||
*/
|
||||
export const ${flagName}: Getter<${typeof flagConfig.defaultValue}> = createNativeFlagGetter('${flagName}', ${JSON.stringify(
|
||||
flagConfig.defaultValue,
|
||||
)});`,
|
||||
)
|
||||
.join('\n')}
|
||||
|
||||
/**
|
||||
* Overrides the feature flags with the provided methods.
|
||||
* NOTE: Only JS-only flags can be overridden from JavaScript using this API.
|
||||
*/
|
||||
export const override = setOverrides;
|
||||
`);
|
|
@ -1,68 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
const generateFiles = require('./generateFiles');
|
||||
const path = require('path');
|
||||
|
||||
const REACT_NATIVE_PACKAGE_ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
function update() {
|
||||
generateFiles(
|
||||
{
|
||||
configPath: path.join(__dirname, 'ReactNativeFeatureFlags.json'),
|
||||
jsPath: path.join(
|
||||
REACT_NATIVE_PACKAGE_ROOT,
|
||||
'src',
|
||||
'private',
|
||||
'featureflags',
|
||||
),
|
||||
commonCxxPath: path.join(
|
||||
REACT_NATIVE_PACKAGE_ROOT,
|
||||
'ReactCommon',
|
||||
'react',
|
||||
'featureflags',
|
||||
),
|
||||
commonNativeModuleCxxPath: path.join(
|
||||
REACT_NATIVE_PACKAGE_ROOT,
|
||||
'ReactCommon',
|
||||
'react',
|
||||
'nativemodule',
|
||||
'featureflags',
|
||||
),
|
||||
androidPath: path.join(
|
||||
REACT_NATIVE_PACKAGE_ROOT,
|
||||
'ReactAndroid',
|
||||
'src',
|
||||
'main',
|
||||
'java',
|
||||
'com',
|
||||
'facebook',
|
||||
'react',
|
||||
'internal',
|
||||
'featureflags',
|
||||
),
|
||||
androidJniPath: path.join(
|
||||
REACT_NATIVE_PACKAGE_ROOT,
|
||||
'ReactAndroid',
|
||||
'src',
|
||||
'main',
|
||||
'jni',
|
||||
'react',
|
||||
'featureflags',
|
||||
),
|
||||
},
|
||||
{
|
||||
verifyUnchanged: process.argv.includes('--verify-unchanged'),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
update();
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
getCxxTypeFromDefaultValue: defaultValue => {
|
||||
switch (typeof defaultValue) {
|
||||
case 'boolean':
|
||||
return 'bool';
|
||||
case 'number':
|
||||
return 'int';
|
||||
case 'string':
|
||||
return 'std::string';
|
||||
default:
|
||||
throw new Error(
|
||||
`Unsupported default value type: ${typeof defaultValue}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
getKotlinTypeFromDefaultValue: defaultValue => {
|
||||
switch (typeof defaultValue) {
|
||||
case 'boolean':
|
||||
return 'Boolean';
|
||||
case 'number':
|
||||
return 'Int';
|
||||
case 'string':
|
||||
return 'String';
|
||||
default:
|
||||
throw new Error(
|
||||
`Unsupported default value type: ${typeof defaultValue}`,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
DO_NOT_MODIFY_COMMENT: `/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/`,
|
||||
};
|
|
@ -124,7 +124,6 @@ def use_react_native! (
|
|||
pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact"
|
||||
pod 'React-debug', :path => "#{prefix}/ReactCommon/react/debug"
|
||||
pod 'React-utils', :path => "#{prefix}/ReactCommon/react/utils"
|
||||
pod 'React-featureflags', :path => "#{prefix}/ReactCommon/react/featureflags"
|
||||
pod 'React-Mapbuffer', :path => "#{prefix}/ReactCommon"
|
||||
pod 'React-jserrorhandler', :path => "#{prefix}/ReactCommon/jserrorhandler"
|
||||
pod 'React-nativeconfig', :path => "#{prefix}/ReactCommon"
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
* 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<<ec82a5158f766de0467ab9a38e4ffb15>>
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
import type {TurboModule} from '../../../Libraries/TurboModule/RCTExport';
|
||||
|
||||
import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModuleRegistry';
|
||||
|
||||
export interface Spec extends TurboModule {
|
||||
+commonTestFlag?: () => boolean;
|
||||
}
|
||||
|
||||
const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get<Spec>(
|
||||
'NativeReactNativeFeatureFlagsCxx',
|
||||
);
|
||||
|
||||
export default NativeReactNativeFeatureFlags;
|
|
@ -1,53 +0,0 @@
|
|||
/**
|
||||
* 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<<b554016876afbf53c25670806a5ff581>>
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT: Do NOT modify this file directly.
|
||||
*
|
||||
* To change the definition of the flags, edit
|
||||
* packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.json.
|
||||
*
|
||||
* To regenerate this code, run the following script from the repo root:
|
||||
* yarn featureflags-update
|
||||
*/
|
||||
|
||||
import {
|
||||
type Getter,
|
||||
createJavaScriptFlagGetter,
|
||||
createNativeFlagGetter,
|
||||
setOverrides,
|
||||
} from './ReactNativeFeatureFlagsBase';
|
||||
|
||||
export type ReactNativeFeatureFlagsJsOnly = {
|
||||
jsOnlyTestFlag: Getter<boolean>,
|
||||
};
|
||||
|
||||
export type ReactNativeFeatureFlagsJsOnlyOverrides = Partial<ReactNativeFeatureFlagsJsOnly>;
|
||||
|
||||
export type ReactNativeFeatureFlags = {
|
||||
...ReactNativeFeatureFlagsJsOnly,
|
||||
commonTestFlag: Getter<boolean>,
|
||||
}
|
||||
|
||||
/**
|
||||
* JS-only flag for testing. Do NOT modify.
|
||||
*/
|
||||
export const jsOnlyTestFlag: Getter<boolean> = createJavaScriptFlagGetter('jsOnlyTestFlag', false);
|
||||
|
||||
/**
|
||||
* Common flag for testing. Do NOT modify.
|
||||
*/
|
||||
export const commonTestFlag: Getter<boolean> = createNativeFlagGetter('commonTestFlag', false);
|
||||
|
||||
/**
|
||||
* Overrides the feature flags with the provided methods.
|
||||
* NOTE: Only JS-only flags can be overridden from JavaScript using this API.
|
||||
*/
|
||||
export const override = setOverrides;
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* 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-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
import type {
|
||||
ReactNativeFeatureFlagsJsOnly,
|
||||
ReactNativeFeatureFlagsJsOnlyOverrides,
|
||||
} from './ReactNativeFeatureFlags';
|
||||
|
||||
import NativeReactNativeFeatureFlags from './NativeReactNativeFeatureFlags';
|
||||
|
||||
const accessedFeatureFlags: Set<string> = new Set();
|
||||
const overrides: ReactNativeFeatureFlagsJsOnlyOverrides = {};
|
||||
|
||||
export type Getter<T> = () => T;
|
||||
|
||||
function createGetter<T: boolean | number | string>(
|
||||
configName: string,
|
||||
customValueGetter: Getter<?T>,
|
||||
defaultValue: T,
|
||||
): Getter<T> {
|
||||
let cachedValue: ?T;
|
||||
|
||||
return () => {
|
||||
if (cachedValue == null) {
|
||||
accessedFeatureFlags.add(configName);
|
||||
cachedValue = customValueGetter() ?? defaultValue;
|
||||
}
|
||||
return cachedValue;
|
||||
};
|
||||
}
|
||||
|
||||
export function createJavaScriptFlagGetter<
|
||||
K: $Keys<ReactNativeFeatureFlagsJsOnly>,
|
||||
>(
|
||||
configName: K,
|
||||
defaultValue: ReturnType<ReactNativeFeatureFlagsJsOnly[K]>,
|
||||
): Getter<ReturnType<ReactNativeFeatureFlagsJsOnly[K]>> {
|
||||
return createGetter(
|
||||
configName,
|
||||
() => overrides[configName]?.(),
|
||||
defaultValue,
|
||||
);
|
||||
}
|
||||
|
||||
type NativeFeatureFlags = $NonMaybeType<typeof NativeReactNativeFeatureFlags>;
|
||||
|
||||
export function createNativeFlagGetter<K: $Keys<NativeFeatureFlags>>(
|
||||
configName: K,
|
||||
defaultValue: ReturnType<$NonMaybeType<NativeFeatureFlags[K]>>,
|
||||
): Getter<ReturnType<$NonMaybeType<NativeFeatureFlags[K]>>> {
|
||||
return createGetter(
|
||||
configName,
|
||||
() => NativeReactNativeFeatureFlags?.[configName]?.(),
|
||||
defaultValue,
|
||||
);
|
||||
}
|
||||
|
||||
export function getOverrides(): ?ReactNativeFeatureFlagsJsOnlyOverrides {
|
||||
return overrides;
|
||||
}
|
||||
|
||||
export function setOverrides(
|
||||
newOverrides: ReactNativeFeatureFlagsJsOnlyOverrides,
|
||||
): void {
|
||||
if (accessedFeatureFlags.size > 0) {
|
||||
const accessedFeatureFlagsStr = Array.from(accessedFeatureFlags).join(', ');
|
||||
throw new Error(
|
||||
`Feature flags were accessed before being overridden: ${accessedFeatureFlagsStr}`,
|
||||
);
|
||||
}
|
||||
|
||||
Object.assign(overrides, newOverrides);
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/**
|
||||
* 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-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
describe('ReactNativeFeatureFlags', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
});
|
||||
|
||||
it('should provide default values for common flags if the native module is NOT available', () => {
|
||||
const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags');
|
||||
expect(ReactNativeFeatureFlags.commonTestFlag()).toBe(false);
|
||||
});
|
||||
|
||||
it('should access and cache common flags from the native module if it is available', () => {
|
||||
const commonTestFlagFn = jest.fn(() => true);
|
||||
|
||||
jest.doMock('../NativeReactNativeFeatureFlags', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
commonTestFlag: commonTestFlagFn,
|
||||
},
|
||||
}));
|
||||
|
||||
const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags');
|
||||
|
||||
expect(commonTestFlagFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(ReactNativeFeatureFlags.commonTestFlag()).toBe(true);
|
||||
expect(commonTestFlagFn).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(ReactNativeFeatureFlags.commonTestFlag()).toBe(true);
|
||||
expect(commonTestFlagFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should provide default values for JS-only flags', () => {
|
||||
const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags');
|
||||
expect(ReactNativeFeatureFlags.jsOnlyTestFlag()).toBe(false);
|
||||
});
|
||||
|
||||
it('should access and cache overridden JS-only flags', () => {
|
||||
const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags');
|
||||
|
||||
const jsOnlyTestFlagFn = jest.fn(() => true);
|
||||
ReactNativeFeatureFlags.override({
|
||||
jsOnlyTestFlag: jsOnlyTestFlagFn,
|
||||
});
|
||||
|
||||
expect(jsOnlyTestFlagFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(ReactNativeFeatureFlags.jsOnlyTestFlag()).toBe(true);
|
||||
expect(jsOnlyTestFlagFn).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(ReactNativeFeatureFlags.jsOnlyTestFlag()).toBe(true);
|
||||
expect(jsOnlyTestFlagFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should throw an error if any of the flags has been accessed before overridding', () => {
|
||||
const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags');
|
||||
|
||||
ReactNativeFeatureFlags.commonTestFlag();
|
||||
|
||||
expect(() =>
|
||||
ReactNativeFeatureFlags.override({
|
||||
jsOnlyTestFlag: () => true,
|
||||
}),
|
||||
).toThrow(
|
||||
'Feature flags were accessed before being overridden: commonTestFlag',
|
||||
);
|
||||
});
|
||||
});
|
|
@ -33,13 +33,6 @@ function describe(message) {
|
|||
try {
|
||||
echo('Executing JavaScript tests');
|
||||
|
||||
describe('Test: feature flags codegen');
|
||||
if (exec(`${YARN_BINARY} run featureflags-check`).code) {
|
||||
echo('Failed to run featureflags check.');
|
||||
exitCode = 1;
|
||||
throw Error(exitCode);
|
||||
}
|
||||
|
||||
describe('Test: eslint');
|
||||
if (exec(`${YARN_BINARY} run lint`).code) {
|
||||
echo('Failed to run eslint.');
|
||||
|
|
Загрузка…
Ссылка в новой задаче