From bf3656b75885c5a015e0dd09a5ef6fba0a503ea6 Mon Sep 17 00:00:00 2001 From: Vincent Riemer Date: Mon, 13 Feb 2023 14:52:38 -0800 Subject: [PATCH 01/81] - Ensure move tracking is applied to pressed moves Summary: Changelog: [Internal] - Ensure pointer move tracking is applied to movement while the pointer is pressed Reviewed By: javache Differential Revision: D42977052 fbshipit-source-id: 2d48c35a908449d0b2338c33273fb75a430bc393 --- .../react/uimanager/JSPointerDispatcher.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java index 2a462123eaa69b..8f4a992f85383a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -260,7 +260,6 @@ public void handleMotionEvent( break; case MotionEvent.ACTION_HOVER_MOVE: // TODO(luwe) - converge this with ACTION_MOVE - // If we don't move enough, ignore this event. float[] eventCoordinates = eventState.getEventCoordinatesByPointerId().get(activePointerId); float[] lastEventCoordinates = @@ -275,18 +274,7 @@ public void handleMotionEvent( onMove(activeTargetTag, eventState, motionEvent, eventDispatcher); break; case MotionEvent.ACTION_MOVE: - // TODO(luwe) - converge this with ACTION_HOVER_MOVE - boolean listeningForMove = - isAnyoneListeningForBubblingEvent(activeHitPath, EVENT.MOVE, EVENT.MOVE_CAPTURE); - if (listeningForMove) { - eventDispatcher.dispatchEvent( - PointerEvent.obtain( - PointerEventHelper.POINTER_MOVE, - activeTargetTag, - eventState, - motionEvent, - getCoalescingKey())); - } + onMove(activeTargetTag, eventState, motionEvent, eventDispatcher); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: From ceb1d0dea694739f357d86296b94f5834e5ee7f7 Mon Sep 17 00:00:00 2001 From: Vitali Zaidman Date: Mon, 13 Feb 2023 15:09:44 -0800 Subject: [PATCH 02/81] Generate enum types that would be allowed to be used as well as string/number in c++ turbo modules generators (#36030) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36030 Generate enum types in c++ turbo modules. For enums in the ts schema file such as: ``` export enum NumEnum { ONE = 1, TWO = 2, } ``` This would export enums and the relevant Bridging to js and from js code to the spec H files such as: ``` #pragma mark - SampleTurboModuleCxxNumEnum enum SampleTurboModuleCxxNumEnum { ONE, TWO }; template <> struct Bridging { static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, int32_t value) { if (value == 1) { return SampleTurboModuleCxxNumEnum::ONE; } else if (value == 2) { return SampleTurboModuleCxxNumEnum::TWO; } else { throw jsi::JSError(rt, "No appropriate enum member found for value"); } } static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxNumEnum value) { if (value == SampleTurboModuleCxxNumEnum::ONE) { return bridging::toJs(rt, 1); } else if (value == SampleTurboModuleCxxNumEnum::TWO) { return bridging::toJs(rt, 2); } else { throw jsi::JSError(rt, "No appropriate enum member found for enum value"); } } }; ``` That code would allow us to use these enums in the cxx files like this: ``` NativeCxxModuleExampleCxxEnumInt getNumEnum( jsi::Runtime &rt, NativeCxxModuleExampleCxxEnumInt arg); ``` Changelog: [General] [Added] Generate enum types that would be allowed to be used as well as string/number in c++ turbo modules generators Reviewed By: christophpurrer Differential Revision: D42884147 fbshipit-source-id: d34d1fc7ba268b570821dc108444196f69a431b2 --- .../GenerateModuleH-test.js.snap | 374 +++++++++++++++--- .../src/generators/Utils.js | 20 + .../components/ComponentsGeneratorUtils.js | 3 +- .../src/generators/components/CppHelpers.js | 19 +- .../components/GenerateEventEmitterH.js | 3 +- .../generators/components/GeneratePropsH.js | 4 +- .../generators/components/GenerateTests.js | 4 +- .../generators/modules/GenerateModuleCpp.js | 10 +- .../src/generators/modules/GenerateModuleH.js | 173 +++++++- .../src/generators/modules/Utils.js | 6 + .../modules/__test_fixtures__/fixtures.js | 136 ++++++- .../GenerateModuleCpp-test.js.snap | 8 + .../GenerateModuleH-test.js.snap | 230 ++++++++++- .../GenerateModuleHObjCpp-test.js.snap | 1 + .../GenerateModuleJavaSpec-test.js.snap | 4 + .../GenerateModuleJniCpp-test.js.snap | 6 + .../GenerateModuleMm-test.js.snap | 7 + .../NativeCxxModuleExample.cpp | 16 +- .../NativeCxxModuleExample.h | 22 +- .../NativeCxxModuleExample.js | 23 +- .../NativeCxxModuleExampleExample.js | 10 +- 21 files changed, 973 insertions(+), 106 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap index 20b3a737fbee08..541b349dbba853 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap @@ -18,7 +18,8 @@ exports[`GenerateModuleH can generate a header file NativeModule specs 1`] = ` namespace facebook { namespace react { -class JSI_EXPORT NativeArrayTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeArrayTurboModuleCxxSpecJSI : public TurboModule { protected: NativeArrayTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -79,7 +80,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeBooleanTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeBooleanTurboModuleCxxSpecJSI : public TurboModule { protected: NativeBooleanTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -131,7 +133,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeCallbackTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeCallbackTurboModuleCxxSpecJSI : public TurboModule { protected: NativeCallbackTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -183,7 +186,135 @@ private: Delegate delegate_; }; -#pragma mark - NativeEnumTurboModuleBaseStateType + +#pragma mark - NativeEnumTurboModuleStatusRegularEnum + +enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + std::string value = rawValue.utf8(rt); + if (value == \\"Active\\") { + return NativeEnumTurboModuleStatusRegularEnum::Active; + } else if (value == \\"Paused\\") { + return NativeEnumTurboModuleStatusRegularEnum::Paused; + } else if (value == \\"Off\\") { + return NativeEnumTurboModuleStatusRegularEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value) { + if (value == NativeEnumTurboModuleStatusRegularEnum::Active) { + return bridging::toJs(rt, \\"Active\\"); + } else if (value == NativeEnumTurboModuleStatusRegularEnum::Paused) { + return bridging::toJs(rt, \\"Paused\\"); + } else if (value == NativeEnumTurboModuleStatusRegularEnum::Off) { + return bridging::toJs(rt, \\"Off\\"); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleStatusStrEnum + +enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + std::string value = rawValue.utf8(rt); + if (value == \\"active\\") { + return NativeEnumTurboModuleStatusStrEnum::Active; + } else if (value == \\"paused\\") { + return NativeEnumTurboModuleStatusStrEnum::Paused; + } else if (value == \\"off\\") { + return NativeEnumTurboModuleStatusStrEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value) { + if (value == NativeEnumTurboModuleStatusStrEnum::Active) { + return bridging::toJs(rt, \\"active\\"); + } else if (value == NativeEnumTurboModuleStatusStrEnum::Paused) { + return bridging::toJs(rt, \\"paused\\"); + } else if (value == NativeEnumTurboModuleStatusStrEnum::Off) { + return bridging::toJs(rt, \\"off\\"); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleStatusNumEnum + +enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, int32_t value) { + + if (value == 2) { + return NativeEnumTurboModuleStatusNumEnum::Active; + } else if (value == 1) { + return NativeEnumTurboModuleStatusNumEnum::Paused; + } else if (value == 0) { + return NativeEnumTurboModuleStatusNumEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value) { + if (value == NativeEnumTurboModuleStatusNumEnum::Active) { + return bridging::toJs(rt, 2); + } else if (value == NativeEnumTurboModuleStatusNumEnum::Paused) { + return bridging::toJs(rt, 1); + } else if (value == NativeEnumTurboModuleStatusNumEnum::Off) { + return bridging::toJs(rt, 0); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleStatusFractionEnum + +enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, float value) { + + if (value == 0.2f) { + return NativeEnumTurboModuleStatusFractionEnum::Active; + } else if (value == 0.1f) { + return NativeEnumTurboModuleStatusFractionEnum::Paused; + } else if (value == 0f) { + return NativeEnumTurboModuleStatusFractionEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) { + if (value == NativeEnumTurboModuleStatusFractionEnum::Active) { + return bridging::toJs(rt, 0.2f); + } else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) { + return bridging::toJs(rt, 0.1f); + } else if (value == NativeEnumTurboModuleStatusFractionEnum::Off) { + return bridging::toJs(rt, 0f); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + #pragma mark - NativeEnumTurboModuleBaseStateType template struct NativeEnumTurboModuleBaseStateType { @@ -260,7 +391,7 @@ struct NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { static jsi::String strToJs(jsi::Runtime &rt, P2 value) { return bridging::toJs(rt, value); } - static double numToJs(jsi::Runtime &rt, P3 value) { + static int numToJs(jsi::Runtime &rt, P3 value) { return bridging::toJs(rt, value); } static double fractionToJs(jsi::Runtime &rt, P4 value) { @@ -289,9 +420,9 @@ protected: public: virtual jsi::String getStatusRegular(jsi::Runtime &rt, jsi::Object statusProp) = 0; virtual jsi::String getStatusStr(jsi::Runtime &rt, jsi::Object statusProp) = 0; - virtual double getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) = 0; + virtual int getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) = 0; virtual double getStatusFraction(jsi::Runtime &rt, jsi::Object statusProp) = 0; - virtual jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, double c, double d) = 0; + virtual jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, int c, double d) = 0; virtual jsi::Object getStateTypeWithEnums(jsi::Runtime &rt, jsi::Object paramOfTypeWithEnums) = 0; }; @@ -330,12 +461,12 @@ private: return bridging::callFromJs( rt, &T::getStatusStr, jsInvoker_, instance_, std::move(statusProp)); } - double getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) override { + int getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) override { static_assert( bridging::getParameterCount(&T::getStatusNum) == 2, \\"Expected getStatusNum(...) to have 2 parameters\\"); - return bridging::callFromJs( + return bridging::callFromJs( rt, &T::getStatusNum, jsInvoker_, instance_, std::move(statusProp)); } double getStatusFraction(jsi::Runtime &rt, jsi::Object statusProp) override { @@ -346,7 +477,7 @@ private: return bridging::callFromJs( rt, &T::getStatusFraction, jsInvoker_, instance_, std::move(statusProp)); } - jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, double c, double d) override { + jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, int c, double d) override { static_assert( bridging::getParameterCount(&T::getStateType) == 5, \\"Expected getStateType(...) to have 5 parameters\\"); @@ -370,7 +501,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeNullableTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeNullableTurboModuleCxxSpecJSI : public TurboModule { protected: NativeNullableTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -458,7 +590,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeNumberTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeNumberTurboModuleCxxSpecJSI : public TurboModule { protected: NativeNumberTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -510,7 +643,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeObjectTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeObjectTurboModuleCxxSpecJSI : public TurboModule { protected: NativeObjectTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -589,7 +723,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeOptionalObjectTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeOptionalObjectTurboModuleCxxSpecJSI : public TurboModule { protected: NativeOptionalObjectTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -632,7 +767,8 @@ private: Delegate delegate_; }; -#pragma mark - NativePartialAnnotationTurboModuleBaseSomeObj + + #pragma mark - NativePartialAnnotationTurboModuleBaseSomeObj template struct NativePartialAnnotationTurboModuleBaseSomeObj { @@ -747,7 +883,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativePromiseTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativePromiseTurboModuleCxxSpecJSI : public TurboModule { protected: NativePromiseTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -799,7 +936,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleBaseAnimal + + #pragma mark - SampleTurboModuleBaseAnimal template struct SampleTurboModuleBaseAnimal { @@ -987,7 +1125,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleArraysBaseAnimal + + #pragma mark - SampleTurboModuleArraysBaseAnimal template struct SampleTurboModuleArraysBaseAnimal { @@ -1175,7 +1314,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleNullableBaseAnimal + + #pragma mark - SampleTurboModuleNullableBaseAnimal template struct SampleTurboModuleNullableBaseAnimal { @@ -1363,7 +1503,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleNullableAndOptionalBaseAnimal + + #pragma mark - SampleTurboModuleNullableAndOptionalBaseAnimal template struct SampleTurboModuleNullableAndOptionalBaseAnimal { @@ -1553,7 +1694,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleOptionalBaseAnimal + + #pragma mark - SampleTurboModuleOptionalBaseAnimal template struct SampleTurboModuleOptionalBaseAnimal { @@ -1743,7 +1885,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeStringTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeStringTurboModuleCxxSpecJSI : public TurboModule { protected: NativeStringTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1818,7 +1961,8 @@ exports[`GenerateModuleH can generate a header file NativeModule specs with assu namespace facebook { namespace react { -class JSI_EXPORT NativeArrayTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeArrayTurboModuleCxxSpecJSI : public TurboModule { protected: NativeArrayTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1879,7 +2023,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeBooleanTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeBooleanTurboModuleCxxSpecJSI : public TurboModule { protected: NativeBooleanTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1931,7 +2076,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeCallbackTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeCallbackTurboModuleCxxSpecJSI : public TurboModule { protected: NativeCallbackTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1983,7 +2129,135 @@ private: Delegate delegate_; }; -#pragma mark - NativeEnumTurboModuleBaseStateType + +#pragma mark - NativeEnumTurboModuleStatusRegularEnum + +enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + std::string value = rawValue.utf8(rt); + if (value == \\"Active\\") { + return NativeEnumTurboModuleStatusRegularEnum::Active; + } else if (value == \\"Paused\\") { + return NativeEnumTurboModuleStatusRegularEnum::Paused; + } else if (value == \\"Off\\") { + return NativeEnumTurboModuleStatusRegularEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value) { + if (value == NativeEnumTurboModuleStatusRegularEnum::Active) { + return bridging::toJs(rt, \\"Active\\"); + } else if (value == NativeEnumTurboModuleStatusRegularEnum::Paused) { + return bridging::toJs(rt, \\"Paused\\"); + } else if (value == NativeEnumTurboModuleStatusRegularEnum::Off) { + return bridging::toJs(rt, \\"Off\\"); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleStatusStrEnum + +enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + std::string value = rawValue.utf8(rt); + if (value == \\"active\\") { + return NativeEnumTurboModuleStatusStrEnum::Active; + } else if (value == \\"paused\\") { + return NativeEnumTurboModuleStatusStrEnum::Paused; + } else if (value == \\"off\\") { + return NativeEnumTurboModuleStatusStrEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value) { + if (value == NativeEnumTurboModuleStatusStrEnum::Active) { + return bridging::toJs(rt, \\"active\\"); + } else if (value == NativeEnumTurboModuleStatusStrEnum::Paused) { + return bridging::toJs(rt, \\"paused\\"); + } else if (value == NativeEnumTurboModuleStatusStrEnum::Off) { + return bridging::toJs(rt, \\"off\\"); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleStatusNumEnum + +enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, int32_t value) { + + if (value == 2) { + return NativeEnumTurboModuleStatusNumEnum::Active; + } else if (value == 1) { + return NativeEnumTurboModuleStatusNumEnum::Paused; + } else if (value == 0) { + return NativeEnumTurboModuleStatusNumEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value) { + if (value == NativeEnumTurboModuleStatusNumEnum::Active) { + return bridging::toJs(rt, 2); + } else if (value == NativeEnumTurboModuleStatusNumEnum::Paused) { + return bridging::toJs(rt, 1); + } else if (value == NativeEnumTurboModuleStatusNumEnum::Off) { + return bridging::toJs(rt, 0); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - NativeEnumTurboModuleStatusFractionEnum + +enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off }; + +template <> +struct Bridging { + static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, float value) { + + if (value == 0.2f) { + return NativeEnumTurboModuleStatusFractionEnum::Active; + } else if (value == 0.1f) { + return NativeEnumTurboModuleStatusFractionEnum::Paused; + } else if (value == 0f) { + return NativeEnumTurboModuleStatusFractionEnum::Off; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) { + if (value == NativeEnumTurboModuleStatusFractionEnum::Active) { + return bridging::toJs(rt, 0.2f); + } else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) { + return bridging::toJs(rt, 0.1f); + } else if (value == NativeEnumTurboModuleStatusFractionEnum::Off) { + return bridging::toJs(rt, 0f); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + #pragma mark - NativeEnumTurboModuleBaseStateType template struct NativeEnumTurboModuleBaseStateType { @@ -2060,7 +2334,7 @@ struct NativeEnumTurboModuleBaseStateTypeWithEnumsBridging { static jsi::String strToJs(jsi::Runtime &rt, P2 value) { return bridging::toJs(rt, value); } - static double numToJs(jsi::Runtime &rt, P3 value) { + static int numToJs(jsi::Runtime &rt, P3 value) { return bridging::toJs(rt, value); } static double fractionToJs(jsi::Runtime &rt, P4 value) { @@ -2089,9 +2363,9 @@ protected: public: virtual jsi::String getStatusRegular(jsi::Runtime &rt, jsi::Object statusProp) = 0; virtual jsi::String getStatusStr(jsi::Runtime &rt, jsi::Object statusProp) = 0; - virtual double getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) = 0; + virtual int getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) = 0; virtual double getStatusFraction(jsi::Runtime &rt, jsi::Object statusProp) = 0; - virtual jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, double c, double d) = 0; + virtual jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, int c, double d) = 0; virtual jsi::Object getStateTypeWithEnums(jsi::Runtime &rt, jsi::Object paramOfTypeWithEnums) = 0; }; @@ -2130,12 +2404,12 @@ private: return bridging::callFromJs( rt, &T::getStatusStr, jsInvoker_, instance_, std::move(statusProp)); } - double getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) override { + int getStatusNum(jsi::Runtime &rt, jsi::Object statusProp) override { static_assert( bridging::getParameterCount(&T::getStatusNum) == 2, \\"Expected getStatusNum(...) to have 2 parameters\\"); - return bridging::callFromJs( + return bridging::callFromJs( rt, &T::getStatusNum, jsInvoker_, instance_, std::move(statusProp)); } double getStatusFraction(jsi::Runtime &rt, jsi::Object statusProp) override { @@ -2146,7 +2420,7 @@ private: return bridging::callFromJs( rt, &T::getStatusFraction, jsInvoker_, instance_, std::move(statusProp)); } - jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, double c, double d) override { + jsi::Object getStateType(jsi::Runtime &rt, jsi::String a, jsi::String b, int c, double d) override { static_assert( bridging::getParameterCount(&T::getStateType) == 5, \\"Expected getStateType(...) to have 5 parameters\\"); @@ -2170,7 +2444,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeNullableTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeNullableTurboModuleCxxSpecJSI : public TurboModule { protected: NativeNullableTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2258,7 +2533,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeNumberTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeNumberTurboModuleCxxSpecJSI : public TurboModule { protected: NativeNumberTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2310,7 +2586,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeObjectTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeObjectTurboModuleCxxSpecJSI : public TurboModule { protected: NativeObjectTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2389,7 +2666,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeOptionalObjectTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeOptionalObjectTurboModuleCxxSpecJSI : public TurboModule { protected: NativeOptionalObjectTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2432,7 +2710,8 @@ private: Delegate delegate_; }; -#pragma mark - NativePartialAnnotationTurboModuleBaseSomeObj + + #pragma mark - NativePartialAnnotationTurboModuleBaseSomeObj template struct NativePartialAnnotationTurboModuleBaseSomeObj { @@ -2547,7 +2826,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativePromiseTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativePromiseTurboModuleCxxSpecJSI : public TurboModule { protected: NativePromiseTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -2599,7 +2879,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleBaseAnimal + + #pragma mark - SampleTurboModuleBaseAnimal template struct SampleTurboModuleBaseAnimal { @@ -2787,7 +3068,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleArraysBaseAnimal + + #pragma mark - SampleTurboModuleArraysBaseAnimal template struct SampleTurboModuleArraysBaseAnimal { @@ -2975,7 +3257,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleNullableBaseAnimal + + #pragma mark - SampleTurboModuleNullableBaseAnimal template struct SampleTurboModuleNullableBaseAnimal { @@ -3163,7 +3446,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleNullableAndOptionalBaseAnimal + + #pragma mark - SampleTurboModuleNullableAndOptionalBaseAnimal template struct SampleTurboModuleNullableAndOptionalBaseAnimal { @@ -3353,7 +3637,8 @@ private: Delegate delegate_; }; -#pragma mark - SampleTurboModuleOptionalBaseAnimal + + #pragma mark - SampleTurboModuleOptionalBaseAnimal template struct SampleTurboModuleOptionalBaseAnimal { @@ -3543,7 +3828,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeStringTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeStringTurboModuleCxxSpecJSI : public TurboModule { protected: NativeStringTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); diff --git a/packages/react-native-codegen/src/generators/Utils.js b/packages/react-native-codegen/src/generators/Utils.js index bd1ec2f6b30a6c..da692692daafac 100644 --- a/packages/react-native-codegen/src/generators/Utils.js +++ b/packages/react-native-codegen/src/generators/Utils.js @@ -27,7 +27,27 @@ function indent(nice: string, spaces: number): string { .join('\n'); } +function toPascalCase(inString: string): string { + if (inString.length === 0) { + return inString; + } + + return inString[0].toUpperCase() + inString.slice(1); +} + +function toSafeCppString(input: string): string { + return input.split('-').map(toPascalCase).join(''); +} + +function getEnumName(moduleName: string, origEnumName: string): string { + const uppercasedPropName = toSafeCppString(origEnumName); + return `${moduleName}${uppercasedPropName}`; +} + module.exports = { capitalize, indent, + toPascalCase, + toSafeCppString, + getEnumName, }; diff --git a/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js b/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js index e9f4c057bed558..046b9ed27919b4 100644 --- a/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js +++ b/packages/react-native-codegen/src/generators/components/ComponentsGeneratorUtils.js @@ -25,11 +25,12 @@ import type { const { getCppTypeForAnnotation, getEnumMaskName, - getEnumName, generateStructName, getImports, } = require('./CppHelpers.js'); +const {getEnumName} = require('../Utils'); + function getNativeTypeFromAnnotation( componentName: string, prop: diff --git a/packages/react-native-codegen/src/generators/components/CppHelpers.js b/packages/react-native-codegen/src/generators/components/CppHelpers.js index 0bc7dd754eecc6..cb3090df08cdfa 100644 --- a/packages/react-native-codegen/src/generators/components/CppHelpers.js +++ b/packages/react-native-codegen/src/generators/components/CppHelpers.js @@ -11,17 +11,7 @@ 'use strict'; import type {NamedShape, PropTypeAnnotation} from '../../CodegenSchema'; -function upperCaseFirst(inString: string): string { - if (inString.length === 0) { - return inString; - } - - return inString[0].toUpperCase() + inString.slice(1); -} - -function toSafeCppString(input: string): string { - return input.split('-').map(upperCaseFirst).join(''); -} +const {getEnumName, toSafeCppString} = require('../Utils'); function toIntEnumValueName(propName: string, value: number): string { return `${toSafeCppString(propName)}${value}`; @@ -124,11 +114,6 @@ function generateStructName( return `${componentName}${additional}Struct`; } -function getEnumName(componentName: string, propName: string): string { - const uppercasedPropName = toSafeCppString(propName); - return `${componentName}${uppercasedPropName}`; -} - function getEnumMaskName(enumName: string): string { return `${enumName}Mask`; } @@ -224,10 +209,8 @@ function convertDefaultTypeToString( module.exports = { convertDefaultTypeToString, getCppTypeForAnnotation, - getEnumName, getEnumMaskName, getImports, - toSafeCppString, toIntEnumValueName, generateStructName, generateEventStructName, diff --git a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js index f61ca1ac091aa4..e1ae0d51b440b3 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js +++ b/packages/react-native-codegen/src/generators/components/GenerateEventEmitterH.js @@ -14,10 +14,9 @@ const nullthrows = require('nullthrows'); const { getCppTypeForAnnotation, - toSafeCppString, generateEventStructName, } = require('./CppHelpers'); -const {indent} = require('../Utils'); +const {indent, toSafeCppString} = require('../Utils'); import type { ComponentShape, diff --git a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js index cd0546a8b21251..15a7fcc425a174 100644 --- a/packages/react-native-codegen/src/generators/components/GeneratePropsH.js +++ b/packages/react-native-codegen/src/generators/components/GeneratePropsH.js @@ -19,12 +19,12 @@ const { const { convertDefaultTypeToString, getEnumMaskName, - getEnumName, - toSafeCppString, generateStructName, toIntEnumValueName, } = require('./CppHelpers.js'); +const {getEnumName, toSafeCppString} = require('../Utils'); + import type { ExtendsPropsShape, NamedShape, diff --git a/packages/react-native-codegen/src/generators/components/GenerateTests.js b/packages/react-native-codegen/src/generators/components/GenerateTests.js index 0a292e15fff64e..95f51da618d3dc 100644 --- a/packages/react-native-codegen/src/generators/components/GenerateTests.js +++ b/packages/react-native-codegen/src/generators/components/GenerateTests.js @@ -12,7 +12,9 @@ import type {ComponentShape, PropTypeAnnotation} from '../../CodegenSchema'; import type {SchemaType} from '../../CodegenSchema'; -const {getImports, toSafeCppString} = require('./CppHelpers'); +const {getImports} = require('./CppHelpers'); + +const {toSafeCppString} = require('../Utils'); type FilesOutput = Map; type PropValueType = string | number | boolean; diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index 5b366e953530ae..cef441f6fe1862 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -18,6 +18,7 @@ import type { NativeModuleFunctionTypeAnnotation, NativeModuleParamTypeAnnotation, NativeModuleTypeAnnotation, + NativeModuleEnumMap, } from '../../CodegenSchema'; import type {AliasResolver} from './Utils'; @@ -114,9 +115,11 @@ ${modules} type Param = NamedShape>; function serializeArg( + moduleName: string, arg: Param, index: number, resolveAlias: AliasResolver, + enumMap: NativeModuleEnumMap, ): string { const {typeAnnotation: nullableTypeAnnotation, optional} = arg; const [typeAnnotation, nullable] = @@ -208,9 +211,11 @@ function serializeArg( } function serializePropertyIntoHostFunction( + moduleName: string, hasteModuleName: string, property: NativeModulePropertyShape, resolveAlias: AliasResolver, + enumMap: NativeModuleEnumMap, ): string { const [propertyTypeAnnotation] = unwrapNullable(property.typeAnnotation); @@ -220,7 +225,7 @@ function serializePropertyIntoHostFunction( methodName: property.name, returnTypeAnnotation: propertyTypeAnnotation.returnTypeAnnotation, args: propertyTypeAnnotation.params.map((p, i) => - serializeArg(p, i, resolveAlias), + serializeArg(moduleName, p, i, resolveAlias, enumMap), ), }); } @@ -239,15 +244,18 @@ module.exports = { const nativeModule = nativeModules[hasteModuleName]; const { aliasMap, + enumMap, spec: {properties}, moduleName, } = nativeModule; const resolveAlias = createAliasResolver(aliasMap); const hostFunctions = properties.map(property => serializePropertyIntoHostFunction( + moduleName, hasteModuleName, property, resolveAlias, + enumMap, ), ); diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index a3156c4d7e49c9..56e1a09fcfc626 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -17,10 +17,20 @@ import type { NativeModuleFunctionTypeAnnotation, NativeModulePropertyShape, NativeModuleAliasMap, + NativeModuleEnumMap, + NativeModuleEnumMembers, + NativeModuleEnumMemberType, } from '../../CodegenSchema'; import type {AliasResolver} from './Utils'; -const {createAliasResolver, getModules} = require('./Utils'); + +const {getEnumName, toSafeCppString} = require('../Utils'); + +const { + createAliasResolver, + getModules, + getAreEnumMembersInteger, +} = require('./Utils'); const {indent} = require('../Utils'); const {unwrapNullable} = require('../../parsers/parsers-commons'); @@ -30,12 +40,15 @@ const ModuleClassDeclarationTemplate = ({ hasteModuleName, moduleProperties, structs, + enums, }: $ReadOnly<{ hasteModuleName: string, moduleProperties: string[], structs: string, + enums: string, }>) => { - return `${structs}class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule { + return `${enums} + ${structs}class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule { protected: ${hasteModuleName}CxxSpecJSI(std::shared_ptr jsInvoker); @@ -112,10 +125,12 @@ ${modules.join('\n\n')} }; function translatePrimitiveJSTypeToCpp( + moduleName: string, nullableTypeAnnotation: Nullable, optional: boolean, createErrorMessage: (typeName: string) => string, resolveAlias: AliasResolver, + enumMap: NativeModuleEnumMap, ) { const [typeAnnotation, nullable] = unwrapNullable( nullableTypeAnnotation, @@ -157,7 +172,11 @@ function translatePrimitiveJSTypeToCpp( case 'EnumDeclaration': switch (realTypeAnnotation.memberType) { case 'NumberTypeAnnotation': - return wrap('double'); + return getAreEnumMembersInteger( + enumMap[realTypeAnnotation.name].members, + ) + ? wrap('int') + : wrap('double'); case 'StringTypeAnnotation': return wrap('jsi::String'); default: @@ -192,10 +211,11 @@ function translatePrimitiveJSTypeToCpp( } } -function createStructs( +function createStructsString( moduleName: string, aliasMap: NativeModuleAliasMap, resolveAlias: AliasResolver, + enumMap: NativeModuleEnumMap, ): string { return Object.keys(aliasMap) .map(alias => { @@ -213,11 +233,13 @@ function createStructs( const paramemterConversion = value.properties .map((v, i) => { const translatedParam = translatePrimitiveJSTypeToCpp( + moduleName, v.typeAnnotation, false, typeName => `Unsupported type for param "${v.name}". Found: ${typeName}`, resolveAlias, + enumMap, ); return ` static ${translatedParam} ${v.name}ToJs(jsi::Runtime &rt, P${i} value) { return bridging::toJs(rt, value); @@ -281,9 +303,128 @@ ${paramemterConversion} .join('\n'); } +type NativeEnumMemberValueType = 'std::string' | 'int32_t' | 'float'; + +const EnumTemplate = ({ + enumName, + values, + fromCases, + toCases, + nativeEnumMemberType, +}: { + enumName: string, + values: string, + fromCases: string, + toCases: string, + nativeEnumMemberType: NativeEnumMemberValueType, +}) => { + const fromValue = + nativeEnumMemberType === 'std::string' + ? 'const jsi::String &rawValue' + : `${nativeEnumMemberType} value`; + + const fromValueConvertion = + nativeEnumMemberType === 'std::string' + ? 'std::string value = rawValue.utf8(rt);' + : ''; + + const toValue = + nativeEnumMemberType === 'std::string' ? 'jsi::String' : 'jsi::Value'; + + return ` +#pragma mark - ${enumName} + +enum ${enumName} { ${values} }; + +template <> +struct Bridging<${enumName}> { + static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}) { + ${fromValueConvertion} + ${fromCases} + } + + static ${toValue} toJs(jsi::Runtime &rt, ${enumName} value) { + ${toCases} + } +};`; +}; + +function generateEnum( + moduleName: string, + origEnumName: string, + members: NativeModuleEnumMembers, + memberType: NativeModuleEnumMemberType, +): string { + const enumName = getEnumName(moduleName, origEnumName); + + const nativeEnumMemberType: NativeEnumMemberValueType = + memberType === 'StringTypeAnnotation' + ? 'std::string' + : getAreEnumMembersInteger(members) + ? 'int32_t' + : 'float'; + + const getMemberValueAppearance = (value: string) => + memberType === 'StringTypeAnnotation' + ? `"${value}"` + : `${value}${nativeEnumMemberType === 'float' ? 'f' : ''}`; + + const fromCases = + members + .map( + member => `if (value == ${getMemberValueAppearance(member.value)}) { + return ${enumName}::${toSafeCppString(member.name)}; + }`, + ) + .join(' else ') + + ` else { + throw jsi::JSError(rt, "No appropriate enum member found for value"); + }`; + + const toCases = + members + .map( + member => `if (value == ${enumName}::${toSafeCppString(member.name)}) { + return bridging::toJs(rt, ${getMemberValueAppearance(member.value)}); + }`, + ) + .join(' else ') + + ` else { + throw jsi::JSError(rt, "No appropriate enum member found for enum value"); + }`; + + return EnumTemplate({ + enumName, + values: members.map(member => member.name).join(', '), + fromCases, + toCases, + nativeEnumMemberType, + }); +} + +function createEnums( + moduleName: string, + enumMap: NativeModuleEnumMap, + resolveAlias: AliasResolver, +): string { + return Object.entries(enumMap) + .map(([enumName, enumNode]) => { + return generateEnum( + moduleName, + enumName, + enumNode.members, + enumNode.memberType, + ); + }) + .filter(Boolean) + .join('\n'); +} + function translatePropertyToCpp( + moduleName: string, prop: NativeModulePropertyShape, resolveAlias: AliasResolver, + enumMap: NativeModuleEnumMap, abstract: boolean = false, ) { const [propTypeAnnotation] = @@ -295,20 +436,24 @@ function translatePropertyToCpp( const paramTypes = propTypeAnnotation.params.map(param => { const translatedParam = translatePrimitiveJSTypeToCpp( + moduleName, param.typeAnnotation, param.optional, typeName => `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, resolveAlias, + enumMap, ); return `${translatedParam} ${param.name}`; }); const returnType = translatePrimitiveJSTypeToCpp( + moduleName, propTypeAnnotation.returnTypeAnnotation, false, typeName => `Unsupported return type for ${prop.name}. Found: ${typeName}`, resolveAlias, + enumMap, ); // The first param will always be the runtime reference. @@ -342,25 +487,39 @@ module.exports = { const modules = Object.keys(nativeModules).flatMap(hasteModuleName => { const { aliasMap, + enumMap, spec: {properties}, moduleName, } = nativeModules[hasteModuleName]; const resolveAlias = createAliasResolver(aliasMap); - const structs = createStructs(moduleName, aliasMap, resolveAlias); + const structs = createStructsString( + moduleName, + aliasMap, + resolveAlias, + enumMap, + ); + const enums = createEnums(moduleName, enumMap, resolveAlias); return [ ModuleClassDeclarationTemplate({ hasteModuleName, moduleProperties: properties.map(prop => - translatePropertyToCpp(prop, resolveAlias, true), + translatePropertyToCpp( + moduleName, + prop, + resolveAlias, + enumMap, + true, + ), ), structs, + enums, }), ModuleSpecClassDeclarationTemplate({ hasteModuleName, moduleName, moduleProperties: properties.map(prop => - translatePropertyToCpp(prop, resolveAlias), + translatePropertyToCpp(moduleName, prop, resolveAlias, enumMap), ), }), ]; diff --git a/packages/react-native-codegen/src/generators/modules/Utils.js b/packages/react-native-codegen/src/generators/modules/Utils.js index b89df46a01f896..8d172d32abc814 100644 --- a/packages/react-native-codegen/src/generators/modules/Utils.js +++ b/packages/react-native-codegen/src/generators/modules/Utils.js @@ -15,6 +15,7 @@ import type { NativeModuleAliasMap, NativeModuleObjectTypeAnnotation, NativeModuleSchema, + NativeModuleEnumMembers, } from '../../CodegenSchema'; const invariant = require('invariant'); @@ -47,7 +48,12 @@ function getModules( ); } +function getAreEnumMembersInteger(members: NativeModuleEnumMembers): boolean { + return !members.some(m => `${m.value}`.includes('.')); +} + module.exports = { createAliasResolver, getModules, + getAreEnumMembersInteger, }; diff --git a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js index 5764facb3bc32e..8f96919d4c3843 100644 --- a/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js +++ b/packages/react-native-codegen/src/generators/modules/__test_fixtures__/fixtures.js @@ -31,7 +31,57 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { NativeSampleTurboModule: { type: 'NativeModule', aliasMap: {}, - enumMap: {}, + enumMap: { + NumEnum: { + type: 'EnumDeclarationWithMembers', + name: 'NumEnum', + memberType: 'NumberTypeAnnotation', + members: [ + { + name: 'ONE', + value: '1', + }, + { + name: 'TWO', + value: '2', + }, + ], + }, + FloatEnum: { + type: 'EnumDeclarationWithMembers', + name: 'FloatEnum', + memberType: 'NumberTypeAnnotation', + members: [ + { + name: 'POINT_ZERO', + value: '0.0', + }, + { + name: 'POINT_ONE', + value: '0.1', + }, + { + name: 'POINT_TWO', + value: '0.2', + }, + ], + }, + StringEnum: { + type: 'EnumDeclarationWithMembers', + name: 'StringEnum', + memberType: 'StringTypeAnnotation', + members: [ + { + name: 'HELLO', + value: 'hello', + }, + { + name: 'GoodBye', + value: 'goodbye', + }, + ], + }, + }, spec: { properties: [ { @@ -235,6 +285,19 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { ], }, }, + { + name: 'getEnumReturn', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'EnumDeclaration', + name: 'NumEnum', + memberType: 'NumberTypeAnnotation', + }, + params: [], + }, + }, { name: 'getValueWithCallback', optional: false, @@ -309,6 +372,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { name: 'enumInt', optional: false, typeAnnotation: { + name: 'NumEnum', type: 'EnumDeclaration', memberType: 'NumberTypeAnnotation', }, @@ -317,6 +381,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { name: 'enumFloat', optional: false, typeAnnotation: { + name: 'FloatEnum', type: 'EnumDeclaration', memberType: 'NumberTypeAnnotation', }, @@ -325,6 +390,7 @@ const SIMPLE_NATIVE_MODULES: SchemaType = { name: 'enumString', optional: false, typeAnnotation: { + name: 'StringEnum', type: 'EnumDeclaration', memberType: 'StringTypeAnnotation', }, @@ -1516,7 +1582,57 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = { ], }, }, - enumMap: {}, + enumMap: { + NumEnum: { + type: 'EnumDeclarationWithMembers', + name: 'NumEnum', + memberType: 'NumberTypeAnnotation', + members: [ + { + name: 'ONE', + value: '1', + }, + { + name: 'TWO', + value: '2', + }, + ], + }, + FloatEnum: { + type: 'EnumDeclarationWithMembers', + name: 'FloatEnum', + memberType: 'NumberTypeAnnotation', + members: [ + { + name: 'POINT_ZERO', + value: '0.0', + }, + { + name: 'POINT_ONE', + value: '0.1', + }, + { + name: 'POINT_TWO', + value: '0.2', + }, + ], + }, + StringEnum: { + type: 'EnumDeclarationWithMembers', + name: 'StringEnum', + memberType: 'StringTypeAnnotation', + members: [ + { + name: 'HELLO', + value: 'hello', + }, + { + name: 'GoodBye', + value: 'goodbye', + }, + ], + }, + }, spec: { properties: [ { @@ -1577,6 +1693,7 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = { name: 'enumInt', optional: false, typeAnnotation: { + name: 'NumEnum', type: 'EnumDeclaration', memberType: 'NumberTypeAnnotation', }, @@ -1585,6 +1702,7 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = { name: 'enumFloat', optional: false, typeAnnotation: { + name: 'FloatEnum', type: 'EnumDeclaration', memberType: 'NumberTypeAnnotation', }, @@ -1593,6 +1711,7 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = { name: 'enumString', optional: false, typeAnnotation: { + name: 'StringEnum', type: 'EnumDeclaration', memberType: 'StringTypeAnnotation', }, @@ -1645,6 +1764,19 @@ const CXX_ONLY_NATIVE_MODULES: SchemaType = { ], }, }, + { + name: 'getEnumReturn', + optional: false, + typeAnnotation: { + type: 'FunctionTypeAnnotation', + returnTypeAnnotation: { + type: 'EnumDeclaration', + name: 'NumEnum', + memberType: 'NumberTypeAnnotation', + }, + params: [], + }, + }, ], }, moduleName: 'SampleTurboModuleCxx', diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index 4a22ab252d743b..a07e0f5a717c27 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -121,6 +121,9 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnums(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getUnion(rt, args[0].asNumber(), args[1].asNumber(), args[2].asObject(rt), args[3].asString(rt)); } +static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getEnumReturn(rt); +} NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker) : TurboModule(\\"SampleTurboModuleCxx\\", jsInvoker) { @@ -128,6 +131,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared methodMap_[\\"getNullableNumberFromNullableAlias\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNullableNumberFromNullableAlias}; methodMap_[\\"getEnums\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnums}; methodMap_[\\"getUnion\\"] = MethodMetadata {4, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion}; + methodMap_[\\"getEnumReturn\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn}; } @@ -321,6 +325,9 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(js static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue(rt, args[0].asNumber(), args[1].asString(rt), args[2].asObject(rt)); } +static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->getEnumReturn(rt); +} static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback(rt, args[0].asObject(rt).asFunction(rt)); return jsi::Value::undefined(); @@ -346,6 +353,7 @@ NativeSampleTurboModuleCxxSpecJSI::NativeSampleTurboModuleCxxSpecJSI(std::shared methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject}; methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag}; methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue}; + methodMap_[\\"getEnumReturn\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn}; methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback}; methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise}; methodMap_[\\"getValueWithOptionalArg\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithOptionalArg}; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index 82800da2235299..e0bd0a41e962bb 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -19,7 +19,8 @@ Map { namespace facebook { namespace react { -class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -80,7 +81,8 @@ Map { namespace facebook { namespace react { -class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -202,7 +204,95 @@ Map { namespace facebook { namespace react { -#pragma mark - SampleTurboModuleCxxBaseObjectAlias + +#pragma mark - SampleTurboModuleCxxNumEnum + +enum SampleTurboModuleCxxNumEnum { ONE, TWO }; + +template <> +struct Bridging { + static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, int32_t value) { + + if (value == 1) { + return SampleTurboModuleCxxNumEnum::ONE; + } else if (value == 2) { + return SampleTurboModuleCxxNumEnum::TWO; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxNumEnum value) { + if (value == SampleTurboModuleCxxNumEnum::ONE) { + return bridging::toJs(rt, 1); + } else if (value == SampleTurboModuleCxxNumEnum::TWO) { + return bridging::toJs(rt, 2); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - SampleTurboModuleCxxFloatEnum + +enum SampleTurboModuleCxxFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO }; + +template <> +struct Bridging { + static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, float value) { + + if (value == 0.0f) { + return SampleTurboModuleCxxFloatEnum::POINT_ZERO; + } else if (value == 0.1f) { + return SampleTurboModuleCxxFloatEnum::POINT_ONE; + } else if (value == 0.2f) { + return SampleTurboModuleCxxFloatEnum::POINT_TWO; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxFloatEnum value) { + if (value == SampleTurboModuleCxxFloatEnum::POINT_ZERO) { + return bridging::toJs(rt, 0.0f); + } else if (value == SampleTurboModuleCxxFloatEnum::POINT_ONE) { + return bridging::toJs(rt, 0.1f); + } else if (value == SampleTurboModuleCxxFloatEnum::POINT_TWO) { + return bridging::toJs(rt, 0.2f); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - SampleTurboModuleCxxStringEnum + +enum SampleTurboModuleCxxStringEnum { HELLO, GoodBye }; + +template <> +struct Bridging { + static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + std::string value = rawValue.utf8(rt); + if (value == \\"hello\\") { + return SampleTurboModuleCxxStringEnum::HELLO; + } else if (value == \\"goodbye\\") { + return SampleTurboModuleCxxStringEnum::GoodBye; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleCxxStringEnum value) { + if (value == SampleTurboModuleCxxStringEnum::HELLO) { + return bridging::toJs(rt, \\"hello\\"); + } else if (value == SampleTurboModuleCxxStringEnum::GoodBye) { + return bridging::toJs(rt, \\"goodbye\\"); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + #pragma mark - SampleTurboModuleCxxBaseObjectAlias template struct SampleTurboModuleCxxBaseObjectAlias { @@ -246,8 +336,9 @@ protected: public: virtual jsi::Value getMixed(jsi::Runtime &rt, jsi::Value arg) = 0; virtual std::optional getNullableNumberFromNullableAlias(jsi::Runtime &rt, std::optional a) = 0; - virtual jsi::String getEnums(jsi::Runtime &rt, double enumInt, double enumFloat, jsi::String enumString) = 0; + virtual jsi::String getEnums(jsi::Runtime &rt, int enumInt, double enumFloat, jsi::String enumString) = 0; virtual jsi::Object getUnion(jsi::Runtime &rt, double chooseInt, double chooseFloat, jsi::Object chooseObject, jsi::String chooseString) = 0; + virtual int getEnumReturn(jsi::Runtime &rt) = 0; }; @@ -285,7 +376,7 @@ private: return bridging::callFromJs>( rt, &T::getNullableNumberFromNullableAlias, jsInvoker_, instance_, std::move(a)); } - jsi::String getEnums(jsi::Runtime &rt, double enumInt, double enumFloat, jsi::String enumString) override { + jsi::String getEnums(jsi::Runtime &rt, int enumInt, double enumFloat, jsi::String enumString) override { static_assert( bridging::getParameterCount(&T::getEnums) == 4, \\"Expected getEnums(...) to have 4 parameters\\"); @@ -301,6 +392,14 @@ private: return bridging::callFromJs( rt, &T::getUnion, jsInvoker_, instance_, std::move(chooseInt), std::move(chooseFloat), std::move(chooseObject), std::move(chooseString)); } + int getEnumReturn(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::getEnumReturn) == 1, + \\"Expected getEnumReturn(...) to have 1 parameters\\"); + + return bridging::callFromJs( + rt, &T::getEnumReturn, jsInvoker_, instance_); + } private: T *instance_; @@ -334,7 +433,8 @@ Map { namespace facebook { namespace react { -class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -395,7 +495,8 @@ Map { namespace facebook { namespace react { -#pragma mark - AliasTurboModuleBaseOptions + + #pragma mark - AliasTurboModuleBaseOptions template struct AliasTurboModuleBaseOptions { @@ -539,7 +640,8 @@ Map { namespace facebook { namespace react { -#pragma mark - CameraRollManagerBasePhotoIdentifierImage + + #pragma mark - CameraRollManagerBasePhotoIdentifierImage template struct CameraRollManagerBasePhotoIdentifierImage { @@ -846,7 +948,8 @@ private: Delegate delegate_; }; -#pragma mark - ExceptionsManagerBaseStackFrame + + #pragma mark - ExceptionsManagerBaseStackFrame template struct ExceptionsManagerBaseStackFrame { @@ -1099,7 +1202,95 @@ Map { namespace facebook { namespace react { -class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { + +#pragma mark - SampleTurboModuleNumEnum + +enum SampleTurboModuleNumEnum { ONE, TWO }; + +template <> +struct Bridging { + static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, int32_t value) { + + if (value == 1) { + return SampleTurboModuleNumEnum::ONE; + } else if (value == 2) { + return SampleTurboModuleNumEnum::TWO; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleNumEnum value) { + if (value == SampleTurboModuleNumEnum::ONE) { + return bridging::toJs(rt, 1); + } else if (value == SampleTurboModuleNumEnum::TWO) { + return bridging::toJs(rt, 2); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - SampleTurboModuleFloatEnum + +enum SampleTurboModuleFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO }; + +template <> +struct Bridging { + static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, float value) { + + if (value == 0.0f) { + return SampleTurboModuleFloatEnum::POINT_ZERO; + } else if (value == 0.1f) { + return SampleTurboModuleFloatEnum::POINT_ONE; + } else if (value == 0.2f) { + return SampleTurboModuleFloatEnum::POINT_TWO; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleFloatEnum value) { + if (value == SampleTurboModuleFloatEnum::POINT_ZERO) { + return bridging::toJs(rt, 0.0f); + } else if (value == SampleTurboModuleFloatEnum::POINT_ONE) { + return bridging::toJs(rt, 0.1f); + } else if (value == SampleTurboModuleFloatEnum::POINT_TWO) { + return bridging::toJs(rt, 0.2f); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + +#pragma mark - SampleTurboModuleStringEnum + +enum SampleTurboModuleStringEnum { HELLO, GoodBye }; + +template <> +struct Bridging { + static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + std::string value = rawValue.utf8(rt); + if (value == \\"hello\\") { + return SampleTurboModuleStringEnum::HELLO; + } else if (value == \\"goodbye\\") { + return SampleTurboModuleStringEnum::GoodBye; + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for value\\"); + } + } + + static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleStringEnum value) { + if (value == SampleTurboModuleStringEnum::HELLO) { + return bridging::toJs(rt, \\"hello\\"); + } else if (value == SampleTurboModuleStringEnum::GoodBye) { + return bridging::toJs(rt, \\"goodbye\\"); + } else { + throw jsi::JSError(rt, \\"No appropriate enum member found for enum value\\"); + } + } +}; + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1113,10 +1304,11 @@ public: virtual jsi::Object getObject(jsi::Runtime &rt, jsi::Object arg) = 0; virtual double getRootTag(jsi::Runtime &rt, double arg) = 0; virtual jsi::Object getValue(jsi::Runtime &rt, double x, jsi::String y, jsi::Object z) = 0; + virtual int getEnumReturn(jsi::Runtime &rt) = 0; virtual void getValueWithCallback(jsi::Runtime &rt, jsi::Function callback) = 0; virtual jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) = 0; virtual jsi::Value getValueWithOptionalArg(jsi::Runtime &rt, std::optional parameter) = 0; - virtual jsi::String getEnums(jsi::Runtime &rt, double enumInt, double enumFloat, jsi::String enumString) = 0; + virtual jsi::String getEnums(jsi::Runtime &rt, int enumInt, double enumFloat, jsi::String enumString) = 0; }; @@ -1210,6 +1402,14 @@ private: return bridging::callFromJs( rt, &T::getValue, jsInvoker_, instance_, std::move(x), std::move(y), std::move(z)); } + int getEnumReturn(jsi::Runtime &rt) override { + static_assert( + bridging::getParameterCount(&T::getEnumReturn) == 1, + \\"Expected getEnumReturn(...) to have 1 parameters\\"); + + return bridging::callFromJs( + rt, &T::getEnumReturn, jsInvoker_, instance_); + } void getValueWithCallback(jsi::Runtime &rt, jsi::Function callback) override { static_assert( bridging::getParameterCount(&T::getValueWithCallback) == 2, @@ -1234,7 +1434,7 @@ private: return bridging::callFromJs( rt, &T::getValueWithOptionalArg, jsInvoker_, instance_, std::move(parameter)); } - jsi::String getEnums(jsi::Runtime &rt, double enumInt, double enumFloat, jsi::String enumString) override { + jsi::String getEnums(jsi::Runtime &rt, int enumInt, double enumFloat, jsi::String enumString) override { static_assert( bridging::getParameterCount(&T::getEnums) == 4, \\"Expected getEnums(...) to have 4 parameters\\"); @@ -1275,7 +1475,8 @@ Map { namespace facebook { namespace react { -class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeSampleTurboModuleCxxSpecJSI : public TurboModule { protected: NativeSampleTurboModuleCxxSpecJSI(std::shared_ptr jsInvoker); @@ -1318,7 +1519,8 @@ private: Delegate delegate_; }; -class JSI_EXPORT NativeSampleTurboModule2CxxSpecJSI : public TurboModule { + + class JSI_EXPORT NativeSampleTurboModule2CxxSpecJSI : public TurboModule { protected: NativeSampleTurboModule2CxxSpecJSI(std::shared_ptr jsInvoker); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap index 4e923454c77659..fdd04f630546b5 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleHObjCpp-test.js.snap @@ -885,6 +885,7 @@ namespace JS { - (NSDictionary *)getValue:(double)x y:(NSString *)y z:(NSDictionary *)z; +- (NSNumber *)getEnumReturn; - (void)getValueWithCallback:(RCTResponseSenderBlock)callback; - (void)getValueWithPromise:(BOOL)error resolve:(RCTPromiseResolveBlock)resolve diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap index 93ec0208c32cf5..cc0c13d0f5653a 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap @@ -425,6 +425,10 @@ public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaMo @DoNotStrip public abstract WritableMap getValue(double x, String y, ReadableMap z); + @ReactMethod(isBlockingSynchronousMethod = true) + @DoNotStrip + public abstract double getEnumReturn(); + @ReactMethod @DoNotStrip public abstract void getValueWithCallback(Callback callback); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap index bb1428ed7ae0cd..177f066876aa61 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJniCpp-test.js.snap @@ -374,6 +374,11 @@ static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getVal return static_cast(turboModule).invokeJavaMethod(rt, ObjectKind, \\"getValue\\", \\"(DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)Lcom/facebook/react/bridge/WritableMap;\\", args, count, cachedMethodId); } +static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getEnumReturn(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + static jmethodID cachedMethodId = nullptr; + return static_cast(turboModule).invokeJavaMethod(rt, NumberKind, \\"getEnumReturn\\", \\"()D\\", args, count, cachedMethodId); +} + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { static jmethodID cachedMethodId = nullptr; return static_cast(turboModule).invokeJavaMethod(rt, VoidKind, \\"getValueWithCallback\\", \\"(Lcom/facebook/react/bridge/Callback;)V\\", args, count, cachedMethodId); @@ -405,6 +410,7 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo methodMap_[\\"getObject\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject}; methodMap_[\\"getRootTag\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getRootTag}; methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + methodMap_[\\"getEnumReturn\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getEnumReturn}; methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise}; methodMap_[\\"getValueWithOptionalArg\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithOptionalArg}; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap index 867858ae3252a7..d9936be271e6d8 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleMm-test.js.snap @@ -424,6 +424,10 @@ namespace facebook { return static_cast(turboModule).invokeObjCMethod(rt, ObjectKind, \\"getValue\\", @selector(getValue:y:z:), args, count); } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getEnumReturn(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { + return static_cast(turboModule).invokeObjCMethod(rt, NumberKind, \\"getEnumReturn\\", @selector(getEnumReturn), args, count); + } + static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { return static_cast(turboModule).invokeObjCMethod(rt, VoidKind, \\"getValueWithCallback\\", @selector(getValueWithCallback:), args, count); } @@ -471,6 +475,9 @@ namespace facebook { methodMap_[\\"getValue\\"] = MethodMetadata {3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue}; + methodMap_[\\"getEnumReturn\\"] = MethodMetadata {0, __hostFunction_NativeSampleTurboModuleSpecJSI_getEnumReturn}; + + methodMap_[\\"getValueWithCallback\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback}; diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp index 200112714168ac..ba25084e06a69e 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp @@ -33,10 +33,24 @@ ConstantsStruct NativeCxxModuleExample::getConstants(jsi::Runtime &rt) { return ConstantsStruct{true, 69, "react-native"}; } -EnumInt NativeCxxModuleExample::getEnum(jsi::Runtime &rt, EnumInt arg) { +CustomEnumInt NativeCxxModuleExample::getCustomEnum( + jsi::Runtime &rt, + CustomEnumInt arg) { return arg; } +NativeCxxModuleExampleCxxEnumFloat NativeCxxModuleExample::getNumEnum( + jsi::Runtime &rt, + NativeCxxModuleExampleCxxEnumInt arg) { + return NativeCxxModuleExampleCxxEnumFloat::FB; +} + +NativeCxxModuleExampleCxxEnumStr NativeCxxModuleExample::getStrEnum( + jsi::Runtime &rt, + NativeCxxModuleExampleCxxEnumNone arg) { + return NativeCxxModuleExampleCxxEnumStr::SB; +} + std::map> NativeCxxModuleExample::getMap( jsi::Runtime &rt, std::map> arg) { diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h index bd36f16e7482a0..c9a8cc48cce2cc 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.h @@ -54,21 +54,21 @@ struct Bridging : NativeCxxModuleExampleCxxBaseValueStructBridging< ObjectStruct> {}; #pragma mark - enums -enum EnumInt { A = 23, B = 42 }; +enum CustomEnumInt { A = 23, B = 42 }; template <> -struct Bridging { - static EnumInt fromJs(jsi::Runtime &rt, int32_t value) { +struct Bridging { + static CustomEnumInt fromJs(jsi::Runtime &rt, int32_t value) { if (value == 23) { - return EnumInt::A; + return CustomEnumInt::A; } else if (value == 42) { - return EnumInt::B; + return CustomEnumInt::B; } else { throw jsi::JSError(rt, "Invalid enum value"); } } - static jsi::Value toJs(jsi::Runtime &rt, EnumInt value) { + static jsi::Value toJs(jsi::Runtime &rt, CustomEnumInt value) { return bridging::toJs(rt, static_cast(value)); } }; @@ -91,7 +91,15 @@ class NativeCxxModuleExample ConstantsStruct getConstants(jsi::Runtime &rt); - EnumInt getEnum(jsi::Runtime &rt, EnumInt arg); + CustomEnumInt getCustomEnum(jsi::Runtime &rt, CustomEnumInt arg); + + NativeCxxModuleExampleCxxEnumFloat getNumEnum( + jsi::Runtime &rt, + NativeCxxModuleExampleCxxEnumInt arg); + + NativeCxxModuleExampleCxxEnumStr getStrEnum( + jsi::Runtime &rt, + NativeCxxModuleExampleCxxEnumNone arg); std::map> getMap( jsi::Runtime &rt, diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js index d4e320077f73c0..2e52bf1eaafa7e 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.js @@ -13,8 +13,23 @@ import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport'; import {TurboModuleRegistry} from 'react-native'; export enum EnumInt { - A = 23, - B = 42, + IA = 23, + IB = 42, +} + +export enum EnumFloat { + FA = 1.23, + FB = 4.56, +} + +export enum EnumNone { + NA, + NB, +} + +export enum EnumStr { + SA = 's---a', + SB = 's---b', } export type UnionFloat = 1.44 | 2.88 | 5.76; @@ -43,7 +58,9 @@ export interface Spec extends TurboModule { +getArray: (arg: Array) => Array; +getBool: (arg: boolean) => boolean; +getConstants: () => ConstantsStruct; - +getEnum: (arg: EnumInt) => EnumInt; + +getCustomEnum: (arg: EnumInt) => EnumInt; + +getNumEnum: (arg: EnumInt) => EnumFloat; + +getStrEnum: (arg: EnumNone) => EnumStr; +getMap: (arg: {[key: string]: ?number}) => {[key: string]: ?number}; +getNumber: (arg: number) => number; +getObject: (arg: ObjectStruct) => ObjectStruct; diff --git a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js index 9c2946883c5702..cecbacba004548 100644 --- a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js @@ -22,6 +22,7 @@ import { import * as React from 'react'; import NativeCxxModuleExample, { EnumInt, + EnumNone, } from '../../../NativeCxxModuleExample/NativeCxxModuleExample'; type State = {| @@ -40,7 +41,9 @@ type Examples = | 'getArray' | 'getBool' | 'getConstants' - | 'getEnum' + | 'getCustomEnum' + | 'getNumEnum' + | 'getStrEnum' | 'getMap' | 'getNumber' | 'getObject' @@ -74,8 +77,9 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { ]), getBool: () => NativeCxxModuleExample?.getBool(true), getConstants: () => NativeCxxModuleExample?.getConstants(), - getEnum: () => NativeCxxModuleExample?.getEnum(EnumInt.A), - getMap: () => NativeCxxModuleExample?.getMap({a: 1, b: null, c: 3}), + getCustomEnum: () => NativeCxxModuleExample?.getCustomEnum(EnumInt.IB), + getNumEnum: () => NativeCxxModuleExample?.getNumEnum(EnumInt.IB), + getStrEnum: () => NativeCxxModuleExample?.getStrEnum(EnumNone.NB), getNumber: () => NativeCxxModuleExample?.getNumber(99.95), getObject: () => NativeCxxModuleExample?.getObject({a: 1, b: 'foo', c: null}), From 6ac88a4378734cc169c2ff00b75da04a9659dbe0 Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Mon, 13 Feb 2023 21:55:33 -0800 Subject: [PATCH 03/81] Add TraceUpdateOverlay native component to render highlights on trace updates Summary: This diff adds `TraceUpdateOverlay` native component to render highlights when trace update is detected from React JS. This allows a highlight border to be rendered outside of the component with re-renders. - Created `TraceUpdateOverlay` native component and added to the `DebugCorePackage` - Added to C++ registry so it's compatible with Fabric - Added to `AppContainer` for all RN apps when global devtools hook is available Changelog: [Android][Internal] - Add trace update overlay to show re-render highlights Reviewed By: javache Differential Revision: D42831719 fbshipit-source-id: 30c2e24859a316c27700270087a0d7779d7ad8ed --- .../TraceUpdateOverlay/TraceUpdateOverlay.js | 163 ++++++++++++++++++ .../TraceUpdateOverlayNativeComponent.js | 43 +++++ .../src/main/java/com/facebook/react/BUCK | 1 + .../com/facebook/react/DebugCorePackage.java | 54 +++++- .../react/views/traceupdateoverlay/BUCK | 29 ++++ .../TraceUpdateOverlay.java | 70 ++++++++ .../TraceUpdateOverlayManager.java | 83 +++++++++ 7 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js create mode 100644 Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/BUCK create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java diff --git a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js new file mode 100644 index 00000000000000..6e5914fd25b26f --- /dev/null +++ b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -0,0 +1,163 @@ +/** + * 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 {Overlay} from './TraceUpdateOverlayNativeComponent'; + +import processColor from '../../StyleSheet/processColor'; +import StyleSheet from '../../StyleSheet/StyleSheet'; +import View from '../View/View'; +import TraceUpdateOverlayNativeComponent, { + Commands, +} from './TraceUpdateOverlayNativeComponent'; +import * as React from 'react'; + +type AgentEvents = { + drawTraceUpdates: [Array<{node: TraceNode, color: string}>], + disableTraceUpdates: [], +}; + +interface Agent { + addListener>( + event: Event, + listener: (...AgentEvents[Event]) => void, + ): void; + removeListener(event: $Keys, listener: () => void): void; +} + +type TraceNode = { + canonical?: TraceNode, + measure?: ( + ( + x: number, + y: number, + width: number, + height: number, + left: number, + top: number, + ) => void, + ) => void, +}; + +type ReactDevToolsGlobalHook = { + on: (eventName: string, (agent: Agent) => void) => void, + off: (eventName: string, (agent: Agent) => void) => void, + reactDevtoolsAgent: Agent, +}; + +const {useEffect, useRef, useState} = React; +const hook: ReactDevToolsGlobalHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; +let devToolsAgent: ?Agent; + +export default function TraceUpdateOverlay(): React.Node { + const [overlayDisabled, setOverlayDisabled] = useState(false); + // This effect is designed to be explictly shown here to avoid re-subscribe from the same + // overlay component. + useEffect(() => { + function attachToDevtools(agent: Agent) { + devToolsAgent = agent; + agent.addListener('drawTraceUpdates', onAgentDrawTraceUpdates); + agent.addListener('disableTraceUpdates', onAgentDisableTraceUpdates); + } + + function subscribe() { + hook?.on('react-devtools', attachToDevtools); + if (hook?.reactDevtoolsAgent) { + attachToDevtools(hook.reactDevtoolsAgent); + } + } + + function unsubscribe() { + hook?.off('react-devtools', attachToDevtools); + const agent = devToolsAgent; + if (agent != null) { + agent.removeListener('drawTraceUpdates', onAgentDrawTraceUpdates); + agent.removeListener('disableTraceUpdates', onAgentDisableTraceUpdates); + devToolsAgent = null; + } + } + + function onAgentDrawTraceUpdates( + nodesToDraw: Array<{node: TraceNode, color: string}> = [], + ) { + // If overlay is disabled before, now it's enabled. + setOverlayDisabled(false); + + const newFramesToDraw: Array> = []; + nodesToDraw.forEach(({node, color}) => { + const component = node.canonical ?? node; + if (!component || !component.measure) { + return; + } + const frameToDrawPromise = new Promise(resolve => { + // The if statement here is to make flow happy + if (component.measure) { + // TODO(T145522797): We should refactor this to use `getBoundingClientRect` when Paper is no longer supported. + component.measure((x, y, width, height, left, top) => { + resolve({ + rect: {left, top, width, height}, + color: processColor(color), + }); + }); + } + }); + newFramesToDraw.push(frameToDrawPromise); + }); + Promise.all(newFramesToDraw).then( + results => { + if (nativeComponentRef.current != null) { + Commands.draw( + nativeComponentRef.current, + JSON.stringify( + results.filter( + ({rect, color}) => rect.width >= 0 && rect.height >= 0, + ), + ), + ); + } + }, + err => { + console.error(`Failed to measure updated traces. Error: ${err}`); + }, + ); + } + + function onAgentDisableTraceUpdates() { + // When trace updates are disabled from the backend, we won't receive draw events until it's enabled by the next draw. We can safely remove the overlay as it's not needed now. + setOverlayDisabled(true); + } + + subscribe(); + return unsubscribe; + }, []); // Only run once when the overlay initially rendered + + const nativeComponentRef = + useRef>(null); + + return ( + !overlayDisabled && ( + + + + ) + ); +} + +const styles = StyleSheet.create({ + overlay: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, +}); diff --git a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js new file mode 100644 index 00000000000000..837223e3774b2d --- /dev/null +++ b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlayNativeComponent.js @@ -0,0 +1,43 @@ +/** + * 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 {HostComponent} from '../../Renderer/shims/ReactNativeTypes'; +import type {ProcessedColorValue} from '../../StyleSheet/processColor'; +import type {ViewProps} from '../View/ViewPropTypes'; + +import codegenNativeCommands from '../../Utilities/codegenNativeCommands'; +import codegenNativeComponent from '../../Utilities/codegenNativeComponent'; +import * as React from 'react'; + +type NativeProps = $ReadOnly<{| + ...ViewProps, +|}>; +export type TraceUpdateOverlayNativeComponentType = HostComponent; +export type Overlay = { + rect: {left: number, top: number, width: number, height: number}, + color: ?ProcessedColorValue, +}; + +interface NativeCommands { + +draw: ( + viewRef: React.ElementRef, + // TODO(T144046177): Ideally we can pass array of Overlay, but currently + // Array type is not supported in RN codegen for building native commands. + overlays: string, + ) => void; +} + +export const Commands: NativeCommands = codegenNativeCommands({ + supportedCommands: ['draw'], +}); + +export default (codegenNativeComponent( + 'TraceUpdateOverlay', +): HostComponent); diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index 9b28df9df24aeb..4d800183de2a21 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -51,6 +51,7 @@ rn_android_library( react_native_target("java/com/facebook/react/turbomodule/core:core"), react_native_target("java/com/facebook/react/turbomodule/core/interfaces:interfaces"), react_native_target("java/com/facebook/react/views/imagehelper:imagehelper"), + react_native_target("java/com/facebook/react/views/traceupdateoverlay:traceupdateoverlay"), ], exported_deps = [ react_native_target("java/com/facebook/react/modules/core:core"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java b/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java index 6626d62f9df260..9a2028db3e153b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java @@ -7,6 +7,8 @@ package com.facebook.react; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ModuleSpec; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.devsupport.JSCHeapCapture; @@ -15,8 +17,15 @@ import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.ViewManager; +import com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlayManager; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; +import javax.inject.Provider; /** * Package defining core framework modules (e.g. UIManager). It should be used for modules that @@ -27,7 +36,9 @@ nativeModules = { JSCHeapCapture.class, }) -public class DebugCorePackage extends TurboReactPackage { +public class DebugCorePackage extends TurboReactPackage implements ViewManagerOnDemandReactPackage { + private @Nullable Map mViewManagers; + public DebugCorePackage() {} @Override @@ -81,4 +92,45 @@ public Map getReactModuleInfos() { "No ReactModuleInfoProvider for DebugCorePackage$$ReactModuleInfoProvider", e); } } + + private static void appendMap( + Map map, String name, Provider provider) { + map.put(name, ModuleSpec.viewManagerSpec(provider)); + } + + /** @return a map of view managers that should be registered with {@link UIManagerModule} */ + private Map getViewManagersMap(final ReactApplicationContext reactContext) { + if (mViewManagers == null) { + Map viewManagers = new HashMap<>(); + appendMap( + viewManagers, + TraceUpdateOverlayManager.REACT_CLASS, + new Provider() { + @Override + public NativeModule get() { + return new TraceUpdateOverlayManager(); + } + }); + + mViewManagers = viewManagers; + } + return mViewManagers; + } + + @Override + public List getViewManagers(ReactApplicationContext reactContext) { + return new ArrayList<>(getViewManagersMap(reactContext).values()); + } + + @Override + public Collection getViewManagerNames(ReactApplicationContext reactContext) { + return getViewManagersMap(reactContext).keySet(); + } + + @Override + public @Nullable ViewManager createViewManager( + ReactApplicationContext reactContext, String viewManagerName) { + ModuleSpec spec = getViewManagersMap(reactContext).get(viewManagerName); + return spec != null ? (ViewManager) spec.getProvider().get() : null; + } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/BUCK new file mode 100644 index 00000000000000..832e27f97d2ce3 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/BUCK @@ -0,0 +1,29 @@ +load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_target", "rn_android_library") + +oncall("react_native") + +rn_android_library( + name = "traceupdateoverlay", + srcs = glob(["*.java"]), + autoglob = False, + labels = [ + "pfh:ReactNative_CommonInfrastructurePlaceholder", + ], + language = "JAVA", + visibility = [ + "PUBLIC", + ], + deps = [ + react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), + react_native_dep("third-party/android/androidx:annotation"), + react_native_dep("third-party/android/androidx:core"), + react_native_dep("third-party/android/androidx:fragment"), + react_native_dep("third-party/android/androidx:legacy-support-core-utils"), + react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_target("java/com/facebook/react/bridge:bridge"), + react_native_target("java/com/facebook/react/module/annotations:annotations"), + react_native_target("java/com/facebook/react/uimanager:uimanager"), + react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), + react_native_target("java/com/facebook/react/util:util"), + ], +) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java b/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java new file mode 100644 index 00000000000000..6799848284828f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlay.java @@ -0,0 +1,70 @@ +/* + * 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.views.traceupdateoverlay; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.View; +import androidx.annotation.UiThread; +import com.facebook.react.uimanager.PixelUtil; +import java.util.ArrayList; +import java.util.List; + +public class TraceUpdateOverlay extends View { + private final Paint mOverlayPaint = new Paint(); + private List mOverlays = new ArrayList(); + + public static class Overlay { + private final int mColor; + private final RectF mRect; + + public Overlay(int color, RectF rect) { + mColor = color; + mRect = rect; + } + + public int getColor() { + return mColor; + } + + public RectF getPixelRect() { + return new RectF( + PixelUtil.toPixelFromDIP(mRect.left), + PixelUtil.toPixelFromDIP(mRect.top), + PixelUtil.toPixelFromDIP(mRect.right), + PixelUtil.toPixelFromDIP(mRect.bottom)); + } + } + + public TraceUpdateOverlay(Context context) { + super(context); + mOverlayPaint.setStyle(Paint.Style.STROKE); + mOverlayPaint.setStrokeWidth(6); + } + + @UiThread + public void setOverlays(List overlays) { + mOverlays = overlays; + invalidate(); + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (!mOverlays.isEmpty()) { + // Draw border outside of the given overlays to be aligned with web trace highlights + for (Overlay overlay : mOverlays) { + mOverlayPaint.setColor(overlay.getColor()); + canvas.drawRect(overlay.getPixelRect(), mOverlayPaint); + } + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java new file mode 100644 index 00000000000000..434be098b1a2fa --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/traceupdateoverlay/TraceUpdateOverlayManager.java @@ -0,0 +1,83 @@ +/* + * 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.views.traceupdateoverlay; + +import android.graphics.RectF; +import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; +import com.facebook.react.bridge.ReactNoCrashSoftException; +import com.facebook.react.bridge.ReactSoftExceptionLogger; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.views.traceupdateoverlay.TraceUpdateOverlay.Overlay; +import java.util.ArrayList; +import java.util.List; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +@ReactModule(name = TraceUpdateOverlayManager.REACT_CLASS) +public class TraceUpdateOverlayManager extends SimpleViewManager { + public static final String REACT_CLASS = "TraceUpdateOverlay"; + + public TraceUpdateOverlayManager() {} + + @Override + public void receiveCommand( + TraceUpdateOverlay view, String commandId, @Nullable ReadableArray args) { + switch (commandId) { + case "draw": + if (args == null) { + break; + } + + String overlaysStr = args.getString(0); + if (overlaysStr == null) { + return; + } + + try { + JSONArray overlaysArr = new JSONArray(overlaysStr); + List overlays = new ArrayList<>(); + for (int i = 0; i < overlaysArr.length(); i++) { + JSONObject overlay = overlaysArr.getJSONObject(i); + JSONObject rectObj = overlay.getJSONObject("rect"); + float left = (float) rectObj.getDouble("left"); + float top = (float) rectObj.getDouble("top"); + float right = (float) (left + rectObj.getDouble("width")); + float bottom = (float) (top + rectObj.getDouble("height")); + RectF rect = new RectF(left, top, right, bottom); + overlays.add(new Overlay(overlay.getInt("color"), rect)); + } + + view.setOverlays(overlays); + } catch (JSONException e) { + FLog.e(REACT_CLASS, "Failed to parse overlays: ", e); + } + break; + + default: + ReactSoftExceptionLogger.logSoftException( + REACT_CLASS, + new ReactNoCrashSoftException( + "Received unexpected command in TraceUpdateOverlayManager")); + } + } + + @Override + public TraceUpdateOverlay createViewInstance(ThemedReactContext context) { + return new TraceUpdateOverlay(context); + } + + @Override + public String getName() { + return REACT_CLASS; + } +} From 31ac1f8aecb3e7a9376d83ed3dcd81dc4e70b164 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Tue, 14 Feb 2023 04:12:39 -0800 Subject: [PATCH 04/81] fix[virtualized-lists]: do not ship tests in npm package (#36143) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36143 Changelog: [Internal] Currently, some `__tests__` are included in `react-native/virtualized-lists`, added them to ignore list, so that we will remove it in the next publish Reviewed By: christophpurrer Differential Revision: D43159337 fbshipit-source-id: 27ed0adf85387a2e8ac902da57888f0b188b0b91 --- packages/virtualized-lists/.npmignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/virtualized-lists/.npmignore diff --git a/packages/virtualized-lists/.npmignore b/packages/virtualized-lists/.npmignore new file mode 100644 index 00000000000000..c912533dd7d2dd --- /dev/null +++ b/packages/virtualized-lists/.npmignore @@ -0,0 +1 @@ +__tests__ From f72f8daeaf20ae53e778143aecbb96303852aeb0 Mon Sep 17 00:00:00 2001 From: szymonrybczak Date: Tue, 14 Feb 2023 04:33:39 -0800 Subject: [PATCH 05/81] feat: add invoking dev menu on iOS by pressing `d` in terminal (#36115) Summary: Inspired by tido64's comment https://github.com/react-native-community/cli/issues/1820#issuecomment-1424270890 I'm adding missing implementation on iOS for invoking dev menu by pressing `d` in terminal while metro is launched. ## Changelog [IOS][ADDED] - Add invoking dev menu on iOS by pressing `d` in terminal. Pull Request resolved: https://github.com/facebook/react-native/pull/36115 Test Plan: Press `d` in terminal while metro is launched - dev menu should appear. https://user-images.githubusercontent.com/63900941/217936561-deea1390-221e-4f32-bbc4-e6fcfdf2a992.mp4 Reviewed By: rshest Differential Revision: D43185001 Pulled By: javache fbshipit-source-id: daa7af3b24b1b9f10d1a1ef8db8d9af816e912ea --- React/CoreModules/RCTDevSettings.mm | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/React/CoreModules/RCTDevSettings.mm b/React/CoreModules/RCTDevSettings.mm index e243eb0e0ade1e..e19a810d877364 100644 --- a/React/CoreModules/RCTDevSettings.mm +++ b/React/CoreModules/RCTDevSettings.mm @@ -117,6 +117,7 @@ - (void)_reloadWithDefaults:(NSDictionary *)defaultValues #if RCT_DEV_SETTINGS_ENABLE_PACKAGER_CONNECTION static RCTHandlerToken reloadToken; +static RCTHandlerToken devMenuToken; static std::atomic numInitializedModules{0}; #endif @@ -195,6 +196,14 @@ - (void)initialize } queue:dispatch_get_main_queue() forMethod:@"reload"]; +#if RCT_DEV_MENU + devMenuToken = [[RCTPackagerConnection sharedPackagerConnection] + addNotificationHandler:^(id params) { + [self.bridge.devMenu show]; + } + queue:dispatch_get_main_queue() + forMethod:@"devMenu"]; +#endif } #endif @@ -246,6 +255,9 @@ - (void)invalidate if (--numInitializedModules == 0) { [[RCTPackagerConnection sharedPackagerConnection] removeHandler:reloadToken]; +#if RCT_DEV_MENU + [[RCTPackagerConnection sharedPackagerConnection] removeHandler:devMenuToken]; +#endif } #endif } From e45e718dd644a3cccf3d60ed46fe6ea4f9cbf9a8 Mon Sep 17 00:00:00 2001 From: Lorenzo Sciandra Date: Tue, 14 Feb 2023 06:51:38 -0800 Subject: [PATCH 06/81] add 0.71.3 changelog (#36149) Summary: Adds changelog for new patch. ## Changelog [Internal] [Changed] - add changelog entry for 0.71.3 Pull Request resolved: https://github.com/facebook/react-native/pull/36149 Test Plan: N/A Reviewed By: dmytrorykun Differential Revision: D43272716 Pulled By: cipolleschi fbshipit-source-id: 58ca3f598aa6a23092902ab6317b01d6915e74e9 --- CHANGELOG.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61e7b129eaa2c8..aa95813a9bfebc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## v0.71.3 + +### Changed + +- Bump package versions ([4b84888a90](https://github.com/facebook/react-native/commit/4b84888a90c9436a8a62cc8507176f1b946b9b93) by [@cipolleschi](https://github.com/cipolleschi)), ([60f0a71060](https://github.com/facebook/react-native/commit/60f0a71060078759b526f65926763274811977f9) by [@cipolleschi](https://github.com/cipolleschi)), ([a3f205a27b](https://github.com/facebook/react-native/commit/a3f205a27b75d4e76354dbcb3203653e1f93f3ee) by [@cipolleschi](https://github.com/cipolleschi)): + - `react-native-codegen` to `0.71.5` + - `react-native-gradle-plugin` to `0.71.15` + +### Fixed + +- (codegen) Add missing C++ include for prop conversion of complex array type ([92fc32aa](https://github.com/facebook/react-native/commit/92fc32aa053ac8401ad8c9f55dcfa1e48ae8fc1d) by [@rshest](https://github.com/rshest)) + +#### Android specific + +- Fixed jscexecutor crash on Android which is caused from NDK incompatibility ([a232decbb1](https://github.com/facebook/react-native/commit/a232decbb1252ade0247a352f887ca4d97ee273c) by [@Kudo](https://github.com/Kudo)) +- Used relative paths for gradle commands ([bb02ccf13f](https://github.com/facebook/react-native/commit/bb02ccf13f76f46b8572e2a85d578fd8d4fd9467) by [@shivenmian](https://github.com/shivenmian)) + +#### iOS specific + +- fix `pod install --project-directory=...` ([ad1ddc241a](https://github.com/facebook/react-native/commit/ad1ddc241af723a3f5da2058709f9684e51fb5ce) by [@tido64](https://github.com/tido64)) + ## v0.71.2 ### Added From 0d82b402aa546aa773e91921989fb8389aee81dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Umut=20Topuzo=C4=9Flu?= Date: Tue, 14 Feb 2023 07:05:03 -0800 Subject: [PATCH 07/81] Fix missing node error message not printed correctly (#36140) Summary: When the node version could not be found there is an error message shown to help what can be done to fix this issue (for example in the error logs in xcode) The problem was that the backtick symbol is interpreted as running commands in terminals so the parts that were in backticks were run and the error message was printed incompletely. Also there were other errors added (.xcode.env command not found, for example) which makes it harder to understand what is going on. In bash / zsh single quotes does not expand commands and variables unlike double quotes which does this. ## Changelog [IOS] [FIXED] - Fix missing node error message not printed correctly when deprecated `find-node-for-xcode.sh` is used. Pull Request resolved: https://github.com/facebook/react-native/pull/36140 Test Plan: I just ran the xcode build again after updating it manually in the node_modules folder. The log output changed from this ``` [Warning] You need to configure your node path in the environment. You can set it up quickly by running: echo 'export NODE_BINARY=/Users/uloco/Library/Caches/fnm_multishells/78434_1676301546457/bin/node' > .xcode.env in the ios folder. This is needed by React Native to work correctly. We fallback to the DEPRECATED behavior of finding . This will be REMOVED in a future version. You can read more about this here: https://reactnative.dev/docs/environment-setup#optional-configuring-your-environment ``` to this ``` [Warning] You need to configure your node path in the `".xcode.env" file` environment. You can set it up quickly by running: `echo export NODE_BINARY=$(command -v node) > .xcode.env` in the ios folder. This is needed by React Native to work correctly. We fallback to the DEPRECATED behavior of finding `node`. This will be REMOVED in a future version. You can read more about this here: https://reactnative.dev/docs/environment-setup#optional-configuring-your-environment ``` Reviewed By: cortinico, cipolleschi Differential Revision: D43258623 Pulled By: rshest fbshipit-source-id: 7db0d983b204e59504666686be78311c4c2fb993 --- scripts/xcode/with-environment.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/xcode/with-environment.sh b/scripts/xcode/with-environment.sh index e4a8e42436e7bf..f36190e6b146db 100755 --- a/scripts/xcode/with-environment.sh +++ b/scripts/xcode/with-environment.sh @@ -32,12 +32,12 @@ fi if [ -n "$NODE_BINARY" ]; then echo "Node found at: ${NODE_BINARY}" else - echo "[Warning] You need to configure your node path in the `'.xcode.env' file` environment. " \ - "You can set it up quickly by running: " \ - "echo 'export NODE_BINARY=$(command -v node)' > .xcode.env " \ - "in the ios folder. This is needed by React Native to work correctly. " \ - "We fallback to the DEPRECATED behavior of finding `node`. This will be REMOVED in a future version. " \ - "You can read more about this here: https://reactnative.dev/docs/environment-setup#optional-configuring-your-environment" >&2 + echo '[Warning] You need to configure your node path in the `".xcode.env" file` environment. ' \ + 'You can set it up quickly by running: ' \ + '`echo export NODE_BINARY=$(command -v node) > .xcode.env` ' \ + 'in the ios folder. This is needed by React Native to work correctly. ' \ + 'We fallback to the DEPRECATED behavior of finding `node`. This will be REMOVED in a future version. ' \ + 'You can read more about this here: https://reactnative.dev/docs/environment-setup#optional-configuring-your-environment' >&2 source "${REACT_NATIVE_PATH}/scripts/find-node-for-xcode.sh" fi From 28d8f25c7670d72fcac4f75dde6dd0bc9292cc03 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Tue, 14 Feb 2023 07:06:53 -0800 Subject: [PATCH 08/81] fix: update executor for packages publishing workflow (#36146) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36146 Changelog: [Internal] - While working on 0.71.3, it was discovered that `react-native-codegen` package is being published almost empty (without `lib` folder) - The reason for it is that `prepare` script is not being executed - The main reason for it is npm v6, which requires adding `unsafe-perm` flag for it: https://www.vinayraghu.com/blog/npm-unsafe-perm - Instead of using this flag, changing executor to `nodelts`, which has node v18 and npm v8 - Also adding `run_yarn` before running the script, because `react-native/codegen` uses external dependencies (such as rimraf) for its build scripts Reviewed By: cipolleschi Differential Revision: D43248175 fbshipit-source-id: d12b93decbf408713e309fe8be75d8d5ec994868 --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 950fe6144328d3..d180a22cc62d82 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1537,9 +1537,10 @@ jobs: echo "Nightly build run" find_and_publish_bumped_packages: - executor: reactnativeandroid + executor: nodelts steps: - checkout + - run_yarn - run: name: Set NPM auth token command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc From 9a885db962d07aea5bf2497ff0599f5e2bbb14f4 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 14 Feb 2023 09:42:43 -0800 Subject: [PATCH 09/81] Remove config null check Summary: This removes the null-check on Yoga config added (we think we root-caused the issue), and adds an assertion to the public API accepting a config that it is non-null. There are more changes to config setting that will come later. Changelog: [Internal] Reviewed By: javache Differential Revision: D43273456 fbshipit-source-id: cba498352d114a3fa2694f3a144f5f01a83d3190 --- ReactCommon/yoga/yoga/Yoga.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index bdbf51022dd100..d71257307cfc9e 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -189,6 +189,7 @@ int32_t gConfigInstanceCount = 0; YOGA_EXPORT WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) { const YGNodeRef node = new YGNode{config}; + YGAssert(config != nullptr, "Tried to construct YGNode with null config"); YGAssertWithConfig( config, node != nullptr, "Could not allocate memory for node"); Event::publish(node, {config}); @@ -4301,14 +4302,6 @@ YOGA_EXPORT void YGConfigSetExperimentalFeatureEnabled( YOGA_EXPORT bool YGConfigIsExperimentalFeatureEnabled( const YGConfigRef config, const YGExperimentalFeature feature) { - // S323291 + T145030974 + T145292944: Node config should never be null, but - // Yoga has a private API used by RN to set config which does not check, and - // we crash here where config is null. Add a null check as temporary - // remediation - if (config == nullptr) { - return false; - } - return config->experimentalFeatures[feature]; } From 7b14180302747c49123b8dbdcfc8382b43aee3ba Mon Sep 17 00:00:00 2001 From: Vojtech Novak Date: Tue, 14 Feb 2023 10:12:34 -0800 Subject: [PATCH 10/81] fix: remove unavailable EventEmitter TS export (#36109) Summary: currently, using TS, this is a valid import: `import { EventEmitter } from 'react-native';` However, looking at the [index file](https://github.com/facebook/react-native/blob/main/index.js) we can see that there is no such export. I first thought I'd add the EventEmitter export in order to get the `index.js` in line with the types, but it appears that the Event Emitter will become a separate package at some point https://github.com/facebook/react-native/pull/34401 so removing it from the types seems to be better for future. ## Changelog fix: remove unavailable EventEmitter TS export Pick one each for the category and type tags: [INTERNAL] [CHANGED] - remove unavailable EventEmitter TS export For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: https://github.com/facebook/react-native/pull/36109 Test Plan: tested locally: using `import { EventEmitter } from 'react-native';` correctly gives `TS2305: Module '"react-native"' has no exported member 'EventEmitter'.` Reviewed By: javache, cortinico Differential Revision: D43155568 Pulled By: NickGerleman fbshipit-source-id: b9e8c3f4be9812637c8588d14a9ce4edf188ed36 --- types/index.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 349efc65a9fc8c..268383e915a0fb 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -147,7 +147,6 @@ export * from '../Libraries/Utilities/Platform'; export * from '../Libraries/Vibration/Vibration'; export * from '../Libraries/YellowBox/YellowBoxDeprecated'; export * from '../Libraries/vendor/core/ErrorUtils'; -export * from '../Libraries/vendor/emitter/EventEmitter'; export * from './public/DeprecatedPropertiesAlias'; export * from './public/Insets'; From 611f9c615ebad7d53c1eb1274fe82e36d915165e Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Tue, 14 Feb 2023 13:41:32 -0800 Subject: [PATCH 11/81] Create util class for parsing JSONObject and JSONArray to ReadableMap and ReadableArray Summary: This diff pays the duty in T126215968 where we should move the util methods to a shareable place. ~~I cannot find a good util namespace so I created on under `com.facebook.react.panelapp`.~~ This lives under `com.facebook.react.bridge` next to the `Arguments` class. - Create ~~`ReadableDataParser.java`~~ `JSONArguments.java` - Reuse in multiple places within `react-panellib` Changelog: [Internal] - Code refactor on JSON and ReadableMap conversion Reviewed By: javache Differential Revision: D42978852 fbshipit-source-id: e00a5c4cefcf6114d9a5d947cb00e3ff7f0dccaa --- .../facebook/react/bridge/JSONArguments.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java new file mode 100644 index 00000000000000..7fb9cc131a5e7c --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java @@ -0,0 +1,106 @@ +/* + * 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.bridge; + +import java.util.Iterator; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +public class JSONArguments { + /** + * Parse JSONObject to ReadableMap + * + * @param obj The JSONObject to be parsed + * @return readableMap from the JSONObject + */ + public static ReadableMap fromJSONObject(JSONObject obj) throws JSONException { + WritableMap result = Arguments.createMap(); + Iterator keys = obj.keys(); + + while (keys.hasNext()) { + String key = keys.next(); + Object val = obj.get(key); + if (val instanceof JSONObject) { + result.putMap(key, fromJSONObject((JSONObject) val)); + } else if (val instanceof JSONArray) { + result.putArray(key, fromJSONArray((JSONArray) val)); + } else if (val instanceof String) { + result.putString(key, (String) val); + } else if (val instanceof Boolean) { + result.putBoolean(key, (Boolean) val); + } else if (val instanceof Integer) { + result.putInt(key, (Integer) val); + } else if (val instanceof Double) { + result.putDouble(key, (Double) val); + } else if (obj.isNull(key)) { + result.putNull(key); + } else { + // Unknown value type. Will throw + throw new JSONException("Unexpected value when parsing JSON object. key: " + key); + } + } + + return result; + } + + /** + * Parse String of JSON object to ReadableMap + * + * @param objStr The String JSON object to be parsed + * @return readableMap from the JSONArray + */ + public static ReadableMap fromJSONObjectString(String objStr) throws JSONException { + return fromJSONObject(new JSONObject(objStr)); + } + + /** + * Parse JSONArray to ReadableArray + * + * @param arr The JSONArray to be parsed + * @return readableArray from the JSONArray + */ + public static ReadableArray fromJSONArray(JSONArray arr) throws JSONException { + WritableArray result = Arguments.createArray(); + + for (int i = 0; i < arr.length(); i++) { + Object val = arr.get(i); + + if (val instanceof JSONObject) { + result.pushMap(fromJSONObject((JSONObject) val)); + } else if (val instanceof JSONArray) { + result.pushArray(fromJSONArray((JSONArray) val)); + } else if (val instanceof String) { + result.pushString((String) val); + } else if (val instanceof Boolean) { + result.pushBoolean((Boolean) val); + } else if (val instanceof Integer) { + result.pushInt((Integer) val); + } else if (val instanceof Double) { + result.pushDouble((Double) val); + } else if (arr.isNull(i)) { + result.pushNull(); + } else { + // Unknown value type. Will throw + throw new JSONException("Unexpected value when parsing JSON array. index: " + i); + } + } + + return result; + } + + /** + * Parse String of JSON array to ReadableArray + * + * @param arrStr The String JSON array to be parsed + * @return readableArray from the JSONArray + */ + public static ReadableArray fromJSONArrayString(String arrStr) throws JSONException { + return fromJSONArray(new JSONArray(arrStr)); + } +} From 11570e71a2747602ff485552094b413375b19a96 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Tue, 14 Feb 2023 14:31:52 -0800 Subject: [PATCH 12/81] Deprecate LazyReactPackage.getReactModuleInfoProviderViaReflection Summary: There are two different ways of getting the ReactModuleInfoProvider from LazyReactPackage: 1. static LazyReactPackage.getReactModuleInfoProviderViaReflection(LazyReactPackage) 2. LazyReactPackage.getReactModuleInfoProvider() The first way calls into codegen that only works within Meta's infra. This code-path is *now* dead. Therefore, this diff deprecates the first path, to make LazyReactPackage less confusing. This diff simplifies the implementation to return an empty ReactModuleInfoProvider for the v0.72 cut. In the v0.73 cut, we'll just outright delete this method. Changelog: [Android][Changed] - Deprecate LazyReactPackage.getReactModuleInfoProviderViaReflection() Reviewed By: sshic Differential Revision: D43066800 fbshipit-source-id: 2145c3265ff2bd24e6828b193577ba1f500bce49 --- .../com/facebook/react/LazyReactPackage.java | 42 ++++--------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/LazyReactPackage.java b/ReactAndroid/src/main/java/com/facebook/react/LazyReactPackage.java index 34bbe1c198be0f..9ec077bc04d73d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/LazyReactPackage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/LazyReactPackage.java @@ -33,44 +33,16 @@ */ public abstract class LazyReactPackage implements ReactPackage { + @Deprecated public static ReactModuleInfoProvider getReactModuleInfoProviderViaReflection( LazyReactPackage lazyReactPackage) { - Class reactModuleInfoProviderClass; - try { - reactModuleInfoProviderClass = - Class.forName( - lazyReactPackage.getClass().getCanonicalName() + "$$ReactModuleInfoProvider"); - } catch (ClassNotFoundException e) { - // In OSS case, when the annotation processor does not run, we fall back to non-lazy mode - // For this, we simply return an empty moduleMap. - // NativeModuleRegistryBuilder will eagerly get all the modules, and get the info from the - // modules directly - return new ReactModuleInfoProvider() { - @Override - public Map getReactModuleInfos() { - return Collections.emptyMap(); - } - }; - } - - if (reactModuleInfoProviderClass == null) { - throw new RuntimeException( - "ReactModuleInfoProvider class for " - + lazyReactPackage.getClass().getCanonicalName() - + " not found."); - } - - try { - return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance(); - } catch (InstantiationException e) { - throw new RuntimeException( - "Unable to instantiate ReactModuleInfoProvider for " + lazyReactPackage.getClass(), e); - } catch (IllegalAccessException e) { - throw new RuntimeException( - "Unable to instantiate ReactModuleInfoProvider for " + lazyReactPackage.getClass(), e); - } + return new ReactModuleInfoProvider() { + @Override + public Map getReactModuleInfos() { + return Collections.emptyMap(); + } + }; } - /** * We return an iterable * From 89ef5bd6f9064298dfe55b0b18be4a770ee0872c Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Tue, 14 Feb 2023 22:32:55 -0800 Subject: [PATCH 13/81] Add TraceUpdateOverlay to RN AppContainer Summary: This diff adds `TraceUpdateOverlay` native component to RN `AppContainer.js`. This will enable the overlay when the build is in DEV environment and the DevTools global hook exists. It also closed gap between the JS dev mode and native dev support flag, so that the native component will be available when used by JS. ## Update (2/13/2023) Instead of the original approach where I put a default value to the devsupport manager flag, I did ui manager check from JS and make sure the native component exists before using it. This is cleaner. ## Problem Since the `AppContainer` is being used by all RN apps, we need to make sure the native component is registered in UI Manager of the RN app when it's used. Currently, the native component lives in the `DebugCorePackage.java`, which is added to the RN app [when the `DevSupportManager` is used](https://fburl.com/code/muqmqbsa). However, there's no way to tell if an app is using dev support manager in JS, hence there are gaps when the JS code uses `TraceUpdateOverlay`, vs when the native code registered the native component. This issue caused test error in [ReactNativePerfTest](https://fburl.com/testinfra/j24wzh46) from the [previous diff](https://fburl.com/diff/bv9ckhm7), and it actually prevents Flipper from running this properly as shown in this video: https://pxl.cl/2sqKf The errors shown in Flipper indicates the RN surface from the plugin is also missing `TraceUpdateOverlay` in its UI Manager: {F869168865} ## Solution To fix this issue, we should find a way to expose if the app is using dev support manager in JS. Or we should set to use DevSupportManager whenever it's a dev build as claimed in JS. I will try to find some way to achieve either one of this. I am open to suggestions here for where I should add the native component to. Given that it's used in the AppContainer, and any app could be built in development mode, I don't want to make people to manually add this native component themselves. ## Alternatives There are some other approaches that could mitigate the issue, but less ideal: For the test issue 1) Add `setUseDeveloperSupport(true)` to [ReactNativeTestRule.java](https://fburl.com/code/7jaoamdp). That will make the related test pass by using the DevSupportPackages, which has the native component. However, it only fixes tests using that class. 2) Override the package for [ReactNativeTestRule.java](https://fburl.com/code/b4em32fa), or `addPackage` with more packages including the native component. Again this only fixes this test. 3) Add the native component to the [`MainReactPackage`](https://fburl.com/code/nlayho86), which is what I did here in this diff. This would fix more cases as this package is [recommended to be used](https://fburl.com/code/53eweuoh) for all RN app. However, it may not fix all the cases if the RN app didn't manually use it. 4) Add the native component in the [`CoreModulesPackage`](https://fburl.com/code/lfeklztl), which will make all RN apps work, but at the cost of increase package size when this feature is not needed. Or, we could argue that we want to have highlights on trace updates for production build as well? Changelog: [Internal] - Enable TraceUpdateOverlay to RN AppContainer Reviewed By: rubennorte Differential Revision: D43180893 fbshipit-source-id: a1530cc6e2a9d8c905bdfe5d622d85c4712266f8 --- .../TraceUpdateOverlay/TraceUpdateOverlay.js | 10 +++++++++- Libraries/ReactNative/AppContainer.js | 8 +++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js index 6e5914fd25b26f..e0318fac9c4a15 100644 --- a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js +++ b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -10,6 +10,7 @@ import type {Overlay} from './TraceUpdateOverlayNativeComponent'; +import UIManager from '../../ReactNative/UIManager'; import processColor from '../../StyleSheet/processColor'; import StyleSheet from '../../StyleSheet/StyleSheet'; import View from '../View/View'; @@ -53,6 +54,8 @@ type ReactDevToolsGlobalHook = { const {useEffect, useRef, useState} = React; const hook: ReactDevToolsGlobalHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; +const isNativeComponentReady = + UIManager.hasViewManagerConfig('TraceUpdateOverlay'); let devToolsAgent: ?Agent; export default function TraceUpdateOverlay(): React.Node { @@ -60,6 +63,10 @@ export default function TraceUpdateOverlay(): React.Node { // This effect is designed to be explictly shown here to avoid re-subscribe from the same // overlay component. useEffect(() => { + if (!isNativeComponentReady) { + return; + } + function attachToDevtools(agent: Agent) { devToolsAgent = agent; agent.addListener('drawTraceUpdates', onAgentDrawTraceUpdates); @@ -141,7 +148,8 @@ export default function TraceUpdateOverlay(): React.Node { useRef>(null); return ( - !overlayDisabled && ( + !overlayDisabled && + isNativeComponentReady && ( { state: State = { inspector: null, devtoolsOverlay: null, + traceUpdateOverlay: null, mainKey: 1, hasError: false, }; @@ -75,7 +77,10 @@ class AppContainer extends React.Component { const devtoolsOverlay = ( ); - this.setState({devtoolsOverlay}); + const TraceUpdateOverlay = + require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default; + const traceUpdateOverlay = ; + this.setState({devtoolsOverlay, traceUpdateOverlay}); } } } @@ -127,6 +132,7 @@ class AppContainer extends React.Component { {!this.state.hasError && innerView} + {this.state.traceUpdateOverlay} {this.state.devtoolsOverlay} {this.state.inspector} {logBox} From b5e4fea86ef9df1ed0edb438f918dfc8330f649c Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 15 Feb 2023 04:17:06 -0800 Subject: [PATCH 14/81] Move graphics' platform/ios files to graphics/platform/ios/react/renderer/graphics folder structure Summary: To Properly setup the Header Search Paths for `use_frameworks!`, we need to move the files that are in the `react/renderer/graphics/platform/ios` folder into the `react/renderer/graphics/platform/ios/react/renderer/graphics` folder. This mimic the same folder structure we have also in `cxx` and `android` ## Changelog: [iOS][Changed] - Moved the files from `.../platform/ios` to `.../platform/ios/react/renderer/graphics` Reviewed By: sshic Differential Revision: D43082032 fbshipit-source-id: 519d2e12eb7edd50b5f71bac5b1c618c6bf89919 --- ReactCommon/react/renderer/graphics/BUCK | 4 +++- .../platform/ios/{ => react/renderer/graphics}/Float.h | 0 .../ios/{ => react/renderer/graphics}/PlatformColorParser.h | 0 .../ios/{ => react/renderer/graphics}/RCTPlatformColorUtils.h | 0 .../{ => react/renderer/graphics}/RCTPlatformColorUtils.mm | 0 5 files changed, 3 insertions(+), 1 deletion(-) rename ReactCommon/react/renderer/graphics/platform/ios/{ => react/renderer/graphics}/Float.h (100%) rename ReactCommon/react/renderer/graphics/platform/ios/{ => react/renderer/graphics}/PlatformColorParser.h (100%) rename ReactCommon/react/renderer/graphics/platform/ios/{ => react/renderer/graphics}/RCTPlatformColorUtils.h (100%) rename ReactCommon/react/renderer/graphics/platform/ios/{ => react/renderer/graphics}/RCTPlatformColorUtils.mm (100%) diff --git a/ReactCommon/react/renderer/graphics/BUCK b/ReactCommon/react/renderer/graphics/BUCK index c41482d5a464e1..5c103d48d3fe82 100644 --- a/ReactCommon/react/renderer/graphics/BUCK +++ b/ReactCommon/react/renderer/graphics/BUCK @@ -14,6 +14,8 @@ load( "subdir_glob", ) +oncall("react_native") + APPLE_COMPILER_FLAGS = get_apple_compiler_flags() rn_xplat_cxx_library( @@ -67,7 +69,7 @@ rn_xplat_cxx_library( fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_exported_headers = subdir_glob( [ - ("platform/ios", "*.h"), + ("platform/ios/react/renderer/graphics", "*.h"), ], prefix = "react/renderer/graphics", ), diff --git a/ReactCommon/react/renderer/graphics/platform/ios/Float.h b/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/Float.h similarity index 100% rename from ReactCommon/react/renderer/graphics/platform/ios/Float.h rename to ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/Float.h diff --git a/ReactCommon/react/renderer/graphics/platform/ios/PlatformColorParser.h b/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.h similarity index 100% rename from ReactCommon/react/renderer/graphics/platform/ios/PlatformColorParser.h rename to ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/PlatformColorParser.h diff --git a/ReactCommon/react/renderer/graphics/platform/ios/RCTPlatformColorUtils.h b/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.h similarity index 100% rename from ReactCommon/react/renderer/graphics/platform/ios/RCTPlatformColorUtils.h rename to ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.h diff --git a/ReactCommon/react/renderer/graphics/platform/ios/RCTPlatformColorUtils.mm b/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm similarity index 100% rename from ReactCommon/react/renderer/graphics/platform/ios/RCTPlatformColorUtils.mm rename to ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/RCTPlatformColorUtils.mm From d1e500c3b19182897ccfb8abfe87e3f32dcacd3e Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 15 Feb 2023 04:17:06 -0800 Subject: [PATCH 15/81] Move ReactCommon's `.../nativemodule/xxx/platform/ios` files to `.../nativemodule/xxx/platform/ios/ReactCommon` Summary: To properly setup the Header Search Paths for `use_frameworks!`, we need to move the files that are in the `.../nativemodule/xxx/platform/ios` folder into the `.../nativemodule/xxx/platform/ios/ReactCommon` folder. We have two folders to migrate: `core` and `sample`. As a cleanup, `sample` should be extracted from the codebase and moved to RNTester or a library as it can be used as an example to add more examples in the codebase that we ship to our users. This mimic the same folder structure we have also in `cxx` and `android` ## Changelog [iOS][Changed] Moved the files from `.../nativemodule/xxx/platform/ios` to `.../nativemodule/xxx/platform/ios/ReactCommon` Reviewed By: cortinico Differential Revision: D43082851 fbshipit-source-id: 414426274d9a5ab20cc0e76cdada0c2977264b5f --- ReactCommon/react/nativemodule/core/BUCK | 4 +++- .../core/platform/ios/{ => ReactCommon}/RCTBlockGuard.h | 0 .../core/platform/ios/{ => ReactCommon}/RCTBlockGuard.mm | 0 .../core/platform/ios/{ => ReactCommon}/RCTTurboModule.h | 0 .../core/platform/ios/{ => ReactCommon}/RCTTurboModule.mm | 0 .../platform/ios/{ => ReactCommon}/RCTTurboModuleManager.h | 0 .../platform/ios/{ => ReactCommon}/RCTTurboModuleManager.mm | 0 ReactCommon/react/nativemodule/samples/BUCK | 4 +++- .../ios/{ => ReactCommon}/RCTNativeSampleTurboModuleSpec.h | 0 .../ios/{ => ReactCommon}/RCTNativeSampleTurboModuleSpec.mm | 0 .../platform/ios/{ => ReactCommon}/RCTSampleTurboCxxModule.h | 0 .../platform/ios/{ => ReactCommon}/RCTSampleTurboCxxModule.mm | 0 .../platform/ios/{ => ReactCommon}/RCTSampleTurboModule.h | 0 .../platform/ios/{ => ReactCommon}/RCTSampleTurboModule.mm | 0 .../ios/{ => ReactCommon}/SampleTurboCxxModuleLegacyImpl.cpp | 0 .../ios/{ => ReactCommon}/SampleTurboCxxModuleLegacyImpl.h | 0 16 files changed, 6 insertions(+), 2 deletions(-) rename ReactCommon/react/nativemodule/core/platform/ios/{ => ReactCommon}/RCTBlockGuard.h (100%) rename ReactCommon/react/nativemodule/core/platform/ios/{ => ReactCommon}/RCTBlockGuard.mm (100%) rename ReactCommon/react/nativemodule/core/platform/ios/{ => ReactCommon}/RCTTurboModule.h (100%) rename ReactCommon/react/nativemodule/core/platform/ios/{ => ReactCommon}/RCTTurboModule.mm (100%) rename ReactCommon/react/nativemodule/core/platform/ios/{ => ReactCommon}/RCTTurboModuleManager.h (100%) rename ReactCommon/react/nativemodule/core/platform/ios/{ => ReactCommon}/RCTTurboModuleManager.mm (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/RCTNativeSampleTurboModuleSpec.h (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/RCTNativeSampleTurboModuleSpec.mm (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/RCTSampleTurboCxxModule.h (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/RCTSampleTurboCxxModule.mm (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/RCTSampleTurboModule.h (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/RCTSampleTurboModule.mm (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/SampleTurboCxxModuleLegacyImpl.cpp (100%) rename ReactCommon/react/nativemodule/samples/platform/ios/{ => ReactCommon}/SampleTurboCxxModuleLegacyImpl.h (100%) diff --git a/ReactCommon/react/nativemodule/core/BUCK b/ReactCommon/react/nativemodule/core/BUCK index 9de875edcb6542..143dcb6183e395 100644 --- a/ReactCommon/react/nativemodule/core/BUCK +++ b/ReactCommon/react/nativemodule/core/BUCK @@ -1,5 +1,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "CXX", "FBJNI_TARGET", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags", "react_native_target", "react_native_xplat_shared_library_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob") +oncall("react_native") + rn_xplat_cxx_library( name = "core", srcs = glob( @@ -43,7 +45,7 @@ rn_xplat_cxx_library( ], ios_exported_headers = subdir_glob( [ - ("platform/ios", "*.h"), + ("platform/ios/ReactCommon", "*.h"), ], prefix = "ReactCommon", ), diff --git a/ReactCommon/react/nativemodule/core/platform/ios/RCTBlockGuard.h b/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.h similarity index 100% rename from ReactCommon/react/nativemodule/core/platform/ios/RCTBlockGuard.h rename to ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.h diff --git a/ReactCommon/react/nativemodule/core/platform/ios/RCTBlockGuard.mm b/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.mm similarity index 100% rename from ReactCommon/react/nativemodule/core/platform/ios/RCTBlockGuard.mm rename to ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTBlockGuard.mm diff --git a/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.h b/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h similarity index 100% rename from ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.h rename to ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h diff --git a/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm b/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm similarity index 100% rename from ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModule.mm rename to ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm diff --git a/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.h b/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h similarity index 100% rename from ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.h rename to ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h diff --git a/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm b/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm similarity index 100% rename from ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm rename to ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.mm diff --git a/ReactCommon/react/nativemodule/samples/BUCK b/ReactCommon/react/nativemodule/samples/BUCK index 2285cf02648ade..ea1153fa91c277 100644 --- a/ReactCommon/react/nativemodule/samples/BUCK +++ b/ReactCommon/react/nativemodule/samples/BUCK @@ -1,5 +1,7 @@ load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "FBJNI_TARGET", "get_objc_arc_preprocessor_flags", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags", "react_native_dep", "react_native_target", "react_native_xplat_target", "rn_android_library", "rn_xplat_cxx_library", "subdir_glob") +oncall("react_native") + rn_xplat_cxx_library( name = "samples", srcs = glob( @@ -44,7 +46,7 @@ rn_xplat_cxx_library( ], ios_exported_headers = subdir_glob( [ - ("platform/ios", "*.h"), + ("platform/ios/ReactCommon", "*.h"), ], prefix = "ReactCommon", ), diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.h diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTNativeSampleTurboModuleSpec.mm diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.h b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboCxxModule.h similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.h rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboCxxModule.h diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.mm b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboCxxModule.mm similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboCxxModule.mm rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboCxxModule.mm diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.h b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.h rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.h diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.mm b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/RCTSampleTurboModule.mm rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/SampleTurboCxxModuleLegacyImpl.cpp similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/SampleTurboCxxModuleLegacyImpl.cpp diff --git a/ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h b/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/SampleTurboCxxModuleLegacyImpl.h similarity index 100% rename from ReactCommon/react/nativemodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h rename to ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/SampleTurboCxxModuleLegacyImpl.h From 5588e0fe0b78bfcbc32b6880e9c985853aea5653 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 15 Feb 2023 04:17:06 -0800 Subject: [PATCH 16/81] Move files from `.../textinput/iostextinput` to `.../textinput/iostextinput/react/renderer/components/iostextinput` Summary: To properly setup the Header Search Paths for `use_frameworks!`, we need to move the files that are in the `.../textinput/iostextinput` folder into the `.../textinput/iostextinput/react/renderer/components/iostextinput` folder. This mimic the same folder structure we have also `android` ## Changelog [iOS][Changed] Moved the files from `.../textinput/iostextinput` to `.../textinput/iostextinput/react/renderer/components/iostextinput` Reviewed By: cortinico Differential Revision: D43084639 fbshipit-source-id: fe0f55d9f372bda0fbd59c6c567ac747ca308a69 --- .../react/renderer/components/textinput/iostextinput/BUCK | 3 +++ .../components/iostextinput}/TextInputComponentDescriptor.h | 0 .../components/iostextinput}/TextInputEventEmitter.cpp | 0 .../renderer/components/iostextinput}/TextInputEventEmitter.h | 0 .../renderer/components/iostextinput}/TextInputProps.cpp | 0 .../renderer/components/iostextinput}/TextInputProps.h | 0 .../renderer/components/iostextinput}/TextInputShadowNode.cpp | 0 .../renderer/components/iostextinput}/TextInputShadowNode.h | 0 .../renderer/components/iostextinput}/TextInputState.cpp | 0 .../renderer/components/iostextinput}/TextInputState.h | 0 .../{ => react/renderer/components/iostextinput}/conversions.h | 0 .../{ => react/renderer/components/iostextinput}/primitives.h | 0 .../renderer/components/iostextinput}/propsConversions.h | 0 13 files changed, 3 insertions(+) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputComponentDescriptor.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputEventEmitter.cpp (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputEventEmitter.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputProps.cpp (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputProps.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputShadowNode.cpp (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputShadowNode.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputState.cpp (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/TextInputState.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/conversions.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/primitives.h (100%) rename ReactCommon/react/renderer/components/textinput/iostextinput/{ => react/renderer/components/iostextinput}/propsConversions.h (100%) diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/BUCK b/ReactCommon/react/renderer/components/textinput/iostextinput/BUCK index 28b6cf40d8289b..7b60f0a67174bc 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/BUCK +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/BUCK @@ -12,6 +12,8 @@ load( "subdir_glob", ) +oncall("react_native") + APPLE_COMPILER_FLAGS = get_apple_compiler_flags() rn_xplat_cxx_library( @@ -28,6 +30,7 @@ rn_xplat_cxx_library( exported_headers = subdir_glob( [ ("", "*.h"), + ("react/renderer/components/iostextinput", "*.h"), ], # TODO(shergin) T26519801 Figure out better directories structure prefix = "react/renderer/components/iostextinput", diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputComponentDescriptor.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputComponentDescriptor.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputEventEmitter.cpp b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.cpp similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputEventEmitter.cpp rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.cpp diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputEventEmitter.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputEventEmitter.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputEventEmitter.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.cpp rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.cpp diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputProps.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputProps.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.cpp b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.cpp rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputShadowNode.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputState.cpp b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputState.cpp rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.cpp diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputState.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/TextInputState.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputState.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/conversions.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/conversions.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/conversions.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/conversions.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/primitives.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/primitives.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/primitives.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/primitives.h diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/propsConversions.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h similarity index 100% rename from ReactCommon/react/renderer/components/textinput/iostextinput/propsConversions.h rename to ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h From 931a4c5e239a006ecc81becf3252d23d44c969ef Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 15 Feb 2023 04:17:06 -0800 Subject: [PATCH 17/81] Move files from `.../imagemanager/platform/ios` to `.../imagemanager/platform/ios/react/renderer/imagemanager` Summary: To properly setup the Header Search Paths for `use_frameworks!`, we need to move the files that are in the `.../imagemanager/platform/ios` folder into the `.../imagemanager/platform/ios/react/renderer/imagemanager` folder. This mimic the same folder structure we have also `android` ## Changelog [iOS][Changed] Moved the files from `.../imagemanager/platform/ios` to `.../imagemanager/platform/ios/react/renderer/imagemanager` Reviewed By: cortinico Differential Revision: D43088421 fbshipit-source-id: c3b86a95e67cc1ab9531997bb1bfbf011b7f730f --- ReactCommon/react/renderer/imagemanager/BUCK | 6 ++++-- .../ios/{ => react/renderer/imagemanager}/ImageManager.mm | 0 .../ios/{ => react/renderer/imagemanager}/ImageRequest.cpp | 0 .../ios/{ => react/renderer/imagemanager}/RCTImageManager.h | 0 .../{ => react/renderer/imagemanager}/RCTImageManager.mm | 0 .../renderer/imagemanager}/RCTImageManagerProtocol.h | 0 .../renderer/imagemanager}/RCTImagePrimitivesConversions.h | 0 .../{ => react/renderer/imagemanager}/RCTSyncImageManager.h | 0 .../renderer/imagemanager}/RCTSyncImageManager.mm | 0 9 files changed, 4 insertions(+), 2 deletions(-) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/ImageManager.mm (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/ImageRequest.cpp (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/RCTImageManager.h (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/RCTImageManager.mm (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/RCTImageManagerProtocol.h (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/RCTImagePrimitivesConversions.h (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/RCTSyncImageManager.h (100%) rename ReactCommon/react/renderer/imagemanager/platform/ios/{ => react/renderer/imagemanager}/RCTSyncImageManager.mm (100%) diff --git a/ReactCommon/react/renderer/imagemanager/BUCK b/ReactCommon/react/renderer/imagemanager/BUCK index fa5c067f08d556..2bb98e086b2d29 100644 --- a/ReactCommon/react/renderer/imagemanager/BUCK +++ b/ReactCommon/react/renderer/imagemanager/BUCK @@ -13,6 +13,8 @@ load( "subdir_glob", ) +oncall("react_native") + APPLE_COMPILER_FLAGS = get_apple_compiler_flags() rn_xplat_cxx_library( @@ -49,7 +51,7 @@ rn_xplat_cxx_library( ios_exported_headers = subdir_glob( [ ("", "*.h"), - ("platform/ios", "RCTImagePrimitivesConversions.h"), + ("platform/ios/react/renderer/imagemanager", "RCTImagePrimitivesConversions.h"), ], prefix = "react/renderer/imagemanager", ), @@ -61,7 +63,7 @@ rn_xplat_cxx_library( ios_headers = subdir_glob( [ ("", "*.h"), - ("platform/ios", "**/*.h"), + ("platform/ios/react/renderer/imagemanager", "**/*.h"), ], prefix = "", ), diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/ImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageManager.mm similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/ImageManager.mm rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageManager.mm diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/ImageRequest.cpp rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.h b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.h similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.h rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.h diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.mm similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManager.mm rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.mm diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManagerProtocol.h b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManagerProtocol.h similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/RCTImageManagerProtocol.h rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManagerProtocol.h diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTImagePrimitivesConversions.h b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImagePrimitivesConversions.h similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/RCTImagePrimitivesConversions.h rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImagePrimitivesConversions.h diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.h b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.h rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.mm similarity index 100% rename from ReactCommon/react/renderer/imagemanager/platform/ios/RCTSyncImageManager.mm rename to ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.mm From 0e09d6f8a665357f0dc642067eceb8f51ae24b76 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 15 Feb 2023 04:17:06 -0800 Subject: [PATCH 18/81] Move files from `.../textlayoutmanager/platform/ios` to `.../textlayoutmanager/platform/ios/react/renderer/textlayoutmanager` (#36158) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36158 To properly setup the Header Search Paths for `use_frameworks!`, we need to move the files that are in the `.../textlayoutmanager/platform/ios` folder into the `.../textlayoutmanager/platform/ios/react/renderer/textlayoutmanager` folder. This mimic the same folder structure we have also `android` ## Changelog [iOS][Changed] Moved the files from `.../textlayoutmanager/platform/ios` to `.../textlayoutmanager/platform/ios/react/renderer/textlayoutmanager` Reviewed By: cortinico Differential Revision: D43088586 fbshipit-source-id: 9589fe62f36fbff2744fdfbf3475e95954424232 --- ReactCommon/react/renderer/textlayoutmanager/BUCK | 6 ++++-- .../renderer/textlayoutmanager}/NSTextStorage+FontScaling.h | 0 .../renderer/textlayoutmanager}/NSTextStorage+FontScaling.m | 0 .../renderer/textlayoutmanager}/RCTAttributedTextUtils.h | 0 .../renderer/textlayoutmanager}/RCTAttributedTextUtils.mm | 0 .../renderer/textlayoutmanager}/RCTFontProperties.h | 0 .../{ => react/renderer/textlayoutmanager}/RCTFontUtils.h | 0 .../{ => react/renderer/textlayoutmanager}/RCTFontUtils.mm | 0 .../renderer/textlayoutmanager}/RCTTextLayoutManager.h | 0 .../renderer/textlayoutmanager}/RCTTextLayoutManager.mm | 0 .../textlayoutmanager}/RCTTextPrimitivesConversions.h | 0 .../renderer/textlayoutmanager}/TextLayoutManager.h | 0 .../renderer/textlayoutmanager}/TextLayoutManager.mm | 0 13 files changed, 4 insertions(+), 2 deletions(-) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/NSTextStorage+FontScaling.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/NSTextStorage+FontScaling.m (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTAttributedTextUtils.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTAttributedTextUtils.mm (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTFontProperties.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTFontUtils.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTFontUtils.mm (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTTextLayoutManager.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTTextLayoutManager.mm (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/RCTTextPrimitivesConversions.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/TextLayoutManager.h (100%) rename ReactCommon/react/renderer/textlayoutmanager/platform/ios/{ => react/renderer/textlayoutmanager}/TextLayoutManager.mm (100%) diff --git a/ReactCommon/react/renderer/textlayoutmanager/BUCK b/ReactCommon/react/renderer/textlayoutmanager/BUCK index c4e3be0d401ac9..11657d056ca837 100644 --- a/ReactCommon/react/renderer/textlayoutmanager/BUCK +++ b/ReactCommon/react/renderer/textlayoutmanager/BUCK @@ -14,6 +14,8 @@ load( "subdir_glob", ) +oncall("react_native") + APPLE_COMPILER_FLAGS = get_apple_compiler_flags() rn_xplat_cxx_library( @@ -83,7 +85,7 @@ rn_xplat_cxx_library( ], ios_exported_headers = subdir_glob( [ - ("platform/ios", "*.h"), + ("platform/ios/react/renderer/textlayoutmanager", "*.h"), ], prefix = "react/renderer/textlayoutmanager", ), @@ -94,7 +96,7 @@ rn_xplat_cxx_library( ], ios_headers = subdir_glob( [ - ("platform/ios", "**/*.h"), + ("platform/ios/react/renderer/textlayoutmanager", "**/*.h"), ], prefix = "", ), diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/NSTextStorage+FontScaling.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/NSTextStorage+FontScaling.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.m b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/NSTextStorage+FontScaling.m similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/NSTextStorage+FontScaling.m rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/NSTextStorage+FontScaling.m diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTFontProperties.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontProperties.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTFontProperties.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontProperties.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTFontUtils.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTFontUtils.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTFontUtils.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTFontUtils.mm rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTTextPrimitivesConversions.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextPrimitivesConversions.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/TextLayoutManager.h b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/TextLayoutManager.h rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h diff --git a/ReactCommon/react/renderer/textlayoutmanager/platform/ios/TextLayoutManager.mm b/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm similarity index 100% rename from ReactCommon/react/renderer/textlayoutmanager/platform/ios/TextLayoutManager.mm rename to ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm From 13271d3c80debe475fc1c9b88226df3fc587d61a Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 15 Feb 2023 04:17:06 -0800 Subject: [PATCH 19/81] Align OfflineMirrors Summary: Align offline mirrors after changes allow-large-files ## Changelog [internal] - Align offline mirrors Reviewed By: cortinico Differential Revision: D43302165 fbshipit-source-id: d4903d03a54f938ca78d295b4d7c9bca213721cb --- packages/rn-tester/Podfile.lock | 58 +++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 2ecca1bcbdff4b..353aa4e5bdfd70 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -135,36 +135,44 @@ PODS: - ReactCommon/turbomodule/core - React-Core (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default (= 1000.0.0) - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/CoreModulesHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/Default (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/DevSupport (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default (= 1000.0.0) - React-Core/RCTWebSocket (= 1000.0.0) - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-jsinspector (= 1000.0.0) @@ -172,99 +180,121 @@ PODS: - Yoga - React-Core/RCTActionSheetHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTAnimationHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTBlobHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTImageHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTLinkingHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTNetworkHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTPushNotificationHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTSettingsHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTTextHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTVibrationHeaders (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) - Yoga - React-Core/RCTWebSocket (1000.0.0): - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Core/Default (= 1000.0.0) - React-cxxreact (= 1000.0.0) + - React-hermes - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - React-perflogger (= 1000.0.0) @@ -275,12 +305,14 @@ PODS: - React-Codegen (= 1000.0.0) - React-Core/CoreModulesHeaders (= 1000.0.0) - React-jsi (= 1000.0.0) + - React-RCTBlob - React-RCTImage (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) - React-cxxreact (1000.0.0): - boost (= 1.76.0) - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-callinvoker (= 1000.0.0) - React-jsi (= 1000.0.0) @@ -606,6 +638,7 @@ PODS: - RCT-Folly (= 2021.07.22.00) - RCT-Folly/Futures (= 2021.07.22.00) - React-cxxreact (= 1000.0.0) + - React-jsi - React-jsiexecutor (= 1000.0.0) - React-jsinspector (= 1000.0.0) - React-perflogger (= 1000.0.0) @@ -618,6 +651,7 @@ PODS: - React-jsiexecutor (1000.0.0): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-cxxreact (= 1000.0.0) - React-jsi (= 1000.0.0) @@ -642,6 +676,7 @@ PODS: - React-Core - ReactCommon/turbomodule/core - React-RCTBlob (1000.0.0): + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-Codegen (= 1000.0.0) - React-Core/RCTBlobHeaders (= 1000.0.0) @@ -707,6 +742,7 @@ PODS: - ReactCommon/turbomodule/bridging (1000.0.0): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-callinvoker (= 1000.0.0) - React-Core (= 1000.0.0) @@ -717,6 +753,7 @@ PODS: - ReactCommon/turbomodule/core (1000.0.0): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-callinvoker (= 1000.0.0) - React-Core (= 1000.0.0) @@ -727,6 +764,7 @@ PODS: - ReactCommon/turbomodule/samples (1000.0.0): - DoubleConversion - glog + - hermes-engine - RCT-Folly (= 2021.07.22.00) - React-callinvoker (= 1000.0.0) - React-Core (= 1000.0.0) @@ -929,7 +967,7 @@ SPEC CHECKSUMS: FlipperKit: b353b63cb4048a5747529412524407d6efa68336 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: 094454894cb46a8522d3f72e803e634f86536889 + hermes-engine: 44aadce06e4021379728f804a9503c4c5030c246 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 @@ -938,21 +976,21 @@ SPEC CHECKSUMS: React: 2fc6c4c656cccd6753016528ad41199c16fd558e React-callinvoker: a7d5e883a83bb9bd3985b08be832c5e76451d18f React-Codegen: 4f1e911c128928e425e11698ad7859dfd0f92e20 - React-Core: 719bec4b41c93b1affb1e2c3a43956ec482ecb9f - React-CoreModules: feaa45c54c58e1420981f6dd544c8b3d01200caa - React-cxxreact: 97903bdac0fb53409663fd312e2183ae1dd730e5 + React-Core: 279a6e5ee79e88faa99157169b560c49635973d7 + React-CoreModules: d3ee40954b381edc514301341e8b895febfc1848 + React-cxxreact: aff243750dad852080636e615d7ae5639381735b React-Fabric: 62b9929a7345f941d8833630f37d9440b2dda438 React-graphics: cb8a85648695c60f33a00d732b985f734d1470d8 - React-hermes: e35ea664b36773a2ce84c583febf1396080e59f7 + React-hermes: 7f0e87d44b1c7cfbdd11aa3c070d04435fe75d57 React-jsi: e4c75a1cf727c8761908ac2eeb1084e47ba88a26 - React-jsiexecutor: dcc8c2b89b6e0b5abb9bbbfb6df86adf44e3e877 + React-jsiexecutor: 8361f78286021782d885e0888bb059a4045c59b9 React-jsinspector: 9b56a373a6797114e1d89a7dffa98ee98af67a8f React-logger: 07c9b44040a6f948b8e2033207b23cb623f0b9b4 React-perflogger: b4b9fb2ddd856b78003708ab3cf66ce03e6bc7c4 React-RCTActionSheet: 1b1501ef80928be10702cd0ce09120358094cd82 React-RCTAnimation: 6741f7be3e269e057c1426074cc70f34b56e114b React-RCTAppDelegate: 0b3b2c1e02c02f952f5033535ddb23d690e3b890 - React-RCTBlob: 94feb99abafd0527a78f6caaa17a0bcec9ce3167 + React-RCTBlob: fd1ee93e48aa67b0183346a59754375de93de63d React-RCTFabric: db1d7fe55db4811b63ae4060078e7048ebb4a918 React-RCTImage: 055685a12c88939437f6520d9e7c120cd666cbf1 React-RCTLinking: b149b3ff1f96fa93fc445230b9c171adb0e5572c @@ -962,14 +1000,14 @@ SPEC CHECKSUMS: React-RCTTest: 81ebfa8c2e1b0b482effe12485e6486dc0ff70d7 React-RCTText: 4e5ae05b778a0ed2b22b012af025da5e1a1c4e54 React-RCTVibration: ecfd04c1886a9c9a4e31a466c0fbcf6b36e92fde - React-rncore: ec7a711a56a4a64d122be8572b37a67572d5de60 + React-rncore: 1235cadc4feaa607c9af12ca157b8ae991ade3a5 React-runtimeexecutor: c7b2cd6babf6cc50340398bfbb7a9da13c93093f - ReactCommon: a11d5523be510a2d75e50e435de607297072172a + ReactCommon: fdc30b91d89bfd2ed919c2cbccb460435f1f43f4 ScreenshotManager: 37152a3841a53f2de5c0013c58835b8738894553 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 1b1a12ff3d86a10565ea7cbe057d42f5e5fb2a07 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 8da43cb75927abd2bbb2fc21dcebfebb05b89963 +PODFILE CHECKSUM: 920fb3b0e3c9dbdf8d86707f80cf0e7f2dc85c70 COCOAPODS: 1.11.3 From 7208cd63844a878776a7ba5833fc5a909edad104 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Wed, 15 Feb 2023 04:20:20 -0800 Subject: [PATCH 20/81] Switch to xcbeautify (#36131) Summary: `xcpretty` is no longer maintained. Let's switch to `xcbeautify`, which is faster and is maintained. I'm also biased because `xcpretty` hid an error from me that `xcbeautify` did not. ## Changelog [INTERNAL] [CHANGED] - Move CI from `xcpretty` to `xcbeautify` Pull Request resolved: https://github.com/facebook/react-native/pull/36131 Test Plan: Locally yarn `yarn test-ios` and got output that looks like this: Screenshot 2023-02-11 at 9 34 07 PM I also confirmed a junit report that looks like this was generated: ```xml ... ``` Reviewed By: cortinico Differential Revision: D43232774 Pulled By: cipolleschi fbshipit-source-id: fda4e217d4df55b5088026d6911d3dc6c8c9e824 --- .circleci/config.yml | 2 ++ scripts/objc-test.sh | 14 +++++++------- scripts/run-ci-e2e-tests.js | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d180a22cc62d82..e44489663a5fb8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -568,6 +568,8 @@ jobs: - checkout_code_with_cache - setup_artifacts - setup_ruby + - brew_install: + package: xcbeautify - run: name: Run Ruby Tests command: | diff --git a/scripts/objc-test.sh b/scripts/objc-test.sh index a787bab5989045..83ff7639de7f40 100755 --- a/scripts/objc-test.sh +++ b/scripts/objc-test.sh @@ -91,7 +91,7 @@ buildProject() { -sdk iphonesimulator } -xcprettyFormat() { +xcbeautifyFormat() { if [ "$CI" ]; then # Circle CI expects JUnit reports to be available here REPORTS_DIR="$HOME/react-native/reports/junit" @@ -102,7 +102,7 @@ xcprettyFormat() { REPORTS_DIR="$THIS_DIR/../build/reports" fi - xcpretty --report junit --output "$REPORTS_DIR/ios/results.xml" + xcbeautify --report junit --report-path "$REPORTS_DIR/ios/results.xml" } preloadBundles() { @@ -131,16 +131,16 @@ main() { preloadBundles # Build and run tests. - if [ -x "$(command -v xcpretty)" ]; then - runTests | xcprettyFormat && exit "${PIPESTATUS[0]}" + if [ -x "$(command -v xcbeautify)" ]; then + runTests | xcbeautifyFormat && exit "${PIPESTATUS[0]}" else - echo 'Warning: xcpretty is not installed. Install xcpretty to generate JUnit reports.' + echo 'Warning: xcbeautify is not installed. Install xcbeautify to generate JUnit reports.' runTests fi else # Build without running tests. - if [ -x "$(command -v xcpretty)" ]; then - buildProject | xcprettyFormat && exit "${PIPESTATUS[0]}" + if [ -x "$(command -v xcbeautify)" ]; then + buildProject | xcbeautifyFormat && exit "${PIPESTATUS[0]}" else buildProject fi diff --git a/scripts/run-ci-e2e-tests.js b/scripts/run-ci-e2e-tests.js index a94e1be4468860..468b30e8ea06b6 100644 --- a/scripts/run-ci-e2e-tests.js +++ b/scripts/run-ci-e2e-tests.js @@ -234,10 +234,10 @@ try { ].join(' ') + ' | ' + [ - 'xcpretty', + 'xcbeautify', '--report', 'junit', - '--output', + '--reportPath', '"~/react-native/reports/junit/iOS-e2e/results.xml"', ].join(' ') + ' && exit ${PIPESTATUS[0]}', From 96fb708d3eb160fc22a551568729fbab53ddbcbd Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Wed, 15 Feb 2023 06:03:12 -0800 Subject: [PATCH 21/81] Make enums to work as part of data structures for C++ TurboModules codegen (#36155) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36155 [Changelog][Internal] The PR https://github.com/facebook/react-native/pull/36030 (diff D42884147 (https://github.com/facebook/react-native/commit/ceb1d0dea694739f357d86296b94f5834e5ee7f7)) added support for enum types in JS to C++ bridging in C++ TurboModules. This only worked for enums as argument types for exposed methods, but not for the cases when enums are members of complex data structures that are also exposed through a codegen. This diff fixes this problem, so that codegen now correctly works both with enum types as method arguments, but also as data structure members. Some part of the change is the same as D42008724 (https://github.com/facebook/react-native/commit/963e45afd1c69771d1d26df8282774c948f762e3), but there are also some changes related to the types, that were required. Reviewed By: christophpurrer Differential Revision: D43292254 fbshipit-source-id: b2d6cf4a2d4d233b8cc403ecd02b5be16d5d91a7 --- .../GenerateModuleH-test.js.snap | 40 +++++++++---------- .../src/generators/modules/GenerateModuleH.js | 28 ++++++------- .../GenerateModuleH-test.js.snap | 32 +++++++-------- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap index 541b349dbba853..b6a85b3f1ac7a4 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleH-test.js.snap @@ -193,7 +193,7 @@ enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { std::string value = rawValue.utf8(rt); if (value == \\"Active\\") { return NativeEnumTurboModuleStatusRegularEnum::Active; @@ -206,7 +206,7 @@ struct Bridging { } } - static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value) { + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusRegularEnum::Active) { return bridging::toJs(rt, \\"Active\\"); } else if (value == NativeEnumTurboModuleStatusRegularEnum::Paused) { @@ -225,7 +225,7 @@ enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { std::string value = rawValue.utf8(rt); if (value == \\"active\\") { return NativeEnumTurboModuleStatusStrEnum::Active; @@ -238,7 +238,7 @@ struct Bridging { } } - static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value) { + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusStrEnum::Active) { return bridging::toJs(rt, \\"active\\"); } else if (value == NativeEnumTurboModuleStatusStrEnum::Paused) { @@ -257,8 +257,8 @@ enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, int32_t value) { - + static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 2) { return NativeEnumTurboModuleStatusNumEnum::Active; } else if (value == 1) { @@ -270,7 +270,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusNumEnum::Active) { return bridging::toJs(rt, 2); } else if (value == NativeEnumTurboModuleStatusNumEnum::Paused) { @@ -289,8 +289,8 @@ enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, float value) { - + static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 0.2f) { return NativeEnumTurboModuleStatusFractionEnum::Active; } else if (value == 0.1f) { @@ -302,7 +302,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusFractionEnum::Active) { return bridging::toJs(rt, 0.2f); } else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) { @@ -2136,7 +2136,7 @@ enum NativeEnumTurboModuleStatusRegularEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + static NativeEnumTurboModuleStatusRegularEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { std::string value = rawValue.utf8(rt); if (value == \\"Active\\") { return NativeEnumTurboModuleStatusRegularEnum::Active; @@ -2149,7 +2149,7 @@ struct Bridging { } } - static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value) { + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusRegularEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusRegularEnum::Active) { return bridging::toJs(rt, \\"Active\\"); } else if (value == NativeEnumTurboModuleStatusRegularEnum::Paused) { @@ -2168,7 +2168,7 @@ enum NativeEnumTurboModuleStatusStrEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + static NativeEnumTurboModuleStatusStrEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { std::string value = rawValue.utf8(rt); if (value == \\"active\\") { return NativeEnumTurboModuleStatusStrEnum::Active; @@ -2181,7 +2181,7 @@ struct Bridging { } } - static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value) { + static jsi::String toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusStrEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusStrEnum::Active) { return bridging::toJs(rt, \\"active\\"); } else if (value == NativeEnumTurboModuleStatusStrEnum::Paused) { @@ -2200,8 +2200,8 @@ enum NativeEnumTurboModuleStatusNumEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, int32_t value) { - + static NativeEnumTurboModuleStatusNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 2) { return NativeEnumTurboModuleStatusNumEnum::Active; } else if (value == 1) { @@ -2213,7 +2213,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusNumEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusNumEnum::Active) { return bridging::toJs(rt, 2); } else if (value == NativeEnumTurboModuleStatusNumEnum::Paused) { @@ -2232,8 +2232,8 @@ enum NativeEnumTurboModuleStatusFractionEnum { Active, Paused, Off }; template <> struct Bridging { - static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, float value) { - + static NativeEnumTurboModuleStatusFractionEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 0.2f) { return NativeEnumTurboModuleStatusFractionEnum::Active; } else if (value == 0.1f) { @@ -2245,7 +2245,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, NativeEnumTurboModuleStatusFractionEnum value, const std::shared_ptr &jsInvoker) { if (value == NativeEnumTurboModuleStatusFractionEnum::Active) { return bridging::toJs(rt, 0.2f); } else if (value == NativeEnumTurboModuleStatusFractionEnum::Paused) { diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js index 56e1a09fcfc626..0cf09e268390ce 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleH.js @@ -318,18 +318,18 @@ const EnumTemplate = ({ toCases: string, nativeEnumMemberType: NativeEnumMemberValueType, }) => { - const fromValue = + const [fromValue, fromValueConversion, toValue] = nativeEnumMemberType === 'std::string' - ? 'const jsi::String &rawValue' - : `${nativeEnumMemberType} value`; - - const fromValueConvertion = - nativeEnumMemberType === 'std::string' - ? 'std::string value = rawValue.utf8(rt);' - : ''; - - const toValue = - nativeEnumMemberType === 'std::string' ? 'jsi::String' : 'jsi::Value'; + ? [ + 'const jsi::String &rawValue', + 'std::string value = rawValue.utf8(rt);', + 'jsi::String', + ] + : [ + 'const jsi::Value &rawValue', + 'double value = (double)rawValue.asNumber();', + 'jsi::Value', + ]; return ` #pragma mark - ${enumName} @@ -338,12 +338,12 @@ enum ${enumName} { ${values} }; template <> struct Bridging<${enumName}> { - static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}) { - ${fromValueConvertion} + static ${enumName} fromJs(jsi::Runtime &rt, ${fromValue}, const std::shared_ptr &jsInvoker) { + ${fromValueConversion} ${fromCases} } - static ${toValue} toJs(jsi::Runtime &rt, ${enumName} value) { + static ${toValue} toJs(jsi::Runtime &rt, ${enumName} value, const std::shared_ptr &jsInvoker) { ${toCases} } };`; diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap index e0bd0a41e962bb..4f3f7b1d98c058 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleH-test.js.snap @@ -211,8 +211,8 @@ enum SampleTurboModuleCxxNumEnum { ONE, TWO }; template <> struct Bridging { - static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, int32_t value) { - + static SampleTurboModuleCxxNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 1) { return SampleTurboModuleCxxNumEnum::ONE; } else if (value == 2) { @@ -222,7 +222,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxNumEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxNumEnum value, const std::shared_ptr &jsInvoker) { if (value == SampleTurboModuleCxxNumEnum::ONE) { return bridging::toJs(rt, 1); } else if (value == SampleTurboModuleCxxNumEnum::TWO) { @@ -239,8 +239,8 @@ enum SampleTurboModuleCxxFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO }; template <> struct Bridging { - static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, float value) { - + static SampleTurboModuleCxxFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 0.0f) { return SampleTurboModuleCxxFloatEnum::POINT_ZERO; } else if (value == 0.1f) { @@ -252,7 +252,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxFloatEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleCxxFloatEnum value, const std::shared_ptr &jsInvoker) { if (value == SampleTurboModuleCxxFloatEnum::POINT_ZERO) { return bridging::toJs(rt, 0.0f); } else if (value == SampleTurboModuleCxxFloatEnum::POINT_ONE) { @@ -271,7 +271,7 @@ enum SampleTurboModuleCxxStringEnum { HELLO, GoodBye }; template <> struct Bridging { - static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + static SampleTurboModuleCxxStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { std::string value = rawValue.utf8(rt); if (value == \\"hello\\") { return SampleTurboModuleCxxStringEnum::HELLO; @@ -282,7 +282,7 @@ struct Bridging { } } - static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleCxxStringEnum value) { + static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleCxxStringEnum value, const std::shared_ptr &jsInvoker) { if (value == SampleTurboModuleCxxStringEnum::HELLO) { return bridging::toJs(rt, \\"hello\\"); } else if (value == SampleTurboModuleCxxStringEnum::GoodBye) { @@ -1209,8 +1209,8 @@ enum SampleTurboModuleNumEnum { ONE, TWO }; template <> struct Bridging { - static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, int32_t value) { - + static SampleTurboModuleNumEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 1) { return SampleTurboModuleNumEnum::ONE; } else if (value == 2) { @@ -1220,7 +1220,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleNumEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleNumEnum value, const std::shared_ptr &jsInvoker) { if (value == SampleTurboModuleNumEnum::ONE) { return bridging::toJs(rt, 1); } else if (value == SampleTurboModuleNumEnum::TWO) { @@ -1237,8 +1237,8 @@ enum SampleTurboModuleFloatEnum { POINT_ZERO, POINT_ONE, POINT_TWO }; template <> struct Bridging { - static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, float value) { - + static SampleTurboModuleFloatEnum fromJs(jsi::Runtime &rt, const jsi::Value &rawValue, const std::shared_ptr &jsInvoker) { + double value = (double)rawValue.asNumber(); if (value == 0.0f) { return SampleTurboModuleFloatEnum::POINT_ZERO; } else if (value == 0.1f) { @@ -1250,7 +1250,7 @@ struct Bridging { } } - static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleFloatEnum value) { + static jsi::Value toJs(jsi::Runtime &rt, SampleTurboModuleFloatEnum value, const std::shared_ptr &jsInvoker) { if (value == SampleTurboModuleFloatEnum::POINT_ZERO) { return bridging::toJs(rt, 0.0f); } else if (value == SampleTurboModuleFloatEnum::POINT_ONE) { @@ -1269,7 +1269,7 @@ enum SampleTurboModuleStringEnum { HELLO, GoodBye }; template <> struct Bridging { - static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue) { + static SampleTurboModuleStringEnum fromJs(jsi::Runtime &rt, const jsi::String &rawValue, const std::shared_ptr &jsInvoker) { std::string value = rawValue.utf8(rt); if (value == \\"hello\\") { return SampleTurboModuleStringEnum::HELLO; @@ -1280,7 +1280,7 @@ struct Bridging { } } - static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleStringEnum value) { + static jsi::String toJs(jsi::Runtime &rt, SampleTurboModuleStringEnum value, const std::shared_ptr &jsInvoker) { if (value == SampleTurboModuleStringEnum::HELLO) { return bridging::toJs(rt, \\"hello\\"); } else if (value == SampleTurboModuleStringEnum::GoodBye) { From f76d4dee6f876a65cd6476fb399d413d0e96f911 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Wed, 15 Feb 2023 06:03:12 -0800 Subject: [PATCH 22/81] Reference implementation (mock) for NativePerformanceObserver (#36116) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36116 [Changelog][Internal] Add a minimal/reference JavaScript implementation for NativePerformanceObserver - the purpose is both unit testing (JS and native sides separately) and potentially shimming the part of functionality that is not dependent on native side. This is both a setup for adding general unit tests for the Performance* APIs, but also to be able to do non-trivial changes on JS side for WebPerformance (such as in (D43154319). Reviewed By: rubennorte Differential Revision: D43167392 fbshipit-source-id: 213d9534d810dece1dd464f910e92e08dbf39508 --- .../NativePerformanceObserver.cpp | 6 ++ .../NativePerformanceObserver.h | 2 + .../NativePerformanceObserver.js | 7 -- .../WebPerformance/PerformanceObserver.js | 69 ++------------- .../WebPerformance/RawPerformanceEntry.js | 87 +++++++++++++++++++ .../__mocks__/NativePerformanceObserver.js | 56 ++++++++++++ .../NativePerformanceObserverMock-test.js | 56 ++++++++++++ .../__tests__/PerformanceObserver-test.js | 49 +++++++++++ 8 files changed, 261 insertions(+), 71 deletions(-) create mode 100644 Libraries/WebPerformance/RawPerformanceEntry.js create mode 100644 Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js create mode 100644 Libraries/WebPerformance/__tests__/NativePerformanceObserverMock-test.js create mode 100644 Libraries/WebPerformance/__tests__/PerformanceObserver-test.js diff --git a/Libraries/WebPerformance/NativePerformanceObserver.cpp b/Libraries/WebPerformance/NativePerformanceObserver.cpp index dce100dde1bcbd..c1b6265536b31f 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.cpp +++ b/Libraries/WebPerformance/NativePerformanceObserver.cpp @@ -45,4 +45,10 @@ void NativePerformanceObserver::setOnPerformanceEntryCallback( PerformanceEntryReporter::getInstance().setReportingCallback(callback); } +void NativePerformanceObserver::logRawEntry( + jsi::Runtime &rt, + RawPerformanceEntry entry) { + PerformanceEntryReporter::getInstance().logEntry(entry); +} + } // namespace facebook::react diff --git a/Libraries/WebPerformance/NativePerformanceObserver.h b/Libraries/WebPerformance/NativePerformanceObserver.h index 4dd874f558db59..5305a6ce35b91c 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.h +++ b/Libraries/WebPerformance/NativePerformanceObserver.h @@ -69,6 +69,8 @@ class NativePerformanceObserver jsi::Runtime &rt, std::optional> callback); + void logRawEntry(jsi::Runtime &rt, RawPerformanceEntry entry); + private: }; diff --git a/Libraries/WebPerformance/NativePerformanceObserver.js b/Libraries/WebPerformance/NativePerformanceObserver.js index b35bfcb3b0a35b..4af889249a797a 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.js +++ b/Libraries/WebPerformance/NativePerformanceObserver.js @@ -12,13 +12,6 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; -export const RawPerformanceEntryTypeValues = { - UNDEFINED: 0, - MARK: 1, - MEASURE: 2, - EVENT: 3, -}; - export type RawPerformanceEntryType = number; export type RawPerformanceEntry = {| diff --git a/Libraries/WebPerformance/PerformanceObserver.js b/Libraries/WebPerformance/PerformanceObserver.js index c52313f3af17aa..9f47ec7d5135d8 100644 --- a/Libraries/WebPerformance/PerformanceObserver.js +++ b/Libraries/WebPerformance/PerformanceObserver.js @@ -8,74 +8,15 @@ * @flow strict */ -import type { - RawPerformanceEntry, - RawPerformanceEntryType, -} from './NativePerformanceObserver'; import type {PerformanceEntryType} from './PerformanceEntry'; import warnOnce from '../Utilities/warnOnce'; -import NativePerformanceObserver, { - RawPerformanceEntryTypeValues, -} from './NativePerformanceObserver'; +import NativePerformanceObserver from './NativePerformanceObserver'; import {PerformanceEntry} from './PerformanceEntry'; -import {PerformanceEventTiming} from './PerformanceEventTiming'; - -function rawToPerformanceEntryType( - type: RawPerformanceEntryType, -): PerformanceEntryType { - switch (type) { - case RawPerformanceEntryTypeValues.MARK: - return 'mark'; - case RawPerformanceEntryTypeValues.MEASURE: - return 'measure'; - case RawPerformanceEntryTypeValues.EVENT: - return 'event'; - default: - throw new TypeError( - `rawToPerformanceEntryType: unexpected performance entry type received: ${type}`, - ); - } -} - -function performanceEntryTypeToRaw( - type: PerformanceEntryType, -): RawPerformanceEntryType { - switch (type) { - case 'mark': - return RawPerformanceEntryTypeValues.MARK; - case 'measure': - return RawPerformanceEntryTypeValues.MEASURE; - case 'event': - return RawPerformanceEntryTypeValues.EVENT; - default: - // Verify exhaustive check with Flow - (type: empty); - throw new TypeError( - `performanceEntryTypeToRaw: unexpected performance entry type received: ${type}`, - ); - } -} - -function rawToPerformanceEntry(entry: RawPerformanceEntry): PerformanceEntry { - if (entry.entryType === RawPerformanceEntryTypeValues.EVENT) { - return new PerformanceEventTiming({ - name: entry.name, - startTime: entry.startTime, - duration: entry.duration, - processingStart: entry.processingStart, - processingEnd: entry.processingEnd, - interactionId: entry.interactionId, - }); - } else { - return new PerformanceEntry({ - name: entry.name, - entryType: rawToPerformanceEntryType(entry.entryType), - startTime: entry.startTime, - duration: entry.duration, - }); - } -} +import { + performanceEntryTypeToRaw, + rawToPerformanceEntry, +} from './RawPerformanceEntry'; export type PerformanceEntryList = $ReadOnlyArray; diff --git a/Libraries/WebPerformance/RawPerformanceEntry.js b/Libraries/WebPerformance/RawPerformanceEntry.js new file mode 100644 index 00000000000000..c9f3c493f4567c --- /dev/null +++ b/Libraries/WebPerformance/RawPerformanceEntry.js @@ -0,0 +1,87 @@ +/** + * 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 + * @flow strict + */ + +import type { + RawPerformanceEntry, + RawPerformanceEntryType, +} from './NativePerformanceObserver'; +import type {PerformanceEntryType} from './PerformanceEntry'; + +import {PerformanceEntry} from './PerformanceEntry'; +import {PerformanceEventTiming} from './PerformanceEventTiming'; + +export const RawPerformanceEntryTypeValues = { + UNDEFINED: 0, + MARK: 1, + MEASURE: 2, + EVENT: 3, +}; + +export function rawToPerformanceEntry( + entry: RawPerformanceEntry, +): PerformanceEntry { + if (entry.entryType === RawPerformanceEntryTypeValues.EVENT) { + return new PerformanceEventTiming({ + name: entry.name, + startTime: entry.startTime, + duration: entry.duration, + processingStart: entry.processingStart, + processingEnd: entry.processingEnd, + interactionId: entry.interactionId, + }); + } else { + return new PerformanceEntry({ + name: entry.name, + entryType: rawToPerformanceEntryType(entry.entryType), + startTime: entry.startTime, + duration: entry.duration, + }); + } +} + +export function rawToPerformanceEntryType( + type: RawPerformanceEntryType, +): PerformanceEntryType { + switch (type) { + case RawPerformanceEntryTypeValues.MARK: + return 'mark'; + case RawPerformanceEntryTypeValues.MEASURE: + return 'measure'; + case RawPerformanceEntryTypeValues.EVENT: + return 'event'; + case RawPerformanceEntryTypeValues.UNDEFINED: + throw new TypeError( + "rawToPerformanceEntryType: UNDEFINED can't be cast to PerformanceEntryType", + ); + default: + throw new TypeError( + `rawToPerformanceEntryType: unexpected performance entry type received: ${type}`, + ); + } +} + +export function performanceEntryTypeToRaw( + type: PerformanceEntryType, +): RawPerformanceEntryType { + switch (type) { + case 'mark': + return RawPerformanceEntryTypeValues.MARK; + case 'measure': + return RawPerformanceEntryTypeValues.MEASURE; + case 'event': + return RawPerformanceEntryTypeValues.EVENT; + default: + // Verify exhaustive check with Flow + (type: empty); + throw new TypeError( + `performanceEntryTypeToRaw: unexpected performance entry type received: ${type}`, + ); + } +} diff --git a/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js b/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js new file mode 100644 index 00000000000000..617a9122196755 --- /dev/null +++ b/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js @@ -0,0 +1,56 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import type { + GetPendingEntriesResult, + RawPerformanceEntry, + RawPerformanceEntryType, + Spec as NativePerformanceObserver, +} from '../NativePerformanceObserver'; + +const reportingType: Set = new Set(); +let entries: Array = []; +let onPerformanceEntryCallback: ?() => void; + +const NativePerformanceObserverMock: NativePerformanceObserver = { + startReporting: (entryType: RawPerformanceEntryType) => { + reportingType.add(entryType); + }, + + stopReporting: (entryType: RawPerformanceEntryType) => { + reportingType.delete(entryType); + }, + + popPendingEntries: (): GetPendingEntriesResult => { + const res = entries; + entries = []; + return { + droppedEntriesCount: 0, + entries: res, + }; + }, + + setOnPerformanceEntryCallback: (callback?: () => void) => { + onPerformanceEntryCallback = callback; + }, + + logRawEntry: (entry: RawPerformanceEntry) => { + if (reportingType.has(entry.entryType)) { + entries.push(entry); + // $FlowFixMe[incompatible-call] + global.queueMicrotask(() => { + // We want to emulate the way it's done in native (i.e. async/batched) + onPerformanceEntryCallback?.(); + }); + } + }, +}; + +export default NativePerformanceObserverMock; diff --git a/Libraries/WebPerformance/__tests__/NativePerformanceObserverMock-test.js b/Libraries/WebPerformance/__tests__/NativePerformanceObserverMock-test.js new file mode 100644 index 00000000000000..0fe3b7720f1a1e --- /dev/null +++ b/Libraries/WebPerformance/__tests__/NativePerformanceObserverMock-test.js @@ -0,0 +1,56 @@ +/** + * 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 + * @oncall react_native + */ + +import NativePerformanceObserverMock from '../__mocks__/NativePerformanceObserver'; +import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; + +describe('NativePerformanceObserver', () => { + it('correctly starts and stops listening to entries in a nominal scenario', async () => { + NativePerformanceObserverMock.startReporting( + RawPerformanceEntryTypeValues.MARK, + ); + + NativePerformanceObserverMock.logRawEntry({ + name: 'mark1', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 10, + }); + + NativePerformanceObserverMock.logRawEntry({ + name: 'mark2', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 20, + }); + + NativePerformanceObserverMock.logRawEntry({ + name: 'event1', + entryType: RawPerformanceEntryTypeValues.EVENT, + startTime: 0, + duration: 20, + }); + + const entriesResult = NativePerformanceObserverMock.popPendingEntries(); + expect(entriesResult).not.toBe(undefined); + const entries = entriesResult.entries; + + expect(entries.length).toBe(2); + expect(entries[0].name).toBe('mark1'); + expect(entries[1].name).toBe('mark2'); + + const entriesResult1 = NativePerformanceObserverMock.popPendingEntries(); + expect(entriesResult1).not.toBe(undefined); + const entries1 = entriesResult1.entries; + expect(entries1.length).toBe(0); + + NativePerformanceObserverMock.stopReporting('mark'); + }); +}); diff --git a/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js b/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js new file mode 100644 index 00000000000000..060b9a9ab9f6f0 --- /dev/null +++ b/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js @@ -0,0 +1,49 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @oncall react_native + */ + +import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; + +// NOTE: Jest mocks of transitive dependencies don't appear to work with +// ES6 module imports, therefore forced to use commonjs style imports here. +const NativePerformanceObserver = require('../NativePerformanceObserver'); +const PerformanceObserver = require('../PerformanceObserver').default; + +jest.mock( + '../NativePerformanceObserver', + () => require('../__mocks__/NativePerformanceObserver').default, +); + +describe('PerformanceObserver', () => { + it('can be mocked by a reference NativePerformanceObserver implementation', async () => { + expect(NativePerformanceObserver).not.toBe(undefined); + + let totalEntries = 0; + const observer = new PerformanceObserver((list, _observer) => { + const entries = list.getEntries(); + expect(entries).toHaveLength(1); + const entry = entries[0]; + expect(entry.name).toBe('mark1'); + expect(entry.entryType).toBe('mark'); + totalEntries += entries.length; + }); + expect(() => observer.observe({entryTypes: ['mark']})).not.toThrow(); + + NativePerformanceObserver.logRawEntry({ + name: 'mark1', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 0, + }); + + await jest.runAllTicks(); + expect(totalEntries).toBe(1); + observer.disconnect(); + }); +}); From 3418f65d88fa8be3473f757e932ecba1bbfce783 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Wed, 15 Feb 2023 06:04:52 -0800 Subject: [PATCH 23/81] Expose `rrc_root` via prefab (#36166) Summary: The `rrc_root` was not exposed via prefab. I'm adding it to make possible for Reanimated to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/35643. ## Changelog [ANDROID] [CHANGED] - Expose `rrc_root` via prefab. Pull Request resolved: https://github.com/facebook/react-native/pull/36166 Reviewed By: cipolleschi Differential Revision: D43304302 Pulled By: cortinico fbshipit-source-id: 1c4a7013a33b48a8a7a445a78430630542420f4d --- ReactAndroid/build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 6cfc6a248c90f0..56bacf0b9b7965 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -112,6 +112,10 @@ final def preparePrefab = tasks.register("preparePrefab", PreparePrefabHeadersTa new Pair("../ReactCommon/react/renderer/graphics/platform/cxx/", ""), ] ), + new PrefabPreprocessingEntry( + "rrc_root", + new Pair("../ReactCommon/react/renderer/components/root/", "react/renderer/components/root/") + ), new PrefabPreprocessingEntry( "rrc_view", new Pair("../ReactCommon/react/renderer/components/view/", "react/renderer/components/view/") @@ -471,6 +475,7 @@ android { "react_render_core", "react_render_graphics", "rrc_image", + "rrc_root", "rrc_view", "jsi", "glog", @@ -567,6 +572,9 @@ android { rrc_image { headers(new File(prefabHeadersDir, "rrc_image").absolutePath) } + rrc_root { + headers(new File(prefabHeadersDir, "rrc_root").absolutePath) + } rrc_view { headers(new File(prefabHeadersDir, "rrc_view").absolutePath) } From 4a07ed2c0c78fd7d3353aff6e0a7f75a2a4b6b86 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 15 Feb 2023 06:05:56 -0800 Subject: [PATCH 24/81] Make it easier for users to build from source if needed (#36165) Summary: This page is not up to date anymore: https://reactnative.dev/contributing/how-to-build-from-source I'm pushing those changes to make it easier to consume our build when building from source. I'll update the page those change lands. ## Changelog [Internal] [Changed] - Make it easier for users to build from source if needed Pull Request resolved: https://github.com/facebook/react-native/pull/36165 Test Plan: If the CI is green, we should be good to merge this Reviewed By: cipolleschi Differential Revision: D43303867 Pulled By: cortinico fbshipit-source-id: c0080b06cbcbf872ee92fcfa82a9f823d5b247f4 --- package.json | 3 +++ settings.gradle.kts | 15 ++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1e96436351a657..d99ef6323c5a01 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,11 @@ }, "files": [ "android", + "build.gradle.kts", "cli.js", "flow", "flow-typed", + "gradle.properties", "index.js", "interface.js", "jest-preset.js", @@ -61,6 +63,7 @@ "sdks/.hermesversion", "sdks/hermes-engine", "sdks/hermesc", + "settings.gradle.kts", "template.config.js", "template", "!template/node_modules", diff --git a/settings.gradle.kts b/settings.gradle.kts index 836c9a2946eaa1..47ea26461d5496 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,14 +13,15 @@ pluginManagement { } } -include( - ":ReactAndroid", - ":ReactAndroid:hermes-engine", - ":ReactAndroid:external-artifacts", - ":packages:rn-tester:android:app") +include(":ReactAndroid", ":ReactAndroid:hermes-engine", ":ReactAndroid:external-artifacts") -// Include this to enable codegen Gradle plugin. -includeBuild("packages/react-native-gradle-plugin/") +// If the ./packages folder exists, then we're inside the React Native repository. +// If not, a users is consuming this project for a build from source. +if (File("./packages").exists()) { + include(":packages:rn-tester:android:app") + // Include this to enable codegen Gradle plugin. + includeBuild("packages/react-native-gradle-plugin/") +} rootProject.name = "react-native-github" From 8299cdcdea6f53797e1f2b6b77ccb392910a1c33 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 15 Feb 2023 08:03:07 -0800 Subject: [PATCH 25/81] React Native sync for revisions 48b687f...fccf3a9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: This sync includes the following changes: - **[86c8c8db7](https://github.com/facebook/react/commit/86c8c8db7 )**: test: Don't retry flushActWork if flushUntilNextPaint threw ([#26121](https://github.com/facebook/react/pull/26121)) //// - **[64acd3918](https://github.com/facebook/react/commit/64acd3918 )**: remove unguarded getRootNode call ([#26152](https://github.com/facebook/react/pull/26152)) //// - **[71cace4d3](https://github.com/facebook/react/commit/71cace4d3 )**: Migrate testRunner from jasmine2 to jest-circus ([#26144](https://github.com/facebook/react/pull/26144)) //// - **[c8510227c](https://github.com/facebook/react/commit/c8510227c )**: Treat displayName as undefined ([#26148](https://github.com/facebook/react/pull/26148)) //// - **[55542bc73](https://github.com/facebook/react/commit/55542bc73 )**: Update jest printBasicPrototype config ([#26142](https://github.com/facebook/react/pull/26142)) //// - **[6396b6641](https://github.com/facebook/react/commit/6396b6641 )**: Model Float on Hoistables semantics ([#26106](https://github.com/facebook/react/pull/26106)) //// - **[ef9f6e77b](https://github.com/facebook/react/commit/ef9f6e77b )**: Enable passing Server References from Server to Client ([#26124](https://github.com/facebook/react/pull/26124)) //// - **[35698311d](https://github.com/facebook/react/commit/35698311d )**: Update jest escapeString config ([#26140](https://github.com/facebook/react/pull/26140)) //// - **[6ddcbd4f9](https://github.com/facebook/react/commit/6ddcbd4f9 )**: [flow] enable LTI inference mode ([#26104](https://github.com/facebook/react/pull/26104)) //// - **[53b1f69ba](https://github.com/facebook/react/commit/53b1f69ba )**: Implement unstable_getBoundingClientRect in RN Fabric refs ([#26137](https://github.com/facebook/react/pull/26137)) //// - **[594093496](https://github.com/facebook/react/commit/594093496 )**: Update to Jest 29 ([#26088](https://github.com/facebook/react/pull/26088)) //// - **[28fcae062](https://github.com/facebook/react/commit/28fcae062 )**: Add support for SVG `transformOrigin` prop ([#26130](https://github.com/facebook/react/pull/26130)) //// - **[3ff1540e9](https://github.com/facebook/react/commit/3ff1540e9 )**: Prefer JSX in ReactNoop assertions (to combat out-of-memory test runs) ([#26127](https://github.com/facebook/react/pull/26127)) //// - **[01a0c4e12](https://github.com/facebook/react/commit/01a0c4e12 )**: Add Edge Server Builds for workerd / edge-light ([#26116](https://github.com/facebook/react/pull/26116)) //// - **[f0cf832e1](https://github.com/facebook/react/commit/f0cf832e1 )**: Update Flight Fixture to "use client" instead of .client.js ([#26118](https://github.com/facebook/react/pull/26118)) //// - **[03a216070](https://github.com/facebook/react/commit/03a216070 )**: Rename "dom" fork to "dom-node" and "bun" fork to "dom-bun" ([#26117](https://github.com/facebook/react/pull/26117)) //// - **[4bf2113a1](https://github.com/facebook/react/commit/4bf2113a1 )**: Revert "Move the Webpack manifest config to one level deeper ([#26083](https://github.com/facebook/react/pull/26083))" ([#26111](https://github.com/facebook/react/pull/26111)) //// - **[2ef24145e](https://github.com/facebook/react/commit/2ef24145e )**: [flow] upgrade to 0.199.0 ([#26096](https://github.com/facebook/react/pull/26096)) //// - **[922dd7ba5](https://github.com/facebook/react/commit/922dd7ba5 )**: Revert the outer module object to an object ([#26093](https://github.com/facebook/react/pull/26093)) //// - **[9d111ffdf](https://github.com/facebook/react/commit/9d111ffdf )**: Serialize Promises through Flight ([#26086](https://github.com/facebook/react/pull/26086)) //// - **[0ba4698c7](https://github.com/facebook/react/commit/0ba4698c7 )**: Fix async test in React reconciler ([#26087](https://github.com/facebook/react/pull/26087)) //// - **[8c234c0de](https://github.com/facebook/react/commit/8c234c0de )**: Move the Webpack manifest config to one level deeper ([#26083](https://github.com/facebook/react/pull/26083)) //// - **[977bccd24](https://github.com/facebook/react/commit/977bccd24 )**: Refactor Flight Encoding ([#26082](https://github.com/facebook/react/pull/26082)) //// - **[d7bb524ad](https://github.com/facebook/react/commit/d7bb524ad )**: [cleanup] Remove unused package jest-mock-scheduler ([#26084](https://github.com/facebook/react/pull/26084)) //// - **[6b3083266](https://github.com/facebook/react/commit/6b3083266 )**: Upgrade prettier ([#26081](https://github.com/facebook/react/pull/26081)) //// - **[1f5ce59dd](https://github.com/facebook/react/commit/1f5ce59dd )**: [cleanup] fully roll out warnAboutSpreadingKeyToJSX ([#26080](https://github.com/facebook/react/pull/26080)) //// Changelog: [General][Changed] - React Native sync for revisions 48b687f...fccf3a9 jest_e2e[run_all_tests] Reviewed By: rubennorte Differential Revision: D43305607 fbshipit-source-id: 8da7567ca2a182f4be27788935c2da30a731f83b --- Libraries/Renderer/REVISION | 2 +- Libraries/Renderer/shims/ReactNativeTypes.js | 12 ++++++------ .../Renderer/shims/ReactNativeViewConfigRegistry.js | 10 +++++----- .../shims/createReactNativeComponentClass.js | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 2ef55796759cfe..b808372b01808f 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -48b687fc95a172cec8f305312a27d105e5719581 \ No newline at end of file +fccf3a9fba5fd778c678657c556344b333111cfb \ No newline at end of file diff --git a/Libraries/Renderer/shims/ReactNativeTypes.js b/Libraries/Renderer/shims/ReactNativeTypes.js index 39ecaf5257a8b1..403452ef41a5d6 100644 --- a/Libraries/Renderer/shims/ReactNativeTypes.js +++ b/Libraries/Renderer/shims/ReactNativeTypes.js @@ -6,7 +6,7 @@ * * @noformat * @flow strict - * @generated SignedSource<> + * @generated SignedSource<<265b342f0d29323bebb711ba0bc882ec>> * * This file was sync'd from the facebook/react repository. */ @@ -51,7 +51,7 @@ export type AttributeConfiguration = $ReadOnly<{ [propName: string]: AnyAttributeType, style: $ReadOnly<{ [propName: string]: AnyAttributeType, - ..., + ... }>, ... }>; @@ -60,7 +60,7 @@ export type PartialAttributeConfiguration = $ReadOnly<{ [propName: string]: AnyAttributeType, style?: $ReadOnly<{ [propName: string]: AnyAttributeType, - ..., + ... }>, ... }>; @@ -79,13 +79,13 @@ export type ViewConfig = $ReadOnly<{ skipBubbling?: ?boolean, }>, }>, - ..., + ... }>, directEventTypes?: $ReadOnly<{ [eventName: string]: $ReadOnly<{ registrationName: string, }>, - ..., + ... }>, uiViewClassName: string, validAttributes: AttributeConfiguration, @@ -122,7 +122,7 @@ type SecretInternalsType = { type InspectorDataProps = $ReadOnly<{ [propName: string]: string, - ..., + ... }>; type InspectorDataSource = $ReadOnly<{ diff --git a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js index 95538e69da24a8..6fd96f25659a2d 100644 --- a/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js +++ b/Libraries/Renderer/shims/ReactNativeViewConfigRegistry.js @@ -6,7 +6,7 @@ * * @noformat * @flow strict-local - * @generated SignedSource<<7b69bfde64e35b7f706c2f6b9ef91e7c>> + * @generated SignedSource<<47ba85d7f43c9b591d6804827322d00e>> * * This file was sync'd from the facebook/react repository. */ @@ -25,13 +25,13 @@ const customBubblingEventTypes: { skipBubbling?: ?boolean, }>, }>, - ..., + ... } = {}; const customDirectEventTypes: { [eventName: string]: $ReadOnly<{ registrationName: string, }>, - ..., + ... } = {}; exports.customBubblingEventTypes = customBubblingEventTypes; @@ -78,7 +78,7 @@ function processEventTypes(viewConfig: ViewConfig): void { * A callback is provided to load the view config from UIManager. * The callback is deferred until the view is actually rendered. */ -exports.register = function(name: string, callback: () => ViewConfig): string { +exports.register = function (name: string, callback: () => ViewConfig): string { invariant( !viewConfigCallbacks.has(name), 'Tried to register two views with the same name %s', @@ -99,7 +99,7 @@ exports.register = function(name: string, callback: () => ViewConfig): string { * If this is the first time the view has been used, * This configuration will be lazy-loaded from UIManager. */ -exports.get = function(name: string): ViewConfig { +exports.get = function (name: string): ViewConfig { let viewConfig; if (!viewConfigs.has(name)) { const callback = viewConfigCallbacks.get(name); diff --git a/Libraries/Renderer/shims/createReactNativeComponentClass.js b/Libraries/Renderer/shims/createReactNativeComponentClass.js index e1aee01e405d83..0b97635aa67869 100644 --- a/Libraries/Renderer/shims/createReactNativeComponentClass.js +++ b/Libraries/Renderer/shims/createReactNativeComponentClass.js @@ -6,7 +6,7 @@ * * @noformat * @flow strict-local - * @generated SignedSource<<7d3d4090dadea2daa09d92e5e66f6e5d>> + * @generated SignedSource<> * * This file was sync'd from the facebook/react repository. */ @@ -26,7 +26,7 @@ const {register} = ReactNativeViewConfigRegistry; * @param {string} config iOS View configuration. * @private */ -const createReactNativeComponentClass = function( +const createReactNativeComponentClass = function ( name: string, callback: () => ViewConfig, ): string { From 167d52dacd30d3f120d4466f1553ca86f2243b6e Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 15 Feb 2023 08:13:23 -0800 Subject: [PATCH 26/81] Fix ComponentDescriptorProviderRegistry uninitialized fields Summary: `setComponentDescriptorProviderRequest` is only used on iOS for dynamic registration of additional components. This variable is not default initialized, so will point to invalid memory when a component is missing and thus crash. Changelog: [Internal] Fix Android crash when component is missing Reviewed By: rubennorte Differential Revision: D43305656 fbshipit-source-id: 70dd2973d50abbfcc19e051bd24c1deb90883941 --- .../componentregistry/ComponentDescriptorProviderRegistry.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h index cba67833518026..049cdd4212c43f 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h @@ -12,7 +12,6 @@ #include #include #include -#include namespace facebook { namespace react { @@ -65,7 +64,7 @@ class ComponentDescriptorProviderRegistry final { mutable butter::map componentDescriptorProviders_; mutable ComponentDescriptorProviderRequest - componentDescriptorProviderRequest_; + componentDescriptorProviderRequest_{}; }; } // namespace react From cb28a2c46e1c65fbe71a69ee0b0e0bb4b2e20a35 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 15 Feb 2023 09:34:23 -0800 Subject: [PATCH 27/81] Reduce use of RCTLogError (redbox) in prop parsing (#36161) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36161 Changelog: [iOS][Fixed] - Invalid prop values no longer trigger redbox in the legacy renderer ## Context We are changing React Native to behave more like a browser in the sense that **bad style values are not runtime errors**. (See e.g. D43159284 (https://github.com/facebook/react-native/commit/d6e9891577c81503407adaa85db8f5bf97557db0), D43184380.) The recommended way for developers to ensure they are passing correct style values is to use a typechecker (TypeScript or Flow) in conjunction with E2E tests and manual spot checks. ## This diff This change is similar to D43184380, but here we target the legacy renderer on iOS by removing the redboxes from most of `RCTConvert`'s methods. I'm intentionally going with the simplest possible improvement which is to downgrade the redboxes to `RCTLogInfo` ( = log to stdout but not the JS console). Leaving the call sites in place (as opposed to deleting them) will be helpful if we decide that we want to repurpose these checks for a new, more visible diagnostic (though we would likely only build such a diagnostic in Fabric at this point). Reviewed By: javache Differential Revision: D43184379 fbshipit-source-id: 5a3d12f5d884372c7dc8743227d58d403caf24e3 --- React/Base/RCTConvert.h | 2 +- React/Base/RCTConvert.m | 22 +++++++++++----------- React/Views/RCTConvert+Transform.m | 2 +- React/Views/RCTFont.mm | 2 +- React/Views/RCTView.m | 2 +- React/Views/RCTViewManager.m | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 7a7cc75ebdce8f..386c17175d355e 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -173,7 +173,7 @@ RCT_EXTERN NSArray *RCTConvertArrayValue(SEL, id); * avoid repeating the same boilerplate for every error message. */ #define RCTLogConvertError(json, typeName) \ - RCTLogError(@"JSON value '%@' of type %@ cannot be converted to %@", json, [json classForCoder], typeName) + RCTLogInfo(@"JSON value '%@' of type %@ cannot be converted to %@", json, [json classForCoder], typeName) /** * This macro is used for creating simple converter functions that just call diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 5e4820585b0131..a2dfa2bcf6dd89 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -69,7 +69,7 @@ + (NSIndexSet *)NSIndexSet:(id)json for (NSNumber *number in json) { NSInteger index = number.integerValue; if (RCT_DEBUG && index < 0) { - RCTLogError(@"Invalid index value %lld. Indices must be positive.", (long long)index); + RCTLogInfo(@"Invalid index value %lld. Indices must be positive.", (long long)index); } [indexSet addIndex:index]; } @@ -169,7 +169,7 @@ + (NSURLRequest *)NSURLRequest:(id)json __block BOOL allHeadersAreStrings = YES; [headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, id header, BOOL *stop) { if (![header isKindOfClass:[NSString class]]) { - RCTLogError( + RCTLogInfo( @"Values of HTTP headers passed must be of type string. " "Value of header '%@' is not a string.", key); @@ -200,11 +200,11 @@ + (RCTFileURL *)RCTFileURL:(id)json { NSURL *fileURL = [self NSURL:json]; if (!fileURL.fileURL) { - RCTLogError(@"URI must be a local file, '%@' isn't.", fileURL); + RCTLogInfo(@"URI must be a local file, '%@' isn't.", fileURL); return nil; } if (![[NSFileManager defaultManager] fileExistsAtPath:fileURL.path]) { - RCTLogError(@"File '%@' could not be found.", fileURL); + RCTLogInfo(@"File '%@' could not be found.", fileURL); return nil; } return fileURL; @@ -225,7 +225,7 @@ + (NSDate *)NSDate:(id)json }); NSDate *date = [formatter dateFromString:json]; if (!date) { - RCTLogError( + RCTLogInfo( @"JSON String '%@' could not be interpreted as a date. " "Expected format: YYYY-MM-DD'T'HH:mm:ss.sssZ", json); @@ -242,7 +242,7 @@ + (NSLocale *)NSLocale:(id)json if ([json isKindOfClass:[NSString class]]) { NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:json]; if (!locale) { - RCTLogError(@"JSON String '%@' could not be interpreted as a valid locale. ", json); + RCTLogInfo(@"JSON String '%@' could not be interpreted as a valid locale. ", json); } return locale; } else if (json) { @@ -267,15 +267,15 @@ + (NSLocale *)NSLocale:(id)json if ([allValues containsObject:json] || [json isEqual:defaultValue]) { return json; } - RCTLogError(@"Invalid %s '%@'. should be one of: %@", typeName, json, allValues); + RCTLogInfo(@"Invalid %s '%@'. should be one of: %@", typeName, json, allValues); return defaultValue; } if (RCT_DEBUG && ![json isKindOfClass:[NSString class]]) { - RCTLogError(@"Expected NSNumber or NSString for %s, received %@: %@", typeName, [json classForCoder], json); + RCTLogInfo(@"Expected NSNumber or NSString for %s, received %@: %@", typeName, [json classForCoder], json); } id value = mapping[json]; if (RCT_DEBUG && !value && [json description].length > 0) { - RCTLogError( + RCTLogInfo( @"Invalid %s '%@'. should be one of: %@", typeName, json, @@ -541,7 +541,7 @@ static void convertCGStruct(const char *type, NSArray *fields, CGFloat *result, NSUInteger count = fields.count; if ([json isKindOfClass:[NSArray class]]) { if (RCT_DEBUG && [json count] != count) { - RCTLogError( + RCTLogInfo( @"Expected array with count %llu, but count is %llu: %@", (unsigned long long)count, (unsigned long long)[json count], @@ -1295,7 +1295,7 @@ + (UIImage *)UIImage:(id)json } if (!CGSizeEqualToSize(imageSource.size, CGSizeZero) && !CGSizeEqualToSize(imageSource.size, image.size)) { - RCTLogError( + RCTLogInfo( @"Image source %@ size %@ does not match loaded image size %@.", URL.path.lastPathComponent, NSStringFromCGSize(imageSource.size), diff --git a/React/Views/RCTConvert+Transform.m b/React/Views/RCTConvert+Transform.m index 1d2b99b3a055d5..348d4ec4abe8cc 100644 --- a/React/Views/RCTConvert+Transform.m +++ b/React/Views/RCTConvert+Transform.m @@ -138,7 +138,7 @@ + (CATransform3D)CATransform3D:(id)json transform = CATransform3DConcat(next, transform); } else { - RCTLogError(@"Unsupported transform type for a CATransform3D: %@.", property); + RCTLogInfo(@"Unsupported transform type for a CATransform3D: %@.", property); } } return transform; diff --git a/React/Views/RCTFont.mm b/React/Views/RCTFont.mm index 4f75304ee76a7b..9cbb2013ea474a 100644 --- a/React/Views/RCTFont.mm +++ b/React/Views/RCTFont.mm @@ -332,7 +332,7 @@ + (RCTFontVariantDescriptor *)RCTFontVariantDescriptor:(id)json }); RCTFontVariantDescriptor *value = mapping[json]; if (RCT_DEBUG && !value && [json description].length > 0) { - RCTLogError( + RCTLogInfo( @"Invalid RCTFontVariantDescriptor '%@'. should be one of: %@", json, [[mapping allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]); diff --git a/React/Views/RCTView.m b/React/Views/RCTView.m index 6d7583395e3415..eb30e9da667843 100644 --- a/React/Views/RCTView.m +++ b/React/Views/RCTView.m @@ -212,7 +212,7 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event case RCTPointerEventsBoxNone: return hitSubview; default: - RCTLogError(@"Invalid pointer-events specified %lld on %@", (long long)_pointerEvents, self); + RCTLogInfo(@"Invalid pointer-events specified %lld on %@", (long long)_pointerEvents, self); return hitSubview ?: hitView; } } diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index a866b6f748987d..8c97b298879372 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -266,7 +266,7 @@ - (RCTShadowView *)shadowView view.userInteractionEnabled = NO; break; default: - RCTLogError(@"UIView base class does not support pointerEvent value: %@", json); + RCTLogInfo(@"UIView base class does not support pointerEvent value: %@", json); } } RCT_CUSTOM_VIEW_PROPERTY(removeClippedSubviews, BOOL, RCTView) From e328fc2e2429c7917e33125feafd26ad4699ee00 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 15 Feb 2023 13:06:36 -0800 Subject: [PATCH 28/81] Reduce use of Java exceptions in prop parsing (#36160) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36160 Changelog: [Android][Fixed] - Invalid prop values no longer trigger Java exceptions in the legacy renderer ## Context We are changing React Native to behave more like a browser in the sense that **bad style values are not runtime errors**. (See e.g. D43159284 (https://github.com/facebook/react-native/commit/d6e9891577c81503407adaa85db8f5bf97557db0), D43184380.) The recommended way for developers to ensure they are passing correct style values is to use a typechecker (TypeScript or Flow) in conjunction with E2E tests and manual spot checks. ## This diff This change is similar to D43184380, but here we target the legacy renderer on Android by (1) replacing exceptions with logging calls, (2) adding fallback values (equivalent to resetting the respective props to `null`) where needed, and (3) replacing `null` checks in `ReactProp` converters with `instanceof` checks. Leaving the logging call sites in place (as opposed to deleting them) will be helpful if we decide that we want to repurpose these checks for a new, more visible diagnostic (though we would likely only build such a diagnostic in Fabric at this point). Reviewed By: javache Differential Revision: D43274525 fbshipit-source-id: 9d1e7ca3b6299dd827e8667e3d542433ec896c0e --- .../react/bridge/ColorPropConverter.java | 11 ++++ .../processing/ReactPropertyProcessor.java | 36 ++++++++----- .../react/uimanager/LayoutShadowNode.java | 54 ++++++++++++------- .../react/uimanager/TouchTargetHelper.java | 12 ++--- .../react/uimanager/TransformHelper.java | 6 +-- .../drawer/ReactDrawerLayoutManager.java | 16 ++++-- .../java/com/facebook/react/views/image/BUCK | 1 + .../react/views/image/ImageResizeMode.java | 21 ++++---- .../react/views/image/ReactImageManager.java | 7 +-- .../com/facebook/react/views/progressbar/BUCK | 1 + .../ReactProgressBarViewManager.java | 10 ++-- .../views/scroll/ReactScrollViewHelper.java | 8 +-- .../views/text/ReactBaseTextShadowNode.java | 13 +++-- .../text/ReactTextAnchorViewManager.java | 13 ++--- .../react/views/text/TextAttributeProps.java | 13 +++-- .../react/views/text/TextAttributes.java | 8 +-- .../react/views/text/frescosupport/BUCK | 1 + ...coBasedReactTextInlineImageShadowNode.java | 11 ++-- .../textinput/ReactTextInputManager.java | 12 +++-- .../textinput/ReactTextInputShadowNode.java | 7 +-- .../react/views/view/ReactViewManager.java | 12 +++-- .../views/image/ReactImagePropertyTest.java | 8 --- 22 files changed, 168 insertions(+), 113 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ColorPropConverter.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ColorPropConverter.java index af4cfd3b1844cc..afc690dedaabbf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ColorPropConverter.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ColorPropConverter.java @@ -12,6 +12,8 @@ import android.util.TypedValue; import androidx.annotation.Nullable; import androidx.core.content.res.ResourcesCompat; +import com.facebook.common.logging.FLog; +import com.facebook.react.common.ReactConstants; public class ColorPropConverter { private static final String JSON_KEY = "resource_paths"; @@ -61,6 +63,15 @@ public static Integer getColor(Object value, Context context) { "ColorValue: the value must be a number or Object."); } + public static Integer getColor(Object value, Context context, int defaultInt) { + try { + return getColor(value, context); + } catch (JSApplicationCausedNativeException e) { + FLog.w(ReactConstants.TAG, e, "Error converting ColorValue"); + return defaultInt; + } + } + public static Integer resolveResourcePath(Context context, @Nullable String resourcePath) { if (resourcePath == null || resourcePath.isEmpty()) { return null; diff --git a/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java b/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java index 2b5b4ed60953cf..359f854fe5114f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java +++ b/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java @@ -363,11 +363,15 @@ private static CodeBlock.Builder getPropertyExtractor( ClassInfo classInfo, PropertyInfo info, CodeBlock.Builder builder) { TypeName propertyType = info.propertyType; if (propertyType.equals(STRING_TYPE)) { - return builder.add("($L)value", STRING_TYPE); + return builder.add("value instanceof $L ? ($L)value : null", STRING_TYPE, STRING_TYPE); } else if (propertyType.equals(READABLE_ARRAY_TYPE)) { - return builder.add("($L)value", READABLE_ARRAY_TYPE); // TODO: use real type but needs import + return builder.add( + "value instanceof $L ? ($L)value : null", + READABLE_ARRAY_TYPE, + READABLE_ARRAY_TYPE); // TODO: use real type but needs import } else if (propertyType.equals(READABLE_MAP_TYPE)) { - return builder.add("($L)value", READABLE_MAP_TYPE); + return builder.add( + "value instanceof $L ? ($L)value : null", READABLE_MAP_TYPE, READABLE_MAP_TYPE); } else if (propertyType.equals(DYNAMIC_TYPE)) { return builder.add("new $L(value)", DYNAMIC_FROM_OBJECT_TYPE); } else if (propertyType.equals(YOGA_VALUE_TYPE)) { @@ -380,40 +384,46 @@ private static CodeBlock.Builder getPropertyExtractor( } if (propertyType.equals(TypeName.BOOLEAN)) { - return builder.add("value == null ? $L : (boolean) value", info.mProperty.defaultBoolean()); + return builder.add( + "!(value instanceof Boolean) ? $L : (boolean)value", info.mProperty.defaultBoolean()); } if (propertyType.equals(TypeName.DOUBLE)) { double defaultDouble = info.mProperty.defaultDouble(); if (Double.isNaN(defaultDouble)) { - return builder.add("value == null ? $T.NaN : (double) value", Double.class); + return builder.add("!(value instanceof Double) ? $T.NaN : (double)value", Double.class); } else { - return builder.add("value == null ? $Lf : (double) value", defaultDouble); + return builder.add("!(value instanceof Double) ? $Lf : (double)value", defaultDouble); } } if (propertyType.equals(TypeName.FLOAT)) { float defaultFloat = info.mProperty.defaultFloat(); if (Float.isNaN(defaultFloat)) { - return builder.add("value == null ? $T.NaN : ((Double)value).floatValue()", Float.class); + return builder.add( + "!(value instanceof Double) ? $T.NaN : ((Double)value).floatValue()", Float.class); } else { - return builder.add("value == null ? $Lf : ((Double)value).floatValue()", defaultFloat); + return builder.add( + "!(value instanceof Double) ? $Lf : ((Double)value).floatValue()", defaultFloat); } } if ("Color".equals(info.mProperty.customType())) { switch (classInfo.getType()) { case VIEW_MANAGER: return builder.add( - "value == null ? $L : $T.getColor(value, view.getContext())", + "value == null ? $L : $T.getColor(value, view.getContext(), $L)", info.mProperty.defaultInt(), - com.facebook.react.bridge.ColorPropConverter.class); + com.facebook.react.bridge.ColorPropConverter.class, + info.mProperty.defaultInt()); case SHADOW_NODE: return builder.add( - "value == null ? $L : $T.getColor(value, node.getThemedContext())", + "value == null ? $L : $T.getColor(value, node.getThemedContext(), $L)", info.mProperty.defaultInt(), - com.facebook.react.bridge.ColorPropConverter.class); + com.facebook.react.bridge.ColorPropConverter.class, + info.mProperty.defaultInt()); } } else if (propertyType.equals(TypeName.INT)) { return builder.add( - "value == null ? $L : ((Double)value).intValue()", info.mProperty.defaultInt()); + "!(value instanceof Double) ? $L : ((Double)value).intValue()", + info.mProperty.defaultInt()); } throw new IllegalArgumentException(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java index bfcf2be62e5366..07cd486b5477f4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/LayoutShadowNode.java @@ -8,9 +8,10 @@ package com.facebook.react.uimanager; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Dynamic; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableType; +import com.facebook.react.common.ReactConstants; import com.facebook.react.modules.i18nmanager.I18nUtil; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactPropGroup; @@ -60,11 +61,14 @@ void setFromDynamic(Dynamic dynamic) { unit = YogaUnit.PERCENT; value = Float.parseFloat(s.substring(0, s.length() - 1)); } else { - throw new IllegalArgumentException("Unknown value: " + s); + FLog.w(ReactConstants.TAG, "Unknown value: " + s); } - } else { + } else if (dynamic.getType() == ReadableType.Number) { unit = YogaUnit.POINT; value = PixelUtil.toPixelFromDIP(dynamic.asDouble()); + } else { + unit = YogaUnit.UNDEFINED; + value = YogaConstants.UNDEFINED; } } } @@ -318,8 +322,9 @@ public void setFlexDirection(@Nullable String flexDirection) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for flexDirection: " + flexDirection); + FLog.w(ReactConstants.TAG, "invalid value for flexDirection: " + flexDirection); + setFlexDirection(YogaFlexDirection.COLUMN); + break; } } } @@ -353,8 +358,9 @@ public void setFlexWrap(@Nullable String flexWrap) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for flexWrap: " + flexWrap); + FLog.w(ReactConstants.TAG, "invalid value for flexWrap: " + flexWrap); + setFlexWrap(YogaWrap.NO_WRAP); + break; } } } @@ -413,8 +419,9 @@ public void setAlignSelf(@Nullable String alignSelf) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for alignSelf: " + alignSelf); + FLog.w(ReactConstants.TAG, "invalid value for alignSelf: " + alignSelf); + setAlignSelf(YogaAlign.AUTO); + return; } } } @@ -473,8 +480,9 @@ public void setAlignItems(@Nullable String alignItems) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for alignItems: " + alignItems); + FLog.w(ReactConstants.TAG, "invalid value for alignItems: " + alignItems); + setAlignItems(YogaAlign.STRETCH); + return; } } } @@ -533,8 +541,9 @@ public void setAlignContent(@Nullable String alignContent) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for alignContent: " + alignContent); + FLog.w(ReactConstants.TAG, "invalid value for alignContent: " + alignContent); + setAlignContent(YogaAlign.FLEX_START); + return; } } } @@ -583,8 +592,9 @@ public void setJustifyContent(@Nullable String justifyContent) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for justifyContent: " + justifyContent); + FLog.w(ReactConstants.TAG, "invalid value for justifyContent: " + justifyContent); + setJustifyContent(YogaJustify.FLEX_START); + break; } } } @@ -617,8 +627,9 @@ public void setOverflow(@Nullable String overflow) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for overflow: " + overflow); + FLog.w(ReactConstants.TAG, "invalid value for overflow: " + overflow); + setOverflow(YogaOverflow.VISIBLE); + break; } } } @@ -647,7 +658,9 @@ public void setDisplay(@Nullable String display) { } default: { - throw new JSApplicationIllegalArgumentException("invalid value for display: " + display); + FLog.w(ReactConstants.TAG, "invalid value for display: " + display); + setDisplay(YogaDisplay.FLEX); + break; } } } @@ -820,8 +833,9 @@ public void setPosition(@Nullable String position) { } default: { - throw new JSApplicationIllegalArgumentException( - "invalid value for position: " + position); + FLog.w(ReactConstants.TAG, "invalid value for position: " + position); + setPositionType(YogaPositionType.RELATIVE); + break; } } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java index cff46d4dcbd27e..f3ad5d201f550a 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java @@ -17,8 +17,9 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.common.ReactConstants; import com.facebook.react.touch.ReactHitSlopView; import com.facebook.react.uimanager.common.ViewUtil; import java.util.ArrayList; @@ -366,7 +367,10 @@ && isTouchPointInView(eventCoords[0], eventCoords[1], view)) { return null; - } else if (pointerEvents == PointerEvents.AUTO) { + } else { + if (pointerEvents != PointerEvents.AUTO) { + FLog.w(ReactConstants.TAG, "Unknown pointer event type: " + pointerEvents.toString()); + } // Either this view or one of its children is the target if (view instanceof ReactCompoundViewGroup && isTouchPointInView(eventCoords[0], eventCoords[1], view) @@ -387,10 +391,6 @@ && isTouchPointInView(eventCoords[0], eventCoords[1], view) pathAccumulator.add(new ViewTarget(view.getId(), view)); } return result; - - } else { - throw new JSApplicationIllegalArgumentException( - "Unknown pointer event type: " + pointerEvents.toString()); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/TransformHelper.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/TransformHelper.java index da72da4b8d577e..49d6af12396a01 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/TransformHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/TransformHelper.java @@ -7,10 +7,11 @@ package com.facebook.react.uimanager; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableType; +import com.facebook.react.common.ReactConstants; /** * Class providing helper methods for converting transformation list (as accepted by 'transform' @@ -100,8 +101,7 @@ public static void processTransform(ReadableArray transforms, double[] result) { } else if ("skewY".equals(transformType)) { MatrixMathHelper.applySkewY(helperMatrix, convertToRadians(transform, transformType)); } else { - throw new JSApplicationIllegalArgumentException( - "Unsupported transform type: " + transformType); + FLog.w(ReactConstants.TAG, "Unsupported transform type: " + transformType); } MatrixMathHelper.multiplyInto(result, result, helperMatrix); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java index f3b50120c4bf0d..68a941f16ed717 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/drawer/ReactDrawerLayoutManager.java @@ -12,11 +12,13 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.drawerlayout.widget.DrawerLayout; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableType; import com.facebook.react.common.MapBuilder; +import com.facebook.react.common.ReactConstants; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ThemedReactContext; @@ -90,13 +92,14 @@ public void setDrawerPosition(ReactDrawerLayout view, Dynamic drawerPosition) { if (Gravity.START == drawerPositionNum || Gravity.END == drawerPositionNum) { view.setDrawerPosition(drawerPositionNum); } else { - throw new JSApplicationIllegalArgumentException( - "Unknown drawerPosition " + drawerPositionNum); + FLog.w(ReactConstants.TAG, "Unknown drawerPosition " + drawerPositionNum); + view.setDrawerPosition(Gravity.START); } } else if (drawerPosition.getType() == ReadableType.String) { setDrawerPositionInternal(view, drawerPosition.asString()); } else { - throw new JSApplicationIllegalArgumentException("drawerPosition must be a string or int"); + FLog.w(ReactConstants.TAG, "drawerPosition must be a string or int"); + view.setDrawerPosition(Gravity.START); } } @@ -106,8 +109,10 @@ private void setDrawerPositionInternal(ReactDrawerLayout view, String drawerPosi } else if (drawerPosition.equals("right")) { view.setDrawerPosition(Gravity.END); } else { - throw new JSApplicationIllegalArgumentException( + FLog.w( + ReactConstants.TAG, "drawerPosition must be 'left' or 'right', received" + drawerPosition); + view.setDrawerPosition(Gravity.START); } } @@ -139,7 +144,8 @@ public void setDrawerLockMode(ReactDrawerLayout view, @Nullable String drawerLoc } else if ("locked-open".equals(drawerLockMode)) { view.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN); } else { - throw new JSApplicationIllegalArgumentException("Unknown drawerLockMode " + drawerLockMode); + FLog.w(ReactConstants.TAG, "Unknown drawerLockMode " + drawerLockMode); + view.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK index f6f86f8b9a7388..eecd39d1a30a49 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/BUCK @@ -41,6 +41,7 @@ rn_android_library( ], deps = [ YOGA_TARGET, + react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), react_native_dep("libraries/fresco/fresco-react-native:fbcore"), react_native_dep("libraries/fresco/fresco-react-native:fresco-drawee"), react_native_dep("libraries/fresco/fresco-react-native:fresco-react-native"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageResizeMode.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageResizeMode.java index 54df4db60d3e17..8af1fce425cce1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageResizeMode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ImageResizeMode.java @@ -9,8 +9,9 @@ import android.graphics.Shader; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.drawee.drawable.ScalingUtils; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.react.common.ReactConstants; /** Converts JS resize modes into Android-specific scale type. */ public class ImageResizeMode { @@ -41,12 +42,11 @@ public static ScalingUtils.ScaleType toScaleType(@Nullable String resizeModeValu // Handled via a combination of ScaleType and TileMode return ScaleTypeStartInside.INSTANCE; } - if (resizeModeValue == null) { - // Use the default. Never use null. - return defaultValue(); + if (resizeModeValue != null) { + FLog.w(ReactConstants.TAG, "Invalid resize mode: '" + resizeModeValue + "'"); } - throw new JSApplicationIllegalArgumentException( - "Invalid resize mode: '" + resizeModeValue + "'"); + // Use the default. Never use null. + return defaultValue(); } /** Converts JS resize modes into {@code Shader.TileMode}. See {@code ImageResizeMode.js}. */ @@ -61,12 +61,11 @@ public static Shader.TileMode toTileMode(@Nullable String resizeModeValue) { // Handled via a combination of ScaleType and TileMode return Shader.TileMode.REPEAT; } - if (resizeModeValue == null) { - // Use the default. Never use null. - return defaultTileMode(); + if (resizeModeValue != null) { + FLog.w(ReactConstants.TAG, "Invalid resize mode: '" + resizeModeValue + "'"); } - throw new JSApplicationIllegalArgumentException( - "Invalid resize mode: '" + resizeModeValue + "'"); + // Use the default. Never use null. + return defaultTileMode(); } /** This is the default as per web and iOS. We want to be consistent across platforms. */ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index 187958c6ee4db0..67345805224b87 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -10,12 +10,13 @@ import android.graphics.Color; import android.graphics.PorterDuff.Mode; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.controller.AbstractDraweeControllerBuilder; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; +import com.facebook.react.common.ReactConstants; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.SimpleViewManager; @@ -210,8 +211,8 @@ public void setResizeMethod(ReactImageView view, @Nullable String resizeMethod) } else if ("scale".equals(resizeMethod)) { view.setResizeMethod(ImageResizeMethod.SCALE); } else { - throw new JSApplicationIllegalArgumentException( - "Invalid resize method: '" + resizeMethod + "'"); + view.setResizeMethod(ImageResizeMethod.AUTO); + FLog.w(ReactConstants.TAG, "Invalid resize method: '" + resizeMethod + "'"); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK index 52d4b639706aed..ba2f92b743d10d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/BUCK @@ -13,6 +13,7 @@ rn_android_library( ], deps = [ YOGA_TARGET, + react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), react_native_dep("third-party/android/androidx:annotation"), react_native_dep("third-party/java/infer-annotations:infer-annotations"), react_native_dep("third-party/java/jsr-305:jsr-305"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java index 3cdb730a391378..eb4cbfd779f858 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java @@ -13,8 +13,9 @@ import android.view.ViewGroup; import android.widget.ProgressBar; import androidx.annotation.Nullable; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.common.ReactConstants; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.BaseViewManager; import com.facebook.react.uimanager.PixelUtil; @@ -146,8 +147,8 @@ protected ViewManagerDelegate getDelegate() { /* package */ static int getStyleFromString(@Nullable String styleStr) { if (styleStr == null) { - throw new JSApplicationIllegalArgumentException( - "ProgressBar needs to have a style, null received"); + FLog.w(ReactConstants.TAG, "ProgressBar needs to have a style, null received"); + return android.R.attr.progressBarStyle; } else if (styleStr.equals("Horizontal")) { return android.R.attr.progressBarStyleHorizontal; } else if (styleStr.equals("Small")) { @@ -163,7 +164,8 @@ protected ViewManagerDelegate getDelegate() { } else if (styleStr.equals("Normal")) { return android.R.attr.progressBarStyle; } else { - throw new JSApplicationIllegalArgumentException("Unknown ProgressBar style: " + styleStr); + FLog.w(ReactConstants.TAG, "Unknown ProgressBar style: " + styleStr); + return android.R.attr.progressBarStyle; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java index 81d2382b212f23..e16dd1cad29358 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java @@ -17,10 +17,10 @@ import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import com.facebook.common.logging.FLog; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.uimanager.FabricViewStateManager; import com.facebook.react.uimanager.PixelUtil; @@ -153,7 +153,8 @@ public static int parseOverScrollMode(String jsOverScrollMode) { } else if (jsOverScrollMode.equals(OVER_SCROLL_NEVER)) { return View.OVER_SCROLL_NEVER; } else { - throw new JSApplicationIllegalArgumentException("wrong overScrollMode: " + jsOverScrollMode); + FLog.w(ReactConstants.TAG, "wrong overScrollMode: " + jsOverScrollMode); + return View.OVER_SCROLL_IF_CONTENT_SCROLLS; } } @@ -167,7 +168,8 @@ public static int parseSnapToAlignment(@Nullable String alignment) { } else if ("end".equals(alignment)) { return SNAP_ALIGNMENT_END; } else { - throw new JSApplicationIllegalArgumentException("wrong snap alignment value: " + alignment); + FLog.w(ReactConstants.TAG, "wrong snap alignment value: " + alignment); + return SNAP_ALIGNMENT_DISABLED; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java index cbf2967d9755ab..12c1c5e05728a9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java @@ -17,10 +17,11 @@ import android.text.TextUtils; import android.view.Gravity; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.LayoutShadowNode; import com.facebook.react.uimanager.NativeViewHierarchyOptimizer; @@ -460,7 +461,8 @@ public void setTextAlign(@Nullable String textAlign) { } else if ("center".equals(textAlign)) { mTextAlign = Gravity.CENTER_HORIZONTAL; } else { - throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign); + FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlign); + mTextAlign = Gravity.NO_GRAVITY; } } markUpdated(); @@ -572,8 +574,8 @@ public void setTextBreakStrategy(@Nullable String textBreakStrategy) { } else if ("balanced".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_BALANCED; } else { - throw new JSApplicationIllegalArgumentException( - "Invalid textBreakStrategy: " + textBreakStrategy); + FLog.w(ReactConstants.TAG, "Invalid textBreakStrategy: " + textBreakStrategy); + mTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY; } markUpdated(); @@ -629,7 +631,8 @@ public void setTextTransform(@Nullable String textTransform) { } else if ("capitalize".equals(textTransform)) { mTextAttributes.setTextTransform(TextTransform.CAPITALIZE); } else { - throw new JSApplicationIllegalArgumentException("Invalid textTransform: " + textTransform); + FLog.w(ReactConstants.TAG, "Invalid textTransform: " + textTransform); + mTextAttributes.setTextTransform(TextTransform.UNSET); } markUpdated(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java index dc874023c58425..7b5d0c1dd32eaf 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java @@ -16,7 +16,7 @@ import android.view.View; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.BaseViewManager; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.Spacing; @@ -65,7 +65,8 @@ public void setEllipsizeMode(ReactTextView view, @Nullable String ellipsizeMode) } else if (ellipsizeMode.equals("clip")) { view.setEllipsizeLocation(null); } else { - throw new JSApplicationIllegalArgumentException("Invalid ellipsizeMode: " + ellipsizeMode); + FLog.w(ReactConstants.TAG, "Invalid ellipsizeMode: " + ellipsizeMode); + view.setEllipsizeLocation(TextUtils.TruncateAt.END); } } @@ -85,8 +86,8 @@ public void setTextAlignVertical(ReactTextView view, @Nullable String textAlignV } else if ("center".equals(textAlignVertical)) { view.setGravityVertical(Gravity.CENTER_VERTICAL); } else { - throw new JSApplicationIllegalArgumentException( - "Invalid textAlignVertical: " + textAlignVertical); + FLog.w(ReactConstants.TAG, "Invalid textAlignVertical: " + textAlignVertical); + view.setGravityVertical(Gravity.NO_GRAVITY); } } @@ -118,8 +119,8 @@ public void setAndroidHyphenationFrequency(ReactTextView view, @Nullable String } else if (frequency.equals("normal")) { view.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL); } else { - throw new JSApplicationIllegalArgumentException( - "Invalid android_hyphenationFrequency: " + frequency); + FLog.w(ReactConstants.TAG, "Invalid android_hyphenationFrequency: " + frequency); + view.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 787ab9bb14db4a..822969ad8d8fc9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -13,9 +13,10 @@ import android.util.LayoutDirection; import android.view.Gravity; import androidx.annotation.Nullable; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.mapbuffer.MapBuffer; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ReactAccessibilityDelegate; @@ -267,7 +268,8 @@ public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL) { } else if ("center".equals(textAlignPropValue)) { textAlignment = Gravity.CENTER_HORIZONTAL; } else { - throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlignPropValue); + FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlignPropValue); + textAlignment = Gravity.NO_GRAVITY; } } return textAlignment; @@ -563,8 +565,8 @@ public static int getLayoutDirection(@Nullable String layoutDirection) { } else if ("ltr".equals(layoutDirection)) { androidLayoutDirection = LayoutDirection.LTR; } else { - throw new JSApplicationIllegalArgumentException( - "Invalid layoutDirection: " + layoutDirection); + FLog.w(ReactConstants.TAG, "Invalid layoutDirection: " + layoutDirection); + androidLayoutDirection = UNSET; } return androidLayoutDirection; } @@ -595,7 +597,8 @@ private void setTextTransform(@Nullable String textTransform) { } else if ("capitalize".equals(textTransform)) { mTextTransform = TextTransform.CAPITALIZE; } else { - throw new JSApplicationIllegalArgumentException("Invalid textTransform: " + textTransform); + FLog.w(ReactConstants.TAG, "Invalid textTransform: " + textTransform); + mTextTransform = TextTransform.NONE; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributes.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributes.java index f4f78871e8b3c8..8d54a23bbdf6ac 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributes.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributes.java @@ -7,7 +7,8 @@ package com.facebook.react.views.text; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; +import com.facebook.common.logging.FLog; +import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.ViewDefaults; @@ -98,8 +99,9 @@ public float getMaxFontSizeMultiplier() { public void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) { if (maxFontSizeMultiplier != 0 && maxFontSizeMultiplier < 1) { - throw new JSApplicationIllegalArgumentException( - "maxFontSizeMultiplier must be NaN, 0, or >= 1"); + FLog.w(ReactConstants.TAG, "maxFontSizeMultiplier must be NaN, 0, or >= 1"); + mMaxFontSizeMultiplier = Float.NaN; + return; } mMaxFontSizeMultiplier = maxFontSizeMultiplier; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK index e48762cb597ef9..7f8afcb93b4f78 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/BUCK @@ -14,6 +14,7 @@ rn_android_library( deps = [ YOGA_TARGET, react_native_dep("third-party/android/androidx:annotation"), + react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), react_native_dep("libraries/fresco/fresco-react-native:fbcore"), react_native_dep("libraries/fresco/fresco-react-native:fresco-drawee"), react_native_dep("libraries/fresco/fresco-react-native:fresco-react-native"), diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageShadowNode.java index 65d83c2a536cf6..845ca7f1d19858 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/frescosupport/FrescoBasedReactTextInlineImageShadowNode.java @@ -11,13 +11,14 @@ import android.content.res.Resources; import android.net.Uri; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.common.util.UriUtil; import com.facebook.drawee.controller.AbstractDraweeControllerBuilder; import com.facebook.react.bridge.Dynamic; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableType; +import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.views.text.ReactTextInlineImageShadowNode; @@ -84,8 +85,8 @@ public void setWidth(Dynamic width) { if (width.getType() == ReadableType.Number) { mWidth = (float) width.asDouble(); } else { - throw new JSApplicationIllegalArgumentException( - "Inline images must not have percentage based width"); + FLog.w(ReactConstants.TAG, "Inline images must not have percentage based width"); + mWidth = YogaConstants.UNDEFINED; } } @@ -94,8 +95,8 @@ public void setHeight(Dynamic height) { if (height.getType() == ReadableType.Number) { mHeight = (float) height.asDouble(); } else { - throw new JSApplicationIllegalArgumentException( - "Inline images must not have percentage based height"); + FLog.w(ReactConstants.TAG, "Inline images must not have percentage based height"); + mHeight = YogaConstants.UNDEFINED; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index f4733dfcd2bc7e..ddbc072e20d38b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -35,7 +35,6 @@ import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.react.bridge.Dynamic; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.ReadableArray; @@ -45,6 +44,7 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeMap; import com.facebook.react.common.MapBuilder; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.mapbuffer.MapBuffer; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.BaseViewManager; @@ -691,7 +691,8 @@ public void setTextAlign(ReactEditText view, @Nullable String textAlign) { } else if ("center".equals(textAlign)) { view.setGravityHorizontal(Gravity.CENTER_HORIZONTAL); } else { - throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign); + FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlign); + view.setGravityHorizontal(Gravity.NO_GRAVITY); } } } @@ -707,8 +708,8 @@ public void setTextAlignVertical(ReactEditText view, @Nullable String textAlignV } else if ("center".equals(textAlignVertical)) { view.setGravityVertical(Gravity.CENTER_VERTICAL); } else { - throw new JSApplicationIllegalArgumentException( - "Invalid textAlignVertical: " + textAlignVertical); + FLog.w(ReactConstants.TAG, "Invalid textAlignVertical: " + textAlignVertical); + view.setGravityVertical(Gravity.NO_GRAVITY); } } @@ -784,7 +785,8 @@ public void setTextContentType(ReactEditText view, @Nullable String autoComplete } else if (REACT_PROPS_AUTOFILL_HINTS_MAP.containsKey(autoComplete)) { setAutofillHints(view, REACT_PROPS_AUTOFILL_HINTS_MAP.get(autoComplete)); } else { - throw new JSApplicationIllegalArgumentException("Invalid autoComplete: " + autoComplete); + FLog.w(ReactConstants.TAG, "Invalid autoComplete: " + autoComplete); + setImportantForAutofill(view, View.IMPORTANT_FOR_AUTOFILL_NO); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java index e621e1b585f9be..d53a7f9083aa60 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputShadowNode.java @@ -15,9 +15,10 @@ import android.widget.EditText; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; +import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.uimanager.Spacing; import com.facebook.react.uimanager.ThemedReactContext; @@ -218,8 +219,8 @@ public void setTextBreakStrategy(@Nullable String textBreakStrategy) { } else if ("balanced".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_BALANCED; } else { - throw new JSApplicationIllegalArgumentException( - "Invalid textBreakStrategy: " + textBreakStrategy); + FLog.w(ReactConstants.TAG, "Invalid textBreakStrategy: " + textBreakStrategy); + mTextBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 4bd81d72153b0b..4b3d624907d0d5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -13,12 +13,14 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.PixelUtil; @@ -152,9 +154,6 @@ public void setBorderStyle(ReactViewGroup view, @Nullable String borderStyle) { @ReactProp(name = "hitSlop") public void setHitSlop(final ReactViewGroup view, Dynamic hitSlop) { switch (hitSlop.getType()) { - case Null: - view.setHitSlopRect(null); - break; case Map: ReadableMap hitSlopMap = hitSlop.asMap(); view.setHitSlopRect( @@ -177,8 +176,11 @@ public void setHitSlop(final ReactViewGroup view, Dynamic hitSlop) { view.setHitSlopRect(new Rect(hitSlopValue, hitSlopValue, hitSlopValue, hitSlopValue)); break; default: - throw new JSApplicationIllegalArgumentException( - "Invalid type for 'hitSlop' value " + hitSlop.getType()); + FLog.w(ReactConstants.TAG, "Invalid type for 'hitSlop' value " + hitSlop.getType()); + /* falls through */ + case Null: + view.setHitSlopRect(null); + break; } } diff --git a/ReactAndroid/src/test/java/com/facebook/react/views/image/ReactImagePropertyTest.java b/ReactAndroid/src/test/java/com/facebook/react/views/image/ReactImagePropertyTest.java index a2e255f1e4db5c..4240993a2a698c 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/views/image/ReactImagePropertyTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/views/image/ReactImagePropertyTest.java @@ -16,7 +16,6 @@ import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.ReactApplicationContext; @@ -101,13 +100,6 @@ public ReactStylesDiffMap buildStyles(Object... keysAndValues) { return new ReactStylesDiffMap(JavaOnlyMap.of(keysAndValues)); } - @Test(expected = JSApplicationIllegalArgumentException.class) - public void testImageInvalidResizeMode() { - ReactImageManager viewManager = new ReactImageManager(); - ReactImageView view = viewManager.createViewInstance(mThemeContext); - viewManager.updateProperties(view, buildStyles("resizeMode", "pancakes")); - } - @Test public void testBorderColor() { ReactImageManager viewManager = new ReactImageManager(); From 8232c47dcfd4e5bc2244927512588da213f77418 Mon Sep 17 00:00:00 2001 From: Felipe Perez Date: Wed, 15 Feb 2023 14:04:52 -0800 Subject: [PATCH 29/81] Make JSONArguments accept Long values Summary: This util class was introduced in D42978852 (https://github.com/facebook/react-native/commit/611f9c615ebad7d53c1eb1274fe82e36d915165e), but the Long type was not ported over. Not sure if this was intentional or not, but this is used from return values from DeviceConfig, where number values are encoded as Long types. Changelog: [Internal] - internal Differential Revision: D43323851 fbshipit-source-id: 6a8a27b75b1738f2f87dd56ee814316af323c258 --- .../main/java/com/facebook/react/bridge/JSONArguments.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java index 7fb9cc131a5e7c..6e336ba1a88993 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JSONArguments.java @@ -38,6 +38,8 @@ public static ReadableMap fromJSONObject(JSONObject obj) throws JSONException { result.putInt(key, (Integer) val); } else if (val instanceof Double) { result.putDouble(key, (Double) val); + } else if (val instanceof Long) { + result.putInt(key, ((Long) val).intValue()); } else if (obj.isNull(key)) { result.putNull(key); } else { @@ -83,6 +85,8 @@ public static ReadableArray fromJSONArray(JSONArray arr) throws JSONException { result.pushInt((Integer) val); } else if (val instanceof Double) { result.pushDouble((Double) val); + } else if (val instanceof Long) { + result.pushInt(((Long) val).intValue()); } else if (arr.isNull(i)) { result.pushNull(); } else { From d16c1a04d8ceaf6b6df07d734cd54d490b6c6093 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 15 Feb 2023 15:40:24 -0800 Subject: [PATCH 30/81] Reduce use of assertions in prop parsing (#36164) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36164 Changelog: [General][Fixed] - Invalid prop values no longer trigger assertion failures in Fabric ## Context Fabric has historically been very strict about prop parsing. It originally `abort()`ed on any prop value that failed to parse according to the expected type; this was replaced with dev-only assertions in D27540903 (https://github.com/facebook/react-native/commit/cb37562f8355b624e271c5b74416c257b0e62a00). We've received feedback that C++ assertions (and other similar mechanisms in the legacy renderer) are still too aggressive and disruptive as a diagnostic for developers working on JS code. We are changing React Native to behave more like a browser in this regard, reflecting a new principle that **bad style values are not runtime errors**. (See e.g. D43159284 (https://github.com/facebook/react-native/commit/d6e9891577c81503407adaa85db8f5bf97557db0).) The recommended way for developers to ensure they are passing correct style values is to use a typechecker (TypeScript or Flow) in conjunction with E2E tests and manual spot checks. More broadly, values passed from JS product code should not be able to crash the app, which is why we're not strictly limiting this change to style props. From now on, if a JS developer can trigger an internal assertion in React Native simply by writing normal application code, that is a bug. ## This diff This diff introduces a new macro called `react_native_expect` which serves as a drop-in replacement for `react_native_assert`, but logs (to glog / logcat / stdout) instead of asserting. This way we don't need to fully delete the existing call sites. This will be helpful if we decide that we want to repurpose these checks for a new, more visible diagnostic. I'm *intentionally* opting for the simplest possible improvement here, which is to silence the assertions - not to print them to the JS console, not to convert them to LogBox warnings, etc. The hypothesis is that this is already strictly an improvement over the previous behaviour, will help us get to feature parity between renderers faster, and allow us to design improved diagnostics that are consistent and helpful. ## Next steps 1. There are still places where Fabric can hit an unguarded assertion in prop conversion code (e.g. unchecked casts from `RawValue` with no fallback code path). I will fix those in a separate diff. 2. Paper on iOS needs a similar treatment as it calls `RCTLogError` liberally during prop parsing (resulting in a native redbox experience that is nearly as bad as an outright crash). I will fix that in a separate diff. 3. I'll add some manual test cases to RNTester to cover these scenarios. 4. We will eventually need to take a clear stance on PropTypes, but since they provide reasonable, non-breaking diagnostics (recoverable JS LogBox + component stack) it is less urgent to do so. Reviewed By: sammy-SC Differential Revision: D43184380 fbshipit-source-id: 0c921efef297d935a2ae5acc57ff23171356014b --- ReactCommon/react/debug/react_native_assert.h | 6 ++ ReactCommon/react/debug/react_native_expect.h | 41 +++++++++ .../renderer/attributedstring/conversions.h | 92 +++++++++---------- .../renderer/components/image/conversions.h | 6 +- .../iostextinput/propsConversions.h | 7 +- .../renderer/components/view/conversions.h | 60 ++++++------ .../components/view/propsConversions.h | 6 +- .../react/renderer/graphics/conversions.h | 26 +++--- packages/rn-tester/Podfile.lock | 4 +- 9 files changed, 148 insertions(+), 100 deletions(-) create mode 100644 ReactCommon/react/debug/react_native_expect.h diff --git a/ReactCommon/react/debug/react_native_assert.h b/ReactCommon/react/debug/react_native_assert.h index b152858b809f05..9ee5ce631c3d0d 100644 --- a/ReactCommon/react/debug/react_native_assert.h +++ b/ReactCommon/react/debug/react_native_assert.h @@ -12,6 +12,12 @@ // test before moving on. When all issues have been found, maybe we can use // `UNDEBUG` flag to disable NDEBUG in debug builds on Android. +// Asserting is appropriate for conditions that: +// 1. May or may not be recoverable, and +// 2. imply there is a bug in React Native when violated. +// For recoverable conditions that can be violated by user mistake (e.g. JS +// code passes an unexpected prop value), consider react_native_expect instead. + #include "flags.h" #undef react_native_assert diff --git a/ReactCommon/react/debug/react_native_expect.h b/ReactCommon/react/debug/react_native_expect.h new file mode 100644 index 00000000000000..45656664101e43 --- /dev/null +++ b/ReactCommon/react/debug/react_native_expect.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +// No header guards since it is legitimately possible to include this file more +// than once with and without REACT_NATIVE_DEBUG. + +// react_native_expect is a non-fatal counterpart of react_native_assert. +// In debug builds, when an expectation fails, we log and move on. +// In release builds, react_native_expect is a noop. + +// react_native_expect is appropriate for recoverable conditions that can be +// violated by user mistake (e.g. JS code passes an unexpected prop value). +// To enforce invariants that are internal to React Native, consider +// react_native_assert (or a stronger mechanism). +// Calling react_native_expect does NOT, by itself, guarantee that the user +// will see a helpful diagnostic (beyond a low level log). That concern is the +// caller's responsibility. + +#include "flags.h" + +#undef react_native_expect + +#ifndef REACT_NATIVE_DEBUG + +#define react_native_expect(e) ((void)0) + +#else // REACT_NATIVE_DEBUG + +#include +#include + +#define react_native_expect(cond) \ + if (!(cond)) { \ + LOG(ERROR) << "react_native_expect failure: " << #cond; \ + } + +#endif // REACT_NATIVE_DEBUG diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index f585794c678594..6e987b3aa91977 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -60,7 +60,7 @@ inline std::string toString(const DynamicTypeRamp &dynamicTypeRamp) { } LOG(ERROR) << "Unsupported DynamicTypeRamp value"; - react_native_assert(false); + react_native_expect(false); // Sane default in case of parsing errors return "body"; @@ -70,7 +70,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, DynamicTypeRamp &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "caption2") { @@ -98,14 +98,14 @@ inline void fromRawValue( } else { // sane default LOG(ERROR) << "Unsupported DynamicTypeRamp value: " << string; - react_native_assert(false); + react_native_expect(false); result = DynamicTypeRamp::Body; } return; } LOG(ERROR) << "Unsupported DynamicTypeRamp type"; - react_native_assert(false); + react_native_expect(false); // Sane default in case of parsing errors result = DynamicTypeRamp::Body; @@ -124,7 +124,7 @@ inline std::string toString(const EllipsizeMode &ellipsisMode) { } LOG(ERROR) << "Unsupported EllipsizeMode value"; - react_native_assert(false); + react_native_expect(false); // Sane default in case of parsing errors return "tail"; @@ -134,7 +134,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, EllipsizeMode &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "clip") { @@ -148,14 +148,14 @@ inline void fromRawValue( } else { // sane default LOG(ERROR) << "Unsupported EllipsizeMode value: " << string; - react_native_assert(false); + react_native_expect(false); result = EllipsizeMode::Tail; } return; } LOG(ERROR) << "Unsupported EllipsizeMode type"; - react_native_assert(false); + react_native_expect(false); // Sane default in case of parsing errors result = EllipsizeMode::Tail; @@ -172,7 +172,7 @@ inline std::string toString(const TextBreakStrategy &textBreakStrategy) { } LOG(ERROR) << "Unsupported TextBreakStrategy value"; - react_native_assert(false); + react_native_expect(false); return "highQuality"; } @@ -180,7 +180,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, TextBreakStrategy &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "simple") { @@ -192,14 +192,14 @@ inline void fromRawValue( } else { // sane default LOG(ERROR) << "Unsupported TextBreakStrategy value: " << string; - react_native_assert(false); + react_native_expect(false); result = TextBreakStrategy::HighQuality; } return; } LOG(ERROR) << "Unsupported TextBreakStrategy type"; - react_native_assert(false); + react_native_expect(false); result = TextBreakStrategy::HighQuality; } @@ -207,7 +207,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, FontWeight &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "normal") { @@ -236,7 +236,7 @@ inline void fromRawValue( result = FontWeight::Weight900; } else { LOG(ERROR) << "Unsupported FontWeight value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = FontWeight::Regular; } @@ -244,7 +244,7 @@ inline void fromRawValue( } LOG(ERROR) << "Unsupported FontWeight type"; - react_native_assert(false); + react_native_expect(false); result = FontWeight::Regular; } @@ -256,7 +256,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, FontStyle &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "normal") { @@ -267,7 +267,7 @@ inline void fromRawValue( result = FontStyle::Oblique; } else { LOG(ERROR) << "Unsupported FontStyle value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = FontStyle::Normal; } @@ -275,7 +275,7 @@ inline void fromRawValue( } LOG(ERROR) << "Unsupported FontStyle type"; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = FontStyle::Normal; } @@ -291,7 +291,7 @@ inline std::string toString(const FontStyle &fontStyle) { } LOG(ERROR) << "Unsupported FontStyle value"; - react_native_assert(false); + react_native_expect(false); // sane default for prod return "normal"; } @@ -300,7 +300,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, FontVariant &result) { - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); result = FontVariant::Default; if (value.hasType>()) { auto items = std::vector{value}; @@ -318,7 +318,7 @@ inline void fromRawValue( (FontVariant)((int)result | (int)FontVariant::ProportionalNums); } else { LOG(ERROR) << "Unsupported FontVariant value: " << item; - react_native_assert(false); + react_native_expect(false); } continue; } @@ -357,7 +357,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, TextTransform &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "none") { @@ -372,7 +372,7 @@ inline void fromRawValue( result = TextTransform::Unset; } else { LOG(ERROR) << "Unsupported TextTransform value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = TextTransform::None; } @@ -380,7 +380,7 @@ inline void fromRawValue( } LOG(ERROR) << "Unsupported TextTransform type"; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = TextTransform::None; } @@ -400,7 +400,7 @@ inline std::string toString(const TextTransform &textTransform) { } LOG(ERROR) << "Unsupported TextTransform value"; - react_native_assert(false); + react_native_expect(false); // sane default for prod return "none"; } @@ -409,7 +409,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, TextAlignment &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "auto") { @@ -424,7 +424,7 @@ inline void fromRawValue( result = TextAlignment::Justified; } else { LOG(ERROR) << "Unsupported TextAlignment value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = TextAlignment::Natural; } @@ -459,7 +459,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, WritingDirection &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "natural" || string == "auto") { @@ -470,7 +470,7 @@ inline void fromRawValue( result = WritingDirection::RightToLeft; } else { LOG(ERROR) << "Unsupported WritingDirection value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = WritingDirection::Natural; } @@ -501,7 +501,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, LineBreakStrategy &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "none") { @@ -514,7 +514,7 @@ inline void fromRawValue( result = LineBreakStrategy::Standard; } else { LOG(ERROR) << "Unsupported LineBreakStrategy value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = LineBreakStrategy::None; } @@ -547,7 +547,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, TextDecorationLineType &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "none") { @@ -564,7 +564,7 @@ inline void fromRawValue( result = TextDecorationLineType::UnderlineStrikethrough; } else { LOG(ERROR) << "Unsupported TextDecorationLineType value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = TextDecorationLineType::None; } @@ -590,7 +590,7 @@ inline std::string toString( } LOG(ERROR) << "Unsupported TextDecorationLineType value"; - react_native_assert(false); + react_native_expect(false); // sane default for prod return "none"; } @@ -599,7 +599,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, TextDecorationStyle &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "solid") { @@ -612,7 +612,7 @@ inline void fromRawValue( result = TextDecorationStyle::Dashed; } else { LOG(ERROR) << "Unsupported TextDecorationStyle value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = TextDecorationStyle::Solid; } @@ -637,7 +637,7 @@ inline std::string toString(const TextDecorationStyle &textDecorationStyle) { } LOG(ERROR) << "Unsupported TextDecorationStyle value"; - react_native_assert(false); + react_native_expect(false); // sane default for prod return "solid"; } @@ -703,7 +703,7 @@ inline std::string toString(const AccessibilityRole &accessibilityRole) { } LOG(ERROR) << "Unsupported AccessibilityRole value"; - react_native_assert(false); + react_native_expect(false); // sane default for prod return "none"; } @@ -712,7 +712,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, AccessibilityRole &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "none") { @@ -773,7 +773,7 @@ inline void fromRawValue( result = AccessibilityRole::Toolbar; } else { LOG(ERROR) << "Unsupported AccessibilityRole value: " << string; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = AccessibilityRole::None; } @@ -781,7 +781,7 @@ inline void fromRawValue( } LOG(ERROR) << "Unsupported AccessibilityRole type"; - react_native_assert(false); + react_native_expect(false); // sane default for prod result = AccessibilityRole::None; } @@ -797,7 +797,7 @@ inline std::string toString(const HyphenationFrequency &hyphenationFrequency) { } LOG(ERROR) << "Unsupported HyphenationFrequency value"; - react_native_assert(false); + react_native_expect(false); return "none"; } @@ -805,7 +805,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, HyphenationFrequency &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "none") { @@ -817,14 +817,14 @@ inline void fromRawValue( } else { // sane default LOG(ERROR) << "Unsupported HyphenationFrequency value: " << string; - react_native_assert(false); + react_native_expect(false); result = HyphenationFrequency::None; } return; } LOG(ERROR) << "Unsupported HyphenationFrequency type"; - react_native_assert(false); + react_native_expect(false); result = HyphenationFrequency::None; } diff --git a/ReactCommon/react/renderer/components/image/conversions.h b/ReactCommon/react/renderer/components/image/conversions.h index 4b4e3d9ca9d31c..c466702c0a43c6 100644 --- a/ReactCommon/react/renderer/components/image/conversions.h +++ b/ReactCommon/react/renderer/components/image/conversions.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -97,7 +97,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, ImageResizeMode &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); if (!value.hasType()) { LOG(ERROR) << "Unsupported ImageResizeMode type"; // "cover" is default in non-Fabric web and iOS @@ -118,7 +118,7 @@ inline void fromRawValue( result = ImageResizeMode::Repeat; } else { LOG(ERROR) << "Unsupported ImageResizeMode value: " << stringValue; - react_native_assert(false); + react_native_expect(false); // "cover" is default in non-Fabric web and iOS result = ImageResizeMode::Cover; } diff --git a/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h index 15dc0004596da0..d3cdf58f32fe1e 100644 --- a/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h +++ b/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/propsConversions.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -158,16 +159,16 @@ inline void fromRawValue( result.end = pair.second; } else { LOG(ERROR) << "Unsupported Selection map key: " << pair.first; - react_native_assert(false); + react_native_expect(false); } } return; } - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); if (value.hasType>()) { auto array = (std::vector)value; - react_native_assert(array.size() == 2); + react_native_expect(array.size() == 2); if (array.size() >= 2) { result = {array.at(0), array.at(1)}; } else { diff --git a/ReactCommon/react/renderer/components/view/conversions.h b/ReactCommon/react/renderer/components/view/conversions.h index a77ae6b2ab72c8..1775a28b681ca2 100644 --- a/ReactCommon/react/renderer/components/view/conversions.h +++ b/ReactCommon/react/renderer/components/view/conversions.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -169,7 +169,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGDirection &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "inherit") { result = YGDirectionInherit; @@ -184,14 +184,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGDirection:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGFlexDirection &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "row") { result = YGFlexDirectionRow; @@ -210,14 +210,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGFlexDirection:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGJustify &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "flex-start") { result = YGJustifyFlexStart; @@ -244,14 +244,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGJustify:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGAlign &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "auto") { result = YGAlignAuto; @@ -286,14 +286,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGAlign:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGPositionType &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "static") { result = YGPositionTypeStatic; @@ -308,14 +308,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGPositionType:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGWrap &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "nowrap") { result = YGWrapNoWrap; @@ -330,14 +330,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGWrap:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGOverflow &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "visible") { result = YGOverflowVisible; @@ -352,14 +352,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGOverflow:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGDisplay &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "flex") { result = YGDisplayFlex; @@ -370,7 +370,7 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse YGDisplay:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( @@ -433,14 +433,14 @@ inline void fromRawValue( } } LOG(FATAL) << "Could not parse YGFloatOptional"; - react_native_assert(false); + react_native_expect(false); } inline Float toRadians(const RawValue &value) { if (value.hasType()) { return (Float)value; } - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; char *suffixStart; double num = strtod( @@ -456,7 +456,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, Transform &result) { - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); auto transformMatrix = Transform{}; auto configurations = static_cast>(value); @@ -474,9 +474,9 @@ inline void fromRawValue( auto ¶meters = pair->second; if (operation == "matrix") { - react_native_assert(parameters.hasType>()); + react_native_expect(parameters.hasType>()); auto numbers = (std::vector)parameters; - react_native_assert(numbers.size() == transformMatrix.matrix.size()); + react_native_expect(numbers.size() == transformMatrix.matrix.size()); auto i = 0; for (auto number : numbers) { transformMatrix.matrix[i++] = number; @@ -534,7 +534,7 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, PointerEventsMode &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "auto") { result = PointerEventsMode::Auto; @@ -553,14 +553,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse PointerEventsMode:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, BackfaceVisibility &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "auto") { result = BackfaceVisibility::Auto; @@ -575,14 +575,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse BackfaceVisibility:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, BorderCurve &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "circular") { result = BorderCurve::Circular; @@ -593,14 +593,14 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse BorderCurve:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline void fromRawValue( const PropsParserContext &context, const RawValue &value, BorderStyle &result) { - react_native_assert(value.hasType()); + react_native_expect(value.hasType()); auto stringValue = (std::string)value; if (stringValue == "solid") { result = BorderStyle::Solid; @@ -615,7 +615,7 @@ inline void fromRawValue( return; } LOG(FATAL) << "Could not parse BorderStyle:" << stringValue; - react_native_assert(false); + react_native_expect(false); } inline std::string toString( diff --git a/ReactCommon/react/renderer/components/view/propsConversions.h b/ReactCommon/react/renderer/components/view/propsConversions.h index ad7cc2f3a3488c..8f2e30df977c37 100644 --- a/ReactCommon/react/renderer/components/view/propsConversions.h +++ b/ReactCommon/react/renderer/components/view/propsConversions.h @@ -724,13 +724,13 @@ static inline void fromRawValue( auto map = (butter::map)rawValue; auto typeIterator = map.find("type"); - react_native_assert( + react_native_expect( typeIterator != map.end() && typeIterator->second.hasType()); std::string type = (std::string)typeIterator->second; if (type == "ThemeAttrAndroid") { auto attrIterator = map.find("attribute"); - react_native_assert( + react_native_expect( attrIterator != map.end() && attrIterator->second.hasType()); @@ -761,7 +761,7 @@ static inline void fromRawValue( }; } else { LOG(ERROR) << "Unknown native drawable type: " << type; - react_native_assert(false); + react_native_expect(false); } } diff --git a/ReactCommon/react/renderer/graphics/conversions.h b/ReactCommon/react/renderer/graphics/conversions.h index 8ce4f341f79696..c142b8e57bf8c0 100644 --- a/ReactCommon/react/renderer/graphics/conversions.h +++ b/ReactCommon/react/renderer/graphics/conversions.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -41,7 +41,7 @@ inline void fromRawValue( } else if (value.hasType>()) { auto items = (std::vector)value; auto length = items.size(); - react_native_assert(length == 3 || length == 4); + react_native_expect(length == 3 || length == 4); colorComponents.red = items.at(0); colorComponents.green = items.at(1); colorComponents.blue = items.at(2); @@ -86,10 +86,10 @@ inline void fromRawValue( return; } - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); if (value.hasType>()) { auto array = (std::vector)value; - react_native_assert(array.size() == 2); + react_native_expect(array.size() == 2); if (array.size() >= 2) { result = {array.at(0), array.at(1)}; } else { @@ -114,16 +114,16 @@ inline void fromRawValue( result.height = pair.second; } else { LOG(ERROR) << "Unsupported Size map key: " << pair.first; - react_native_assert(false); + react_native_expect(false); } } return; } - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); if (value.hasType>()) { auto array = (std::vector)value; - react_native_assert(array.size() == 2); + react_native_expect(array.size() == 2); if (array.size() >= 2) { result = {array.at(0), array.at(1)}; } else { @@ -158,16 +158,16 @@ inline void fromRawValue( result.right = pair.second; } else { LOG(ERROR) << "Unsupported EdgeInsets map key: " << pair.first; - react_native_assert(false); + react_native_expect(false); } } return; } - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); if (value.hasType>()) { auto array = (std::vector)value; - react_native_assert(array.size() == 4); + react_native_expect(array.size() == 4); if (array.size() >= 4) { result = {array.at(0), array.at(1), array.at(2), array.at(3)}; } else { @@ -202,16 +202,16 @@ inline void fromRawValue( result.bottomRight = pair.second; } else { LOG(ERROR) << "Unsupported CornerInsets map key: " << pair.first; - react_native_assert(false); + react_native_expect(false); } } return; } - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); if (value.hasType>()) { auto array = (std::vector)value; - react_native_assert(array.size() == 4); + react_native_expect(array.size() == 4); if (array.size() >= 4) { result = {array.at(0), array.at(1), array.at(2), array.at(3)}; } else { diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index 353aa4e5bdfd70..a9654da05f8da7 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -956,7 +956,7 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: d68947eddece25638eb0f642d1b957c90388afd1 - FBReactNativeSpec: c530d2df977f98d0d72ce4440c074cb73bff6289 + FBReactNativeSpec: dbfbd06ef9022b1a0198d14654ca3f4d8bbdea04 Flipper: 186214d97e5c24edd706f39faf933e5acaaa8644 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 @@ -967,7 +967,7 @@ SPEC CHECKSUMS: FlipperKit: b353b63cb4048a5747529412524407d6efa68336 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: 44aadce06e4021379728f804a9503c4c5030c246 + hermes-engine: c6856cfc0143b20743bc478ca77fc086d74b7bfe libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 From ee4714e3693a3bd88215bd7a19ff805e3262b1c8 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 15 Feb 2023 15:40:24 -0800 Subject: [PATCH 31/81] Consistently assign defaults when prop parsing fails (#36163) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36163 Changelog: [General][Fixed] - Fix assertions in Fabric layout and transform prop parsing Continues D43184380 by adding more graceful fallback paths to the prop parsing logic in Fabric. Reviewed By: sammy-SC Differential Revision: D43184994 fbshipit-source-id: 8f2bb6cdc23197a431b914b36523dce8a8af9b54 --- .../renderer/attributedstring/conversions.h | 2 +- .../renderer/components/view/conversions.h | 105 ++++++++++++++---- 2 files changed, 82 insertions(+), 25 deletions(-) diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 6e987b3aa91977..367afbfc30007d 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -300,8 +300,8 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, FontVariant &result) { - react_native_expect(value.hasType>()); result = FontVariant::Default; + react_native_expect(value.hasType>()); if (value.hasType>()) { auto items = std::vector{value}; for (const auto &item : items) { diff --git a/ReactCommon/react/renderer/components/view/conversions.h b/ReactCommon/react/renderer/components/view/conversions.h index 1775a28b681ca2..b78d264d8d439a 100644 --- a/ReactCommon/react/renderer/components/view/conversions.h +++ b/ReactCommon/react/renderer/components/view/conversions.h @@ -169,7 +169,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGDirection &result) { + result = YGDirectionInherit; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "inherit") { result = YGDirectionInherit; @@ -183,7 +187,7 @@ inline void fromRawValue( result = YGDirectionRTL; return; } - LOG(FATAL) << "Could not parse YGDirection:" << stringValue; + LOG(ERROR) << "Could not parse YGDirection:" << stringValue; react_native_expect(false); } @@ -191,7 +195,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGFlexDirection &result) { + result = YGFlexDirectionColumn; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "row") { result = YGFlexDirectionRow; @@ -209,7 +217,7 @@ inline void fromRawValue( result = YGFlexDirectionRowReverse; return; } - LOG(FATAL) << "Could not parse YGFlexDirection:" << stringValue; + LOG(ERROR) << "Could not parse YGFlexDirection:" << stringValue; react_native_expect(false); } @@ -217,7 +225,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGJustify &result) { + result = YGJustifyFlexStart; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "flex-start") { result = YGJustifyFlexStart; @@ -243,7 +255,7 @@ inline void fromRawValue( result = YGJustifySpaceEvenly; return; } - LOG(FATAL) << "Could not parse YGJustify:" << stringValue; + LOG(ERROR) << "Could not parse YGJustify:" << stringValue; react_native_expect(false); } @@ -251,7 +263,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGAlign &result) { + result = YGAlignStretch; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "auto") { result = YGAlignAuto; @@ -285,7 +301,7 @@ inline void fromRawValue( result = YGAlignSpaceAround; return; } - LOG(FATAL) << "Could not parse YGAlign:" << stringValue; + LOG(ERROR) << "Could not parse YGAlign:" << stringValue; react_native_expect(false); } @@ -293,7 +309,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGPositionType &result) { + result = YGPositionTypeRelative; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "static") { result = YGPositionTypeStatic; @@ -307,7 +327,7 @@ inline void fromRawValue( result = YGPositionTypeAbsolute; return; } - LOG(FATAL) << "Could not parse YGPositionType:" << stringValue; + LOG(ERROR) << "Could not parse YGPositionType:" << stringValue; react_native_expect(false); } @@ -315,7 +335,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGWrap &result) { + result = YGWrapNoWrap; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "nowrap") { result = YGWrapNoWrap; @@ -329,7 +353,7 @@ inline void fromRawValue( result = YGWrapWrapReverse; return; } - LOG(FATAL) << "Could not parse YGWrap:" << stringValue; + LOG(ERROR) << "Could not parse YGWrap:" << stringValue; react_native_expect(false); } @@ -337,7 +361,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGOverflow &result) { + result = YGOverflowVisible; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "visible") { result = YGOverflowVisible; @@ -351,7 +379,7 @@ inline void fromRawValue( result = YGOverflowScroll; return; } - LOG(FATAL) << "Could not parse YGOverflow:" << stringValue; + LOG(ERROR) << "Could not parse YGOverflow:" << stringValue; react_native_expect(false); } @@ -359,7 +387,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, YGDisplay &result) { + result = YGDisplayFlex; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "flex") { result = YGDisplayFlex; @@ -369,7 +401,7 @@ inline void fromRawValue( result = YGDisplayNone; return; } - LOG(FATAL) << "Could not parse YGDisplay:" << stringValue; + LOG(ERROR) << "Could not parse YGDisplay:" << stringValue; react_native_expect(false); } @@ -432,15 +464,20 @@ inline void fromRawValue( return; } } - LOG(FATAL) << "Could not parse YGFloatOptional"; + LOG(ERROR) << "Could not parse YGFloatOptional"; react_native_expect(false); } -inline Float toRadians(const RawValue &value) { +inline Float toRadians( + const RawValue &value, + std::optional defaultValue) { if (value.hasType()) { return (Float)value; } react_native_expect(value.hasType()); + if (!value.hasType() && defaultValue.has_value()) { + return *defaultValue; + } auto stringValue = (std::string)value; char *suffixStart; double num = strtod( @@ -456,10 +493,14 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, Transform &result) { - react_native_expect(value.hasType>()); auto transformMatrix = Transform{}; - auto configurations = static_cast>(value); + react_native_expect(value.hasType>()); + if (!value.hasType>()) { + result = transformMatrix; + return; + } + auto configurations = static_cast>(value); for (const auto &configuration : configurations) { if (!configuration.hasType>()) { // TODO: The following checks have to be removed after codegen is shipped. @@ -487,14 +528,14 @@ inline void fromRawValue( transformMatrix = transformMatrix * Transform::Perspective((Float)parameters); } else if (operation == "rotateX") { - transformMatrix = - transformMatrix * Transform::Rotate(toRadians(parameters), 0, 0); + transformMatrix = transformMatrix * + Transform::Rotate(toRadians(parameters, 0.0f), 0, 0); } else if (operation == "rotateY") { - transformMatrix = - transformMatrix * Transform::Rotate(0, toRadians(parameters), 0); + transformMatrix = transformMatrix * + Transform::Rotate(0, toRadians(parameters, 0.0f), 0); } else if (operation == "rotateZ" || operation == "rotate") { - transformMatrix = - transformMatrix * Transform::Rotate(0, 0, toRadians(parameters)); + transformMatrix = transformMatrix * + Transform::Rotate(0, 0, toRadians(parameters, 0.0f)); } else if (operation == "scale") { auto number = (Float)parameters; transformMatrix = @@ -520,10 +561,10 @@ inline void fromRawValue( transformMatrix * Transform::Translate(0, (Float)parameters, 0); } else if (operation == "skewX") { transformMatrix = - transformMatrix * Transform::Skew(toRadians(parameters), 0); + transformMatrix * Transform::Skew(toRadians(parameters, 0.0f), 0); } else if (operation == "skewY") { transformMatrix = - transformMatrix * Transform::Skew(0, toRadians(parameters)); + transformMatrix * Transform::Skew(0, toRadians(parameters, 0.0f)); } } @@ -534,7 +575,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, PointerEventsMode &result) { + result = PointerEventsMode::Auto; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "auto") { result = PointerEventsMode::Auto; @@ -552,7 +597,7 @@ inline void fromRawValue( result = PointerEventsMode::BoxOnly; return; } - LOG(FATAL) << "Could not parse PointerEventsMode:" << stringValue; + LOG(ERROR) << "Could not parse PointerEventsMode:" << stringValue; react_native_expect(false); } @@ -560,7 +605,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, BackfaceVisibility &result) { + result = BackfaceVisibility::Auto; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "auto") { result = BackfaceVisibility::Auto; @@ -574,7 +623,7 @@ inline void fromRawValue( result = BackfaceVisibility::Hidden; return; } - LOG(FATAL) << "Could not parse BackfaceVisibility:" << stringValue; + LOG(ERROR) << "Could not parse BackfaceVisibility:" << stringValue; react_native_expect(false); } @@ -582,7 +631,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, BorderCurve &result) { + result = BorderCurve::Circular; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "circular") { result = BorderCurve::Circular; @@ -592,7 +645,7 @@ inline void fromRawValue( result = BorderCurve::Continuous; return; } - LOG(FATAL) << "Could not parse BorderCurve:" << stringValue; + LOG(ERROR) << "Could not parse BorderCurve:" << stringValue; react_native_expect(false); } @@ -600,7 +653,11 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, BorderStyle &result) { + result = BorderStyle::Solid; react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } auto stringValue = (std::string)value; if (stringValue == "solid") { result = BorderStyle::Solid; @@ -614,7 +671,7 @@ inline void fromRawValue( result = BorderStyle::Dashed; return; } - LOG(FATAL) << "Could not parse BorderStyle:" << stringValue; + LOG(ERROR) << "Could not parse BorderStyle:" << stringValue; react_native_expect(false); } From 70fb2dce4557da1195289a24638b1e4d2c2edbf7 Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Wed, 15 Feb 2023 20:52:48 -0800 Subject: [PATCH 32/81] Add performance.memory API Summary: This diff adds new performance API `memory`, which is a read-only property that gets the current JS heap size from native side. Note that the JSI API returns an unordered map with unknown list of memory information, which is different from the [web spec](https://fburl.com/p0vpbt33). We may enforce specific memory info type on the JSI API so that it can be properly translate to the web spec. - Update the JS spec - Update Native implementation and return memory information with JSI API `jsi::instrumentation()::getHeapInfo()` - Add native performance module to catalyst package Changelog: [General][Added] - Add performance memory API with native memory Info Reviewed By: rubennorte Differential Revision: D43137071 fbshipit-source-id: 319f1a6ba78fce61e665b00849ecf2579094af83 --- Libraries/WebPerformance/MemoryInfo.js | 45 +++++++++++++++++++ .../WebPerformance/NativePerformance.cpp | 11 +++++ Libraries/WebPerformance/NativePerformance.h | 13 ++++++ Libraries/WebPerformance/NativePerformance.js | 3 ++ Libraries/WebPerformance/Performance.js | 30 +++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 Libraries/WebPerformance/MemoryInfo.js diff --git a/Libraries/WebPerformance/MemoryInfo.js b/Libraries/WebPerformance/MemoryInfo.js new file mode 100644 index 00000000000000..fb469514e0478c --- /dev/null +++ b/Libraries/WebPerformance/MemoryInfo.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + * @oncall react_native + */ + +// flowlint unsafe-getters-setters:off + +export type MemoryInfoLike = { + jsHeapSizeLimit: ?number, + totalJSHeapSize: ?number, + usedJSHeapSize: ?number, +}; + +// Read-only object with JS memory information. This is returned by the performance.memory API. +export default class MemoryInfo { + _jsHeapSizeLimit: ?number; + _totalJSHeapSize: ?number; + _usedJSHeapSize: ?number; + + constructor(memoryInfo: ?MemoryInfoLike) { + if (memoryInfo != null) { + this._jsHeapSizeLimit = memoryInfo.jsHeapSizeLimit; + this._totalJSHeapSize = memoryInfo.totalJSHeapSize; + this._usedJSHeapSize = memoryInfo.usedJSHeapSize; + } + } + + get jsHeapSizeLimit(): ?number { + return this._jsHeapSizeLimit; + } + + get totalJSHeapSize(): ?number { + return this._totalJSHeapSize; + } + + get usedJSHeapSize(): ?number { + return this._usedJSHeapSize; + } +} diff --git a/Libraries/WebPerformance/NativePerformance.cpp b/Libraries/WebPerformance/NativePerformance.cpp index 51db30395df4e8..94b0f4c5413a07 100644 --- a/Libraries/WebPerformance/NativePerformance.cpp +++ b/Libraries/WebPerformance/NativePerformance.cpp @@ -7,6 +7,7 @@ #include "NativePerformance.h" #include +#include #include "PerformanceEntryReporter.h" namespace facebook::react { @@ -46,4 +47,14 @@ void NativePerformance::clearMeasures( PerformanceEntryReporter::getInstance().clearMeasures(measureName); } +std::unordered_map NativePerformance::getSimpleMemoryInfo( + jsi::Runtime &rt) { + auto heapInfo = rt.instrumentation().getHeapInfo(false); + std::unordered_map heapInfoToJs; + for (auto &entry : heapInfo) { + heapInfoToJs[entry.first] = static_cast(entry.second); + } + return heapInfoToJs; +} + } // namespace facebook::react diff --git a/Libraries/WebPerformance/NativePerformance.h b/Libraries/WebPerformance/NativePerformance.h index 7078f50a943143..06a18da5f9534e 100644 --- a/Libraries/WebPerformance/NativePerformance.h +++ b/Libraries/WebPerformance/NativePerformance.h @@ -39,6 +39,19 @@ class NativePerformance : public NativePerformanceCxxSpec, std::optional endMark); void clearMeasures(jsi::Runtime &rt, std::optional measureName); + // To align with web API, we will make sure to return three properties + // (jsHeapSizeLimit, totalJSHeapSize, usedJSHeapSize) + anything needed from + // the VM side. + // `jsHeapSizeLimit`: The maximum size of the heap, in bytes, that + // is available to the context. + // `totalJSHeapSize`: The total allocated heap size, in bytes. + // `usedJSHeapSize`: The currently active segment of JS heap, in + // bytes. + // + // Note that we use int64_t here and it's ok to lose precision in JS doubles + // for heap size information, as double's 2^53 sig bytes is large enough. + std::unordered_map getSimpleMemoryInfo(jsi::Runtime &rt); + private: }; diff --git a/Libraries/WebPerformance/NativePerformance.js b/Libraries/WebPerformance/NativePerformance.js index 85435b4799750c..f25954d9c235ad 100644 --- a/Libraries/WebPerformance/NativePerformance.js +++ b/Libraries/WebPerformance/NativePerformance.js @@ -12,6 +12,8 @@ import type {TurboModule} from '../TurboModule/RCTExport'; import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry'; +export type NativeMemoryInfo = {[key: string]: number}; + export interface Spec extends TurboModule { +mark: (name: string, startTime: number, duration: number) => void; +clearMarks: (markName?: string) => void; @@ -25,6 +27,7 @@ export interface Spec extends TurboModule { endMark?: string, ) => void; +clearMeasures: (measureName?: string) => void; + +getSimpleMemoryInfo: () => NativeMemoryInfo; } export default (TurboModuleRegistry.get('NativePerformanceCxx'): ?Spec); diff --git a/Libraries/WebPerformance/Performance.js b/Libraries/WebPerformance/Performance.js index 0c8ffb700d8a80..81ded123bc2d8e 100644 --- a/Libraries/WebPerformance/Performance.js +++ b/Libraries/WebPerformance/Performance.js @@ -8,9 +8,12 @@ * @flow strict */ +// flowlint unsafe-getters-setters:off + import type {HighResTimeStamp} from './PerformanceEntry'; import warnOnce from '../Utilities/warnOnce'; +import MemoryInfo from './MemoryInfo'; import NativePerformance from './NativePerformance'; import {PerformanceEntry} from './PerformanceEntry'; @@ -86,6 +89,33 @@ function warnNoNativePerformance() { * https://www.w3.org/TR/user-timing/#extensions-performance-interface */ export default class Performance { + // Get the current JS memory information. + get memory(): MemoryInfo { + if (NativePerformance?.getSimpleMemoryInfo) { + // JSI API implementations may have different variants of names for the JS + // heap information we need here. We will parse the result based on our + // guess of the implementation for now. + const memoryInfo = NativePerformance.getSimpleMemoryInfo(); + if (memoryInfo.hasOwnProperty('hermes_heapSize')) { + // We got memory information from Hermes + const {hermes_heapSize, hermes_allocatedBytes} = memoryInfo; + const totalJSHeapSize = Number(hermes_heapSize); + const usedJSHeapSize = Number(hermes_allocatedBytes); + + return new MemoryInfo({ + jsHeapSizeLimit: null, // We don't know the heap size limit from Hermes. + totalJSHeapSize: isNaN(totalJSHeapSize) ? null : totalJSHeapSize, + usedJSHeapSize: isNaN(usedJSHeapSize) ? null : usedJSHeapSize, + }); + } else { + // JSC and V8 has no native implementations for memory information in JSI::Instrumentation + return new MemoryInfo(); + } + } + + return new MemoryInfo(); + } + mark( markName: string, markOptions?: PerformanceMarkOptions, From 40c687c132ffc75f9db7dd4c42378ba676da2ea1 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 16 Feb 2023 04:38:36 -0800 Subject: [PATCH 33/81] Allow for Android offline mirrors to be executed on developer's laptops Summary: Before this change, the only way to update the offline mirror was to run it on a devmachine (OD won't work either due to network restriction). Developer's laptop also won't work as they would download AAPT2 for MacOS. In the offline mirror instead we need AAPT2 for Linux as that's Sandcastle runner type. This relaxes this requirement so the next time a developer has to update the offline mirror they will see the message on the diff with the command to execute, and they should be able to run the command locally (or on their devbox). Changelog: [Internal] [Changed] - Allow for Android offline mirrors to be executed on developer's laptops allow-large-files Reviewed By: cipolleschi Differential Revision: D43344651 fbshipit-source-id: 3e91adb2db45cf94d3f947aaab501d98580dc43d --- ReactAndroid/build.gradle | 6 ++++++ build.gradle.kts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 56bacf0b9b7965..bcc8cda5aff8c5 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -670,6 +670,12 @@ dependencies { androidTestImplementation("androidx.test:runner:${ANDROIDX_TEST_VERSION}") androidTestImplementation("androidx.test:rules:${ANDROIDX_TEST_VERSION}") androidTestImplementation("org.mockito:mockito-core:${MOCKITO_CORE_VERSION}") + + // This compileOnly dependency is needed to be able to update the offline + // mirror from a non-linux machine, while still executing inside a Linux CI + // as we declare a dependency on aap2 @linux so we're sure the linux artifact + // gets downloaded at some point. + compileOnly("com.android.tools.build:aapt2:7.4.1-8841542:linux") } react { diff --git a/build.gradle.kts b/build.gradle.kts index 9c6fad7ae4fb22..e9b1924d538c2f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -91,6 +91,8 @@ tasks.register("downloadAll") { dependsOn(":ReactAndroid:androidDependencies") dependsOn(":ReactAndroid:hermes-engine:dependencies") dependsOn(":ReactAndroid:hermes-engine:androidDependencies") + dependsOn(":packages:rn-tester:android:app:dependencies") + dependsOn(":packages:rn-tester:android:app:androidDependencies") } tasks.register("publishAllInsideNpmPackage") { From 8486e191a170d9eae4d1d628a7539dc9e3d13ea4 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 16 Feb 2023 06:03:01 -0800 Subject: [PATCH 34/81] Address New Architecture performance regressions by properly setting NDEBUG (#36172) Summary: It looks like we're not properly setting `NDEBUG` for "non debug" builds with CMake (the name is terrible but that's what Buck uses originally). This configures `NDEBUG` correctly so that is set only for release variants, so that also `REACT_NATIVE_DEBUG` is set correctly (and we don't fire asserts on release builds). This should address several performance regression we saw for New Architecture on some release scenarios (credits to sammy-SC for spotting it). ## Changelog [ANDROID] [FIXED] - Address New Architecture performance regressions by properly setting NDEBUG Pull Request resolved: https://github.com/facebook/react-native/pull/36172 Test Plan: I've tested this by checking the ninja output for the debug/release builds for the `YogaLayoutableShadowNode.cpp` file ### Debug (does not contain `-DNDEBUG`) ``` build ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir/YogaLayoutableShadowNode.cpp.o: CXX_COMPILER__rrc_view_Debug /Users/ncor/git/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp || cmake_object_order_depends_target_rrc_view DEFINES = -Drrc_view_EXPORTS DEP_FILE = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir/YogaLayoutableShadowNode.cpp.o.d FLAGS = -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fexceptions -frtti -stdlib=libc++ -g -fno-limit-debug-info -fPIC -Wall -Werror -std=c++17 -fexceptions -frtti -Wpedantic -Wno-gnu-zero-variadic-macro-arguments -DLOG_TAG=\"Fabric\" -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_MOBILE=1 -DFOLLY_HAVE_RECVMMSG=1 -DFOLLY_HAVE_PTHREAD=1 -DFOLLY_HAVE_XSI_STRERROR_R=1 INCLUDES = -I/Users/ncor/git/react-native/ReactCommon -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/folly/. -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/glog/exported -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/double-conversion/. -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/boost/boost_1_76_0 -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/fmt/include -I/Users/ncor/git/react-native/ReactAndroid/src/main/jni/first-party/fbgloginit/. -I/Users/ncor/git/react-native/ReactCommon/jsi -I/Users/ncor/git/react-native/ReactCommon/logger/. -I/Users/ncor/git/react-native/ReactCommon/react/renderer/graphics/platform/android -I/Users/ncor/git/react-native/ReactAndroid/src/main/jni/first-party/fb/include -I/Users/ncor/git/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni -I/Users/ncor/git/react-native/ReactCommon/yoga/. -isystem /Users/ncor/.gradle/caches/transforms-3/ebdfaf25aad9044f80de924d25488688/transformed/fbjni-0.3.0/prefab/modules/fbjni/include OBJECT_DIR = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir OBJECT_FILE_DIR = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir TARGET_COMPILE_PDB = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir/ TARGET_PDB = /Users/ncor/git/react-native/ReactAndroid/build/intermediates/cxx/Debug/193k1y15/obj/arm64-v8a/librrc_view.pdb ``` ### Release (does contain `-DNDEBUG`) ``` build ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir/YogaLayoutableShadowNode.cpp.o: CXX_COMPILER__rrc_view_RelWithDebInfo /Users/ncor/git/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp || cmake_object_order_depends_target_rrc_view DEFINES = -Drrc_view_EXPORTS DEP_FILE = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir/YogaLayoutableShadowNode.cpp.o.d FLAGS = -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fexceptions -frtti -stdlib=libc++ -O2 -g -DNDEBUG -fPIC -Wall -Werror -std=c++17 -fexceptions -frtti -Wpedantic -Wno-gnu-zero-variadic-macro-arguments -DLOG_TAG=\"Fabric\" -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_MOBILE=1 -DFOLLY_HAVE_RECVMMSG=1 -DFOLLY_HAVE_PTHREAD=1 -DFOLLY_HAVE_XSI_STRERROR_R=1 INCLUDES = -I/Users/ncor/git/react-native/ReactCommon -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/folly/. -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/glog/exported -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/double-conversion/. -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/boost/boost_1_76_0 -I/Users/ncor/git/react-native/ReactAndroid/build/third-party-ndk/fmt/include -I/Users/ncor/git/react-native/ReactAndroid/src/main/jni/first-party/fbgloginit/. -I/Users/ncor/git/react-native/ReactCommon/jsi -I/Users/ncor/git/react-native/ReactCommon/logger/. -I/Users/ncor/git/react-native/ReactCommon/react/renderer/graphics/platform/android -I/Users/ncor/git/react-native/ReactAndroid/src/main/jni/first-party/fb/include -I/Users/ncor/git/react-native/ReactAndroid/src/main/jni/first-party/yogajni/jni -I/Users/ncor/git/react-native/ReactCommon/yoga/. -isystem /Users/ncor/.gradle/caches/transforms-3/ebdfaf25aad9044f80de924d25488688/transformed/fbjni-0.3.0/prefab/modules/fbjni/include OBJECT_DIR = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir OBJECT_FILE_DIR = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir TARGET_COMPILE_PDB = ReactCommon/react/renderer/components/view/CMakeFiles/rrc_view.dir/ TARGET_PDB = /Users/ncor/git/react-native/ReactAndroid/build/intermediates/cxx/RelWithDebInfo/53pv2v65/obj/arm64-v8a/librrc_view.pdb ``` Reviewed By: sammy-SC, cipolleschi Differential Revision: D43344120 Pulled By: cortinico fbshipit-source-id: e0567aec2742c5dab2d008cdcf198f34d5626b65 --- ReactAndroid/src/main/jni/first-party/fb/CMakeLists.txt | 3 +++ ReactCommon/hermes/executor/CMakeLists.txt | 6 ++++++ ReactCommon/jsc/CMakeLists.txt | 4 ++++ ReactCommon/react/debug/CMakeLists.txt | 4 ++++ ReactCommon/react/debug/flags.h | 4 +++- 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/jni/first-party/fb/CMakeLists.txt b/ReactAndroid/src/main/jni/first-party/fb/CMakeLists.txt index 7319e832fcff96..c3e3ecebbbd75b 100644 --- a/ReactAndroid/src/main/jni/first-party/fb/CMakeLists.txt +++ b/ReactAndroid/src/main/jni/first-party/fb/CMakeLists.txt @@ -21,6 +21,9 @@ add_compile_options( -Wno-error=unused-but-set-variable -DHAVE_POSIX_CLOCKS ) +if(${CMAKE_BUILD_TYPE} MATCHES Release) + add_compile_options(-DNDEBUG) +endif() # Yogacore needs to link towards android and log from the NDK libs target_link_libraries(fb dl android log) diff --git a/ReactCommon/hermes/executor/CMakeLists.txt b/ReactCommon/hermes/executor/CMakeLists.txt index de74c65daea888..f63bd1e7d04f62 100644 --- a/ReactCommon/hermes/executor/CMakeLists.txt +++ b/ReactCommon/hermes/executor/CMakeLists.txt @@ -28,4 +28,10 @@ if(${CMAKE_BUILD_TYPE} MATCHES Debug) PRIVATE -DHERMES_ENABLE_DEBUGGER=1 ) +else() + target_compile_options( + hermes_executor_common + PRIVATE + -DNDEBUG + ) endif() diff --git a/ReactCommon/jsc/CMakeLists.txt b/ReactCommon/jsc/CMakeLists.txt index 2f387fa996f644..5db3ff62a01bbc 100644 --- a/ReactCommon/jsc/CMakeLists.txt +++ b/ReactCommon/jsc/CMakeLists.txt @@ -33,3 +33,7 @@ target_link_libraries(jscruntime # TODO: Remove this flag when ready. # Android has this enabled by default, but the flag is still needed for iOS. target_compile_options(jscruntime PRIVATE -DRN_FABRIC_ENABLED) + +if(${CMAKE_BUILD_TYPE} MATCHES Release) + target_compile_options(jscruntime PRIVATE -DNDEBUG) +endif() diff --git a/ReactCommon/react/debug/CMakeLists.txt b/ReactCommon/react/debug/CMakeLists.txt index 620a1c54392c8c..ccfc69872e7340 100644 --- a/ReactCommon/react/debug/CMakeLists.txt +++ b/ReactCommon/react/debug/CMakeLists.txt @@ -22,3 +22,7 @@ add_library(react_debug SHARED ${react_debug_SRC}) target_include_directories(react_debug PUBLIC ${REACT_COMMON_DIR}) target_link_libraries(react_debug log folly_runtime) + +if(${CMAKE_BUILD_TYPE} MATCHES Release) + target_compile_options(react_debug PUBLIC -DNDEBUG) +endif() diff --git a/ReactCommon/react/debug/flags.h b/ReactCommon/react/debug/flags.h index 62d1cc445746a1..dae3ecc4e51f81 100644 --- a/ReactCommon/react/debug/flags.h +++ b/ReactCommon/react/debug/flags.h @@ -10,7 +10,9 @@ // // Enable REACT_NATIVE_DEBUG if NDEBUG is not defined. // Due to BUCK defaults in open-source, NDEBUG is always defined for all android -// builds (if you build without BUCK, this isn't an issue). Thus we introduce +// builds. +// If you build in OSS with CMake, you will have -DNDEBUG set only for release +// builds, therefore REACT_NATIVE_DEBUG will not be set. Here we introduce // REACT_NATIVE_DEBUG that we use internally instead of NDEBUG that we can // control and use as a more reliable xplat flag. For any build that doesn't // have NDEBUG defined, we enable REACT_NATIVE_DEBUG for convenience. From 581357bc9bbb868f0c4ae7118980def19429b5ee Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Thu, 16 Feb 2023 06:21:43 -0800 Subject: [PATCH 35/81] Implement EventCounts Web Performance API for React Native (#36181) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36181 [Changelog][Internal] Implements EventCounts API (`Performance.eventCounts`) for Web Performance, according to the W3C standard, see the specs here: https://www.w3.org/TR/event-timing/#eventcounts The rationale for why we need it is to support some advanced metrics computations, such as a ratio of "slow events" to total event count, per event type. Reviewed By: rubennorte Differential Revision: D43285073 fbshipit-source-id: 2c53d04d9a57c1301e37f2a5879072c8d33efbbf --- Libraries/WebPerformance/EventCounts.js | 78 ++++++++++++ .../NativePerformanceObserver.cpp | 8 ++ .../NativePerformanceObserver.h | 3 + .../NativePerformanceObserver.js | 2 + Libraries/WebPerformance/Performance.js | 5 +- .../PerformanceEntryReporter.cpp | 7 +- .../WebPerformance/PerformanceEntryReporter.h | 5 + .../WebPerformance/PerformanceObserver.js | 2 +- .../__mocks__/NativePerformanceObserver.js | 10 ++ .../__tests__/EventCounts-test.js | 116 ++++++++++++++++++ 10 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 Libraries/WebPerformance/EventCounts.js create mode 100644 Libraries/WebPerformance/__tests__/EventCounts-test.js diff --git a/Libraries/WebPerformance/EventCounts.js b/Libraries/WebPerformance/EventCounts.js new file mode 100644 index 00000000000000..27ece857093b23 --- /dev/null +++ b/Libraries/WebPerformance/EventCounts.js @@ -0,0 +1,78 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import NativePerformanceObserver from './NativePerformanceObserver'; +import {warnNoNativePerformanceObserver} from './PerformanceObserver'; + +type EventCountsForEachCallbackType = + | (() => void) + | ((value: number) => void) + | ((value: number, key: string) => void) + | ((value: number, key: string, map: Map) => void); + +let cachedEventCounts: ?Map; + +function getCachedEventCounts(): Map { + if (cachedEventCounts) { + return cachedEventCounts; + } + if (!NativePerformanceObserver) { + warnNoNativePerformanceObserver(); + return new Map(); + } + + cachedEventCounts = new Map( + NativePerformanceObserver.getEventCounts(), + ); + // $FlowFixMe[incompatible-call] + global.queueMicrotask(() => { + // To be consistent with the calls to the API from the same task, + // but also not to refetch the data from native too often, + // schedule to invalidate the cache later, + // after the current task is guaranteed to have finished. + cachedEventCounts = null; + }); + return cachedEventCounts ?? new Map(); +} +/** + * Implementation of the EventCounts Web Performance API + * corresponding to the standard in + * https://www.w3.org/TR/event-timing/#eventcounts + */ +export default class EventCounts { + // flowlint unsafe-getters-setters:off + get size(): number { + return getCachedEventCounts().size; + } + + entries(): Iterator<[string, number]> { + return getCachedEventCounts().entries(); + } + + forEach(callback: EventCountsForEachCallbackType): void { + return getCachedEventCounts().forEach(callback); + } + + get(key: string): ?number { + return getCachedEventCounts().get(key); + } + + has(key: string): boolean { + return getCachedEventCounts().has(key); + } + + keys(): Iterator { + return getCachedEventCounts().keys(); + } + + values(): Iterator { + return getCachedEventCounts().values(); + } +} diff --git a/Libraries/WebPerformance/NativePerformanceObserver.cpp b/Libraries/WebPerformance/NativePerformanceObserver.cpp index c1b6265536b31f..e0701acfe6a477 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.cpp +++ b/Libraries/WebPerformance/NativePerformanceObserver.cpp @@ -51,4 +51,12 @@ void NativePerformanceObserver::logRawEntry( PerformanceEntryReporter::getInstance().logEntry(entry); } +std::vector> +NativePerformanceObserver::getEventCounts(jsi::Runtime &rt) { + const auto &eventCounts = + PerformanceEntryReporter::getInstance().getEventCounts(); + return std::vector>( + eventCounts.begin(), eventCounts.end()); +} + } // namespace facebook::react diff --git a/Libraries/WebPerformance/NativePerformanceObserver.h b/Libraries/WebPerformance/NativePerformanceObserver.h index 5305a6ce35b91c..5254628d460fdc 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.h +++ b/Libraries/WebPerformance/NativePerformanceObserver.h @@ -71,6 +71,9 @@ class NativePerformanceObserver void logRawEntry(jsi::Runtime &rt, RawPerformanceEntry entry); + std::vector> getEventCounts( + jsi::Runtime &rt); + private: }; diff --git a/Libraries/WebPerformance/NativePerformanceObserver.js b/Libraries/WebPerformance/NativePerformanceObserver.js index 4af889249a797a..964c4e999330ea 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.js +++ b/Libraries/WebPerformance/NativePerformanceObserver.js @@ -35,6 +35,8 @@ export interface Spec extends TurboModule { +stopReporting: (entryType: RawPerformanceEntryType) => void; +popPendingEntries: () => GetPendingEntriesResult; +setOnPerformanceEntryCallback: (callback?: () => void) => void; + +logRawEntry: (entry: RawPerformanceEntry) => void; + +getEventCounts: () => $ReadOnlyArray<[string, number]>; } export default (TurboModuleRegistry.get( diff --git a/Libraries/WebPerformance/Performance.js b/Libraries/WebPerformance/Performance.js index 81ded123bc2d8e..07c1872b6f363d 100644 --- a/Libraries/WebPerformance/Performance.js +++ b/Libraries/WebPerformance/Performance.js @@ -13,6 +13,7 @@ import type {HighResTimeStamp} from './PerformanceEntry'; import warnOnce from '../Utilities/warnOnce'; +import EventCounts from './EventCounts'; import MemoryInfo from './MemoryInfo'; import NativePerformance from './NativePerformance'; import {PerformanceEntry} from './PerformanceEntry'; @@ -86,9 +87,11 @@ function warnNoNativePerformance() { /** * Partial implementation of the Performance interface for RN, * corresponding to the standard in - * https://www.w3.org/TR/user-timing/#extensions-performance-interface + * https://www.w3.org/TR/user-timing/#extensions-performance-interface */ export default class Performance { + eventCounts: EventCounts = new EventCounts(); + // Get the current JS memory information. get memory(): MemoryInfo { if (NativePerformance?.getSimpleMemoryInfo) { diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.cpp b/Libraries/WebPerformance/PerformanceEntryReporter.cpp index 2cee8e6716944d..7c524ae0ec1d8d 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.cpp +++ b/Libraries/WebPerformance/PerformanceEntryReporter.cpp @@ -47,7 +47,12 @@ GetPendingEntriesResult PerformanceEntryReporter::popPendingEntries() { } void PerformanceEntryReporter::logEntry(const RawPerformanceEntry &entry) { - if (!isReportingType(static_cast(entry.entryType))) { + const auto entryType = static_cast(entry.entryType); + if (entryType == PerformanceEntryType::EVENT) { + eventCounts_[entry.name]++; + } + + if (!isReportingType(entryType)) { return; } diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.h b/Libraries/WebPerformance/PerformanceEntryReporter.h index 5a0cd35c7c1f03..655f58ceab3a8b 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.h +++ b/Libraries/WebPerformance/PerformanceEntryReporter.h @@ -102,6 +102,10 @@ class PerformanceEntryReporter : public EventLogger { void onEventDispatch(EventTag tag) override; void onEventEnd(EventTag tag) override; + const std::unordered_map &getEventCounts() const { + return eventCounts_; + } + private: PerformanceEntryReporter() {} @@ -117,6 +121,7 @@ class PerformanceEntryReporter : public EventLogger { std::vector entries_; std::mutex entriesMutex_; std::array reportingType_{false}; + std::unordered_map eventCounts_; // Mark registry for "measure" lookup PerformanceMarkRegistryType marksRegistry_; diff --git a/Libraries/WebPerformance/PerformanceObserver.js b/Libraries/WebPerformance/PerformanceObserver.js index 9f47ec7d5135d8..ca7d081a0f8935 100644 --- a/Libraries/WebPerformance/PerformanceObserver.js +++ b/Libraries/WebPerformance/PerformanceObserver.js @@ -98,7 +98,7 @@ const onPerformanceEntry = () => { } }; -function warnNoNativePerformanceObserver() { +export function warnNoNativePerformanceObserver() { warnOnce( 'missing-native-performance-observer', 'Missing native implementation of PerformanceObserver', diff --git a/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js b/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js index 617a9122196755..4379e30ab1d23c 100644 --- a/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js +++ b/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js @@ -15,7 +15,10 @@ import type { Spec as NativePerformanceObserver, } from '../NativePerformanceObserver'; +import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; + const reportingType: Set = new Set(); +const eventCounts: Map = new Map(); let entries: Array = []; let onPerformanceEntryCallback: ?() => void; @@ -50,6 +53,13 @@ const NativePerformanceObserverMock: NativePerformanceObserver = { onPerformanceEntryCallback?.(); }); } + if (entry.entryType === RawPerformanceEntryTypeValues.EVENT) { + eventCounts.set(entry.name, (eventCounts.get(entry.name) ?? 0) + 1); + } + }, + + getEventCounts: (): $ReadOnlyArray<[string, number]> => { + return Array.from(eventCounts.entries()); }, }; diff --git a/Libraries/WebPerformance/__tests__/EventCounts-test.js b/Libraries/WebPerformance/__tests__/EventCounts-test.js new file mode 100644 index 00000000000000..7be1b9c1fd8c45 --- /dev/null +++ b/Libraries/WebPerformance/__tests__/EventCounts-test.js @@ -0,0 +1,116 @@ +/** + * 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 + * @oncall react_native + */ + +import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; + +// NOTE: Jest mocks of transitive dependencies don't appear to work with +// ES6 module imports, therefore forced to use commonjs style imports here. +const NativePerformanceObserver = require('../NativePerformanceObserver'); +const Performance = require('../Performance').default; + +jest.mock( + '../NativePerformanceObserver', + () => require('../__mocks__/NativePerformanceObserver').default, +); + +describe('EventCounts', () => { + it('defines EventCounts for Performance', () => { + const eventCounts = new Performance().eventCounts; + expect(eventCounts).not.toBeUndefined(); + }); + + it('consistently implements the API for EventCounts', async () => { + NativePerformanceObserver.logRawEntry({ + name: 'click', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'input', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'input', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'keyup', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'keyup', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'keyup', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + const eventCounts = new Performance().eventCounts; + expect(eventCounts.size).toBe(3); + expect(Array.from(eventCounts.entries())).toStrictEqual([ + ['click', 1], + ['input', 2], + ['keyup', 3], + ]); + + expect(eventCounts.get('click')).toEqual(1); + expect(eventCounts.get('input')).toEqual(2); + expect(eventCounts.get('keyup')).toEqual(3); + + expect(eventCounts.has('click')).toEqual(true); + expect(eventCounts.has('input')).toEqual(true); + expect(eventCounts.has('keyup')).toEqual(true); + + expect(Array.from(eventCounts.keys())).toStrictEqual([ + 'click', + 'input', + 'keyup', + ]); + expect(Array.from(eventCounts.values())).toStrictEqual([1, 2, 3]); + + await jest.runAllTicks(); + NativePerformanceObserver.logRawEntry({ + name: 'input', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'keyup', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'keyup', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + expect(Array.from(eventCounts.values())).toStrictEqual([1, 3, 5]); + + await jest.runAllTicks(); + + NativePerformanceObserver.logRawEntry({ + name: 'click', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + await jest.runAllTicks(); + + NativePerformanceObserver.logRawEntry({ + name: 'keyup', + entryType: RawPerformanceEntryTypeValues.EVENT, + }); + + expect(Array.from(eventCounts.values())).toStrictEqual([2, 3, 6]); + }); +}); From cf194aebfed8c349c6432a5996233a8c1e5cee8f Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Thu, 16 Feb 2023 06:21:43 -0800 Subject: [PATCH 36/81] Implement durationThreshold option for PerformanceObserver (#36152) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36152 [Changelog][Internal] By [the W3C standard](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver/observe), `PerformanceObserver.observer` can optionally take a `durationThreshold` option, so that only entries with duration larger than the threshold are reported. This diff adds support for this on the RN side, as well as unit tests for this feature on the JS side. NOTE: The standard suggests that default value for this is 104s. I left it at 0 for now, as for the RN use cases t may be to too high (needs discussion). Reviewed By: rubennorte Differential Revision: D43154319 fbshipit-source-id: 0f9d435506f48d8e8521e408211347e8391d22fc --- .../NativePerformanceObserver.cpp | 8 + .../NativePerformanceObserver.h | 5 + .../NativePerformanceObserver.js | 4 + .../PerformanceEntryReporter.cpp | 16 +- .../WebPerformance/PerformanceEntryReporter.h | 7 + .../WebPerformance/PerformanceObserver.js | 83 +++++++-- .../__mocks__/NativePerformanceObserver.js | 16 ++ .../__tests__/PerformanceObserver-test.js | 159 ++++++++++++++++++ 8 files changed, 281 insertions(+), 17 deletions(-) diff --git a/Libraries/WebPerformance/NativePerformanceObserver.cpp b/Libraries/WebPerformance/NativePerformanceObserver.cpp index e0701acfe6a477..200140fdae1e6b 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.cpp +++ b/Libraries/WebPerformance/NativePerformanceObserver.cpp @@ -59,4 +59,12 @@ NativePerformanceObserver::getEventCounts(jsi::Runtime &rt) { eventCounts.begin(), eventCounts.end()); } +void NativePerformanceObserver::setDurationThreshold( + jsi::Runtime &rt, + int32_t entryType, + double durationThreshold) { + PerformanceEntryReporter::getInstance().setDurationThreshold( + static_cast(entryType), durationThreshold); +} + } // namespace facebook::react diff --git a/Libraries/WebPerformance/NativePerformanceObserver.h b/Libraries/WebPerformance/NativePerformanceObserver.h index 5254628d460fdc..577bdee0f73e8a 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.h +++ b/Libraries/WebPerformance/NativePerformanceObserver.h @@ -74,6 +74,11 @@ class NativePerformanceObserver std::vector> getEventCounts( jsi::Runtime &rt); + void setDurationThreshold( + jsi::Runtime &rt, + int32_t entryType, + double durationThreshold); + private: }; diff --git a/Libraries/WebPerformance/NativePerformanceObserver.js b/Libraries/WebPerformance/NativePerformanceObserver.js index 964c4e999330ea..86634b60213566 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.js +++ b/Libraries/WebPerformance/NativePerformanceObserver.js @@ -37,6 +37,10 @@ export interface Spec extends TurboModule { +setOnPerformanceEntryCallback: (callback?: () => void) => void; +logRawEntry: (entry: RawPerformanceEntry) => void; +getEventCounts: () => $ReadOnlyArray<[string, number]>; + +setDurationThreshold: ( + entryType: RawPerformanceEntryType, + durationThreshold: number, + ) => void; } export default (TurboModuleRegistry.get( diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.cpp b/Libraries/WebPerformance/PerformanceEntryReporter.cpp index 7c524ae0ec1d8d..a741857de946c9 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.cpp +++ b/Libraries/WebPerformance/PerformanceEntryReporter.cpp @@ -31,8 +31,17 @@ void PerformanceEntryReporter::setReportingCallback( } void PerformanceEntryReporter::startReporting(PerformanceEntryType entryType) { - reportingType_[static_cast(entryType)] = true; + int entryTypeIdx = static_cast(entryType); + reportingType_[entryTypeIdx] = true; + durationThreshold_[entryTypeIdx] = DEFAULT_DURATION_THRESHOLD; } + +void PerformanceEntryReporter::setDurationThreshold( + PerformanceEntryType entryType, + double durationThreshold) { + durationThreshold_[static_cast(entryType)] = durationThreshold; +} + void PerformanceEntryReporter::stopReporting(PerformanceEntryType entryType) { reportingType_[static_cast(entryType)] = false; } @@ -56,6 +65,11 @@ void PerformanceEntryReporter::logEntry(const RawPerformanceEntry &entry) { return; } + if (entry.duration < durationThreshold_[entry.entryType]) { + // The entries duration is lower than the desired reporting threshold, skip + return; + } + std::lock_guard lock(entriesMutex_); if (entries_.size() == MAX_ENTRY_BUFFER_SIZE) { diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.h b/Libraries/WebPerformance/PerformanceEntryReporter.h index 655f58ceab3a8b..721a9ac6984980 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.h +++ b/Libraries/WebPerformance/PerformanceEntryReporter.h @@ -44,6 +44,8 @@ using PerformanceMarkRegistryType = std:: // memory for the sake of the "Performance.measure" mark name lookup constexpr size_t MARKS_BUFFER_SIZE = 1024; +constexpr double DEFAULT_DURATION_THRESHOLD = 0.0; + enum class PerformanceEntryType { UNDEFINED = 0, MARK = 1, @@ -66,6 +68,9 @@ class PerformanceEntryReporter : public EventLogger { void setReportingCallback(std::optional> callback); void startReporting(PerformanceEntryType entryType); void stopReporting(PerformanceEntryType entryType); + void setDurationThreshold( + PerformanceEntryType entryType, + double durationThreshold); GetPendingEntriesResult popPendingEntries(); void logEntry(const RawPerformanceEntry &entry); @@ -122,6 +127,8 @@ class PerformanceEntryReporter : public EventLogger { std::mutex entriesMutex_; std::array reportingType_{false}; std::unordered_map eventCounts_; + std::array durationThreshold_{ + DEFAULT_DURATION_THRESHOLD}; // Mark registry for "measure" lookup PerformanceMarkRegistryType marksRegistry_; diff --git a/Libraries/WebPerformance/PerformanceObserver.js b/Libraries/WebPerformance/PerformanceObserver.js index ca7d081a0f8935..776c9f0ced1e60 100644 --- a/Libraries/WebPerformance/PerformanceObserver.js +++ b/Libraries/WebPerformance/PerformanceObserver.js @@ -8,7 +8,7 @@ * @flow strict */ -import type {PerformanceEntryType} from './PerformanceEntry'; +import type {HighResTimeStamp, PerformanceEntryType} from './PerformanceEntry'; import warnOnce from '../Utilities/warnOnce'; import NativePerformanceObserver from './NativePerformanceObserver'; @@ -62,11 +62,13 @@ export type PerformanceObserverInit = } | { type: PerformanceEntryType, + durationThreshold?: HighResTimeStamp, }; type PerformanceObserverConfig = {| callback: PerformanceObserverCallback, - entryTypes: $ReadOnlySet, + // Map of {entryType: durationThreshold} + entryTypes: $ReadOnlyMap, |}; const observerCountPerEntryType: Map = new Map(); @@ -87,9 +89,13 @@ const onPerformanceEntry = () => { } const entries = rawEntries.map(rawToPerformanceEntry); for (const [observer, observerConfig] of registeredObservers.entries()) { - const entriesForObserver: PerformanceEntryList = entries.filter( - entry => observerConfig.entryTypes.has(entry.entryType) !== -1, - ); + const entriesForObserver: PerformanceEntryList = entries.filter(entry => { + if (!observerConfig.entryTypes.has(entry.entryType)) { + return false; + } + const durationThreshold = observerConfig.entryTypes.get(entry.entryType); + return entry.duration >= (durationThreshold ?? 0); + }); observerConfig.callback( new PerformanceObserverEntryList(entriesForObserver), observer, @@ -105,6 +111,24 @@ export function warnNoNativePerformanceObserver() { ); } +function applyDurationThresholds() { + const durationThresholds: Map = Array.from( + registeredObservers.values(), + ) + .map(config => config.entryTypes) + .reduce( + (accumulator, currentValue) => union(accumulator, currentValue), + new Map(), + ); + + for (const [entryType, durationThreshold] of durationThresholds) { + NativePerformanceObserver?.setDurationThreshold( + performanceEntryTypeToRaw(entryType), + durationThreshold ?? 0, + ); + } +} + /** * Implementation of the PerformanceObserver interface for RN, * corresponding to the standard in https://www.w3.org/TR/performance-timeline/ @@ -145,10 +169,14 @@ export default class PerformanceObserver { if (options.entryTypes) { this._type = 'multiple'; - requestedEntryTypes = new Set(options.entryTypes); + requestedEntryTypes = new Map( + options.entryTypes.map(t => [t, undefined]), + ); } else { this._type = 'single'; - requestedEntryTypes = new Set([options.type]); + requestedEntryTypes = new Map([ + [options.type, options.durationThreshold], + ]); } // The same observer may receive multiple calls to "observe", so we need @@ -178,19 +206,22 @@ export default class PerformanceObserver { // We only need to start listenening to new entry types being observed in // this observer. const newEntryTypes = currentEntryTypes - ? difference(requestedEntryTypes, currentEntryTypes) - : requestedEntryTypes; + ? difference( + new Set(requestedEntryTypes.keys()), + new Set(currentEntryTypes.keys()), + ) + : new Set(requestedEntryTypes.keys()); for (const type of newEntryTypes) { if (!observerCountPerEntryType.has(type)) { - NativePerformanceObserver.startReporting( - performanceEntryTypeToRaw(type), - ); + const rawType = performanceEntryTypeToRaw(type); + NativePerformanceObserver.startReporting(rawType); } observerCountPerEntryType.set( type, (observerCountPerEntryType.get(type) ?? 0) + 1, ); } + applyDurationThresholds(); } disconnect(): void { @@ -205,7 +236,7 @@ export default class PerformanceObserver { } // Disconnect this observer - for (const type of observerConfig.entryTypes) { + for (const type of observerConfig.entryTypes.keys()) { const numberOfObserversForThisType = observerCountPerEntryType.get(type) ?? 0; if (numberOfObserversForThisType === 1) { @@ -224,10 +255,12 @@ export default class PerformanceObserver { NativePerformanceObserver.setOnPerformanceEntryCallback(undefined); isOnPerformanceEntryCallbackSet = false; } + + applyDurationThresholds(); } _validateObserveOptions(options: PerformanceObserverInit): void { - const {type, entryTypes} = options; + const {type, entryTypes, durationThreshold} = options; if (!type && !entryTypes) { throw new TypeError( @@ -252,14 +285,32 @@ export default class PerformanceObserver { "Failed to execute 'observe' on 'PerformanceObserver': This PerformanceObserver has performed observe({type:...}, therefore it cannot perform observe({entryTypes:...})", ); } + + if (entryTypes && durationThreshold !== undefined) { + throw new TypeError( + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and durationThreshold arguments.", + ); + } } static supportedEntryTypes: $ReadOnlyArray = Object.freeze(['mark', 'measure', 'event']); } -function union(a: $ReadOnlySet, b: $ReadOnlySet): Set { - return new Set([...a, ...b]); +// As a Set union, except if value exists in both, we take minimum +function union( + a: $ReadOnlyMap, + b: $ReadOnlyMap, +): Map { + const res = new Map(); + for (const [k, v] of a) { + if (!b.has(k)) { + res.set(k, v); + } else { + res.set(k, Math.min(v ?? 0, b.get(k) ?? 0)); + } + } + return res; } function difference(a: $ReadOnlySet, b: $ReadOnlySet): Set { diff --git a/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js b/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js index 4379e30ab1d23c..98c3313bf0445f 100644 --- a/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js +++ b/Libraries/WebPerformance/__mocks__/NativePerformanceObserver.js @@ -19,6 +19,7 @@ import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; const reportingType: Set = new Set(); const eventCounts: Map = new Map(); +const durationThresholds: Map = new Map(); let entries: Array = []; let onPerformanceEntryCallback: ?() => void; @@ -29,6 +30,7 @@ const NativePerformanceObserverMock: NativePerformanceObserver = { stopReporting: (entryType: RawPerformanceEntryType) => { reportingType.delete(entryType); + durationThresholds.delete(entryType); }, popPendingEntries: (): GetPendingEntriesResult => { @@ -46,6 +48,13 @@ const NativePerformanceObserverMock: NativePerformanceObserver = { logRawEntry: (entry: RawPerformanceEntry) => { if (reportingType.has(entry.entryType)) { + const durationThreshold = durationThresholds.get(entry.entryType); + if ( + durationThreshold !== undefined && + entry.duration < durationThreshold + ) { + return; + } entries.push(entry); // $FlowFixMe[incompatible-call] global.queueMicrotask(() => { @@ -61,6 +70,13 @@ const NativePerformanceObserverMock: NativePerformanceObserver = { getEventCounts: (): $ReadOnlyArray<[string, number]> => { return Array.from(eventCounts.entries()); }, + + setDurationThreshold: ( + entryType: RawPerformanceEntryType, + durationThreshold: number, + ) => { + durationThresholds.set(entryType, durationThreshold); + }, }; export default NativePerformanceObserverMock; diff --git a/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js b/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js index 060b9a9ab9f6f0..a6e6a37be9ff62 100644 --- a/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js +++ b/Libraries/WebPerformance/__tests__/PerformanceObserver-test.js @@ -26,6 +26,7 @@ describe('PerformanceObserver', () => { let totalEntries = 0; const observer = new PerformanceObserver((list, _observer) => { + expect(_observer).toBe(observer); const entries = list.getEntries(); expect(entries).toHaveLength(1); const entry = entries[0]; @@ -46,4 +47,162 @@ describe('PerformanceObserver', () => { expect(totalEntries).toBe(1); observer.disconnect(); }); + + it('prevents durationThreshold to be used together with entryTypes', async () => { + const observer = new PerformanceObserver((list, _observer) => {}); + + expect(() => + observer.observe({entryTypes: ['mark'], durationThreshold: 100}), + ).toThrow(); + }); + + it('handles durationThreshold argument as expected', async () => { + let entries = []; + const observer = new PerformanceObserver((list, _observer) => { + entries = [...entries, ...list.getEntries()]; + }); + + observer.observe({type: 'mark', durationThreshold: 100}); + + NativePerformanceObserver.logRawEntry({ + name: 'mark1', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 200, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark2', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 20, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark3', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 100, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark4', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 500, + }); + + await jest.runAllTicks(); + expect(entries).toHaveLength(3); + expect(entries.map(e => e.name)).toStrictEqual(['mark1', 'mark3', 'mark4']); + }); + + it('correctly works with multiple PerformanceObservers with durationThreshold', async () => { + let entries1 = []; + const observer1 = new PerformanceObserver((list, _observer) => { + entries1 = [...entries1, ...list.getEntries()]; + }); + + let entries2 = []; + const observer2 = new PerformanceObserver((list, _observer) => { + entries2 = [...entries2, ...list.getEntries()]; + }); + + let entries3 = []; + const observer3 = new PerformanceObserver((list, _observer) => { + entries3 = [...entries3, ...list.getEntries()]; + }); + + let entries4 = []; + const observer4 = new PerformanceObserver((list, _observer) => { + entries4 = [...entries4, ...list.getEntries()]; + }); + + observer2.observe({type: 'mark', durationThreshold: 200}); + observer1.observe({type: 'mark', durationThreshold: 100}); + observer3.observe({type: 'mark', durationThreshold: 300}); + observer3.observe({type: 'measure', durationThreshold: 500}); + observer4.observe({entryTypes: ['mark', 'measure']}); + + NativePerformanceObserver.logRawEntry({ + name: 'mark1', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 200, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark2', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 20, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark3', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 100, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark4', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 500, + }); + + await jest.runAllTicks(); + observer1.disconnect(); + + NativePerformanceObserver.logRawEntry({ + name: 'mark5', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 200, + }); + + NativePerformanceObserver.logRawEntry({ + name: 'mark6', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 300, + }); + + await jest.runAllTicks(); + observer3.disconnect(); + + NativePerformanceObserver.logRawEntry({ + name: 'mark7', + entryType: RawPerformanceEntryTypeValues.MARK, + startTime: 0, + duration: 200, + }); + + await jest.runAllTicks(); + observer4.disconnect(); + + expect(entries1.map(e => e.name)).toStrictEqual([ + 'mark1', + 'mark3', + 'mark4', + ]); + expect(entries2.map(e => e.name)).toStrictEqual([ + 'mark1', + 'mark4', + 'mark5', + 'mark6', + 'mark7', + ]); + expect(entries3.map(e => e.name)).toStrictEqual(['mark4', 'mark6']); + expect(entries4.map(e => e.name)).toStrictEqual([ + 'mark1', + 'mark2', + 'mark3', + 'mark4', + 'mark5', + 'mark6', + 'mark7', + ]); + }); }); From e665a0f9952a7852c5506bf334452f8156991ad2 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Thu, 16 Feb 2023 06:25:26 -0800 Subject: [PATCH 37/81] Use std::shared_mutex instead of folly::shared_mutex Summary: changelog: [internal] C++17 has implementation of shared_mutex in standard library. Let's use it instead of folly. Reviewed By: cipolleschi Differential Revision: D43275493 fbshipit-source-id: d766251226aa230110011aca94b4e697fe0d31a1 --- .../Mounting/RCTComponentViewFactory.mm | 10 ++-- React/Fabric/RCTSurfacePresenter.mm | 11 +++-- React/Fabric/RCTSurfaceRegistry.mm | 11 ++--- .../src/main/jni/react/fabric/Binding.cpp | 16 +++--- .../src/main/jni/react/fabric/Binding.h | 6 +-- .../react/fabric/SurfaceHandlerBinding.cpp | 4 +- .../jni/react/fabric/SurfaceHandlerBinding.h | 4 +- ReactCommon/butter/mutex.h | 20 -------- .../ComponentDescriptorProviderRegistry.cpp | 8 +-- .../ComponentDescriptorProviderRegistry.h | 4 +- .../ComponentDescriptorRegistry.cpp | 10 ++-- .../ComponentDescriptorRegistry.h | 4 +- .../react/renderer/core/EventListener.cpp | 6 +-- .../react/renderer/core/EventListener.h | 5 +- .../react/renderer/core/ShadowNodeFamily.cpp | 6 +-- .../react/renderer/core/ShadowNodeFamily.h | 4 +- .../react/renderer/mounting/ShadowTree.cpp | 10 ++-- .../react/renderer/mounting/ShadowTree.h | 3 +- .../renderer/mounting/ShadowTreeRegistry.cpp | 8 +-- .../renderer/mounting/ShadowTreeRegistry.h | 5 +- .../renderer/scheduler/SurfaceHandler.cpp | 49 +++++++++---------- .../react/renderer/scheduler/SurfaceHandler.h | 5 +- .../renderer/scheduler/SurfaceManager.cpp | 6 +-- .../react/renderer/scheduler/SurfaceManager.h | 3 +- .../react/renderer/uimanager/UIManager.cpp | 6 +-- .../react/renderer/uimanager/UIManager.h | 3 +- ReactCommon/react/utils/ContextContainer.h | 14 +++--- ReactCommon/react/utils/SharedFunction.h | 10 ++-- 28 files changed, 115 insertions(+), 136 deletions(-) delete mode 100644 ReactCommon/butter/mutex.h diff --git a/React/Fabric/Mounting/RCTComponentViewFactory.mm b/React/Fabric/Mounting/RCTComponentViewFactory.mm index 0d8e15cebc2a7b..f174ba1dfe3a90 100644 --- a/React/Fabric/Mounting/RCTComponentViewFactory.mm +++ b/React/Fabric/Mounting/RCTComponentViewFactory.mm @@ -11,8 +11,8 @@ #import #import -#import #import +#import #import #import @@ -61,7 +61,7 @@ @implementation RCTComponentViewFactory { butter::map _componentViewClasses; butter::set _registeredComponentsNames; ComponentDescriptorProviderRegistry _providerRegistry; - butter::shared_mutex _mutex; + std::shared_mutex _mutex; } + (RCTComponentViewFactory *)currentComponentViewFactory @@ -155,7 +155,7 @@ - (BOOL)registerComponentIfPossible:(std::string const &)name - (void)registerComponentViewClass:(Class)componentViewClass { RCTAssert(componentViewClass, @"RCTComponentViewFactory: Provided `componentViewClass` is `nil`."); - std::unique_lock lock(_mutex); + std::unique_lock lock(_mutex); auto componentDescriptorProvider = [componentViewClass componentDescriptorProvider]; _componentViewClasses[componentDescriptorProvider.handle] = @@ -177,7 +177,7 @@ - (void)_addDescriptorToProviderRegistry:(ComponentDescriptorProvider const &)pr - (RCTComponentViewDescriptor)createComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle { RCTAssertMainQueue(); - std::shared_lock lock(_mutex); + std::shared_lock lock(_mutex); auto iterator = _componentViewClasses.find(componentHandle); RCTAssert( @@ -198,7 +198,7 @@ - (RCTComponentViewDescriptor)createComponentViewWithComponentHandle:(facebook:: - (facebook::react::ComponentDescriptorRegistry::Shared)createComponentDescriptorRegistryWithParameters: (facebook::react::ComponentDescriptorParameters)parameters { - std::shared_lock lock(_mutex); + std::shared_lock lock(_mutex); return _providerRegistry.createComponentDescriptorRegistry(parameters); } diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index 61bec9c7148da2..eadaf626d53022 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -8,6 +8,7 @@ #import "RCTSurfacePresenter.h" #import +#import #import #import @@ -83,7 +84,7 @@ @implementation RCTSurfacePresenter { RuntimeExecutor _runtimeExecutor; // Protected by `_schedulerLifeCycleMutex`. std::optional _bridgelessBindingsExecutor; // Only used for installing bindings. - butter::shared_mutex _observerListMutex; + std::shared_mutex _observerListMutex; std::vector<__weak id> _observers; // Protected by `_observerListMutex`. } @@ -390,13 +391,13 @@ - (void)schedulerDidSetIsJSResponder:(BOOL)isJSResponder - (void)addObserver:(id)observer { - std::unique_lock lock(_observerListMutex); + std::unique_lock lock(_observerListMutex); _observers.push_back(observer); } - (void)removeObserver:(id)observer { - std::unique_lock lock(_observerListMutex); + std::unique_lock lock(_observerListMutex); std::vector<__weak id>::const_iterator it = std::find(_observers.begin(), _observers.end(), observer); if (it != _observers.end()) { @@ -412,7 +413,7 @@ - (void)mountingManager:(RCTMountingManager *)mountingManager willMountComponent NSArray> *observersCopy; { - std::shared_lock lock(_observerListMutex); + std::shared_lock lock(_observerListMutex); observersCopy = [self _getObservers]; } @@ -429,7 +430,7 @@ - (void)mountingManager:(RCTMountingManager *)mountingManager didMountComponents NSArray> *observersCopy; { - std::shared_lock lock(_observerListMutex); + std::shared_lock lock(_observerListMutex); observersCopy = [self _getObservers]; } diff --git a/React/Fabric/RCTSurfaceRegistry.mm b/React/Fabric/RCTSurfaceRegistry.mm index 50c08f49752eac..5d0e4130fe35a2 100644 --- a/React/Fabric/RCTSurfaceRegistry.mm +++ b/React/Fabric/RCTSurfaceRegistry.mm @@ -7,7 +7,6 @@ #import "RCTSurfaceRegistry.h" -#import #import #import @@ -16,7 +15,7 @@ using namespace facebook; @implementation RCTSurfaceRegistry { - butter::shared_mutex _mutex; + std::shared_mutex _mutex; NSMapTable *_registry; } @@ -32,13 +31,13 @@ - (instancetype)init - (void)enumerateWithBlock:(RCTSurfaceEnumeratorBlock)block { - std::shared_lock lock(_mutex); + std::shared_lock lock(_mutex); block([_registry objectEnumerator]); } - (void)registerSurface:(RCTFabricSurface *)surface { - std::unique_lock lock(_mutex); + std::unique_lock lock(_mutex); ReactTag rootTag = surface.rootViewTag.integerValue; [_registry setObject:surface forKey:(__bridge id)(void *)rootTag]; @@ -46,7 +45,7 @@ - (void)registerSurface:(RCTFabricSurface *)surface - (void)unregisterSurface:(RCTFabricSurface *)surface { - std::unique_lock lock(_mutex); + std::unique_lock lock(_mutex); ReactTag rootTag = surface.rootViewTag.integerValue; [_registry removeObjectForKey:(__bridge id)(void *)rootTag]; @@ -54,7 +53,7 @@ - (void)unregisterSurface:(RCTFabricSurface *)surface - (RCTFabricSurface *)surfaceForRootTag:(ReactTag)rootTag { - std::shared_lock lock(_mutex); + std::shared_lock lock(_mutex); return [_registry objectForKey:(__bridge id)(void *)rootTag]; } diff --git a/ReactAndroid/src/main/jni/react/fabric/Binding.cpp b/ReactAndroid/src/main/jni/react/fabric/Binding.cpp index f5a0aa68229ced..a9b6dc7c3c223a 100644 --- a/ReactAndroid/src/main/jni/react/fabric/Binding.cpp +++ b/ReactAndroid/src/main/jni/react/fabric/Binding.cpp @@ -51,7 +51,7 @@ jni::local_ref Binding::initHybrid( // Thread-safe getter std::shared_ptr Binding::getScheduler() { - std::shared_lock lock(installMutex_); + std::shared_lock lock(installMutex_); return scheduler_; } @@ -132,7 +132,7 @@ void Binding::startSurface( { SystraceSection s2("FabricUIManagerBinding::startSurface::surfaceId::lock"); - std::unique_lock lock(surfaceHandlerRegistryMutex_); + std::unique_lock lock(surfaceHandlerRegistryMutex_); SystraceSection s3("FabricUIManagerBinding::startSurface::surfaceId"); surfaceHandlerRegistry_.emplace(surfaceId, std::move(surfaceHandler)); } @@ -202,7 +202,7 @@ void Binding::startSurfaceWithConstraints( { SystraceSection s2( "FabricUIManagerBinding::startSurfaceWithConstraints::surfaceId::lock"); - std::unique_lock lock(surfaceHandlerRegistryMutex_); + std::unique_lock lock(surfaceHandlerRegistryMutex_); SystraceSection s3( "FabricUIManagerBinding::startSurfaceWithConstraints::surfaceId"); surfaceHandlerRegistry_.emplace(surfaceId, std::move(surfaceHandler)); @@ -246,7 +246,7 @@ void Binding::stopSurface(jint surfaceId) { } { - std::unique_lock lock(surfaceHandlerRegistryMutex_); + std::unique_lock lock(surfaceHandlerRegistryMutex_); auto iterator = surfaceHandlerRegistry_.find(surfaceId); @@ -338,7 +338,7 @@ void Binding::setConstraints( isRTL ? LayoutDirection::RightToLeft : LayoutDirection::LeftToRight; { - std::shared_lock lock(surfaceHandlerRegistryMutex_); + std::shared_lock lock(surfaceHandlerRegistryMutex_); auto iterator = surfaceHandlerRegistry_.find(surfaceId); @@ -377,7 +377,7 @@ void Binding::installFabricUIManager( // Use std::lock and std::adopt_lock to prevent deadlocks by locking mutexes // at the same time - std::unique_lock lock(installMutex_); + std::unique_lock lock(installMutex_); auto globalJavaUiManager = make_global(javaUIManager); mountingManager_ = @@ -467,7 +467,7 @@ void Binding::uninstallFabricUIManager() { << this << ")."; } - std::unique_lock lock(installMutex_); + std::unique_lock lock(installMutex_); animationDriver_ = nullptr; scheduler_ = nullptr; mountingManager_ = nullptr; @@ -476,7 +476,7 @@ void Binding::uninstallFabricUIManager() { std::shared_ptr Binding::verifyMountingManager( std::string const &hint) { - std::shared_lock lock(installMutex_); + std::shared_lock lock(installMutex_); if (!mountingManager_) { LOG(ERROR) << hint << " mounting manager disappeared."; } diff --git a/ReactAndroid/src/main/jni/react/fabric/Binding.h b/ReactAndroid/src/main/jni/react/fabric/Binding.h index 355e616c20fe8c..318fa1e27c5a08 100644 --- a/ReactAndroid/src/main/jni/react/fabric/Binding.h +++ b/ReactAndroid/src/main/jni/react/fabric/Binding.h @@ -10,7 +10,7 @@ #include "FabricMountingManager.h" #include -#include +#include #include #include @@ -123,7 +123,7 @@ class Binding : public jni::HybridClass, void uninstallFabricUIManager(); // Private member variables - butter::shared_mutex installMutex_; + std::shared_mutex installMutex_; std::shared_ptr mountingManager_; std::shared_ptr scheduler_; @@ -139,7 +139,7 @@ class Binding : public jni::HybridClass, BackgroundExecutor backgroundExecutor_; butter::map surfaceHandlerRegistry_{}; - butter::shared_mutex + std::shared_mutex surfaceHandlerRegistryMutex_; // Protects `surfaceHandlerRegistry_`. float pointScaleFactor_ = 1; diff --git a/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.cpp b/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.cpp index 5eaf0a3634848d..63559fe3bb929a 100644 --- a/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.cpp +++ b/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.cpp @@ -21,7 +21,7 @@ void SurfaceHandlerBinding::setDisplayMode(jint mode) { } void SurfaceHandlerBinding::start() { - std::unique_lock lock(lifecycleMutex_); + std::unique_lock lock(lifecycleMutex_); if (surfaceHandler_.getStatus() != SurfaceHandler::Status::Running) { surfaceHandler_.start(); @@ -29,7 +29,7 @@ void SurfaceHandlerBinding::start() { } void SurfaceHandlerBinding::stop() { - std::unique_lock lock(lifecycleMutex_); + std::unique_lock lock(lifecycleMutex_); if (surfaceHandler_.getStatus() == SurfaceHandler::Status::Running) { surfaceHandler_.stop(); diff --git a/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.h b/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.h index 7fdc4919d380e6..e067810a31a4c6 100644 --- a/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.h +++ b/ReactAndroid/src/main/jni/react/fabric/SurfaceHandlerBinding.h @@ -7,6 +7,8 @@ #pragma once +#include + #include #include #include @@ -50,7 +52,7 @@ class SurfaceHandlerBinding : public jni::HybridClass { SurfaceHandler const &getSurfaceHandler(); private: - mutable butter::shared_mutex lifecycleMutex_; + mutable std::shared_mutex lifecycleMutex_; const SurfaceHandler surfaceHandler_; jni::alias_ref jhybridobject_; diff --git a/ReactCommon/butter/mutex.h b/ReactCommon/butter/mutex.h deleted file mode 100644 index 9071356eba1699..00000000000000 --- a/ReactCommon/butter/mutex.h +++ /dev/null @@ -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. - */ - -#pragma once - -#include -#include -#include - -namespace facebook { -namespace butter { - -using shared_mutex = folly::SharedMutex; - -} // namespace butter -} // namespace facebook diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp index 1869439cbc77a4..627b19e06e22ae 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp @@ -11,7 +11,7 @@ namespace facebook::react { void ComponentDescriptorProviderRegistry::add( const ComponentDescriptorProvider &provider) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); /* // TODO: T57583139 @@ -44,7 +44,7 @@ void ComponentDescriptorProviderRegistry::add( void ComponentDescriptorProviderRegistry::setComponentDescriptorProviderRequest( ComponentDescriptorProviderRequest componentDescriptorProviderRequest) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); componentDescriptorProviderRequest_ = std::move(componentDescriptorProviderRequest); } @@ -54,7 +54,7 @@ void ComponentDescriptorProviderRegistry::request( ComponentDescriptorProviderRequest componentDescriptorProviderRequest; { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); componentDescriptorProviderRequest = componentDescriptorProviderRequest_; } @@ -66,7 +66,7 @@ void ComponentDescriptorProviderRegistry::request( ComponentDescriptorRegistry::Shared ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry( ComponentDescriptorParameters const ¶meters) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto registry = std::make_shared( parameters, *this, parameters.contextContainer); diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h index 049cdd4212c43f..9ef8068f2698ac 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include @@ -58,7 +58,7 @@ class ComponentDescriptorProviderRegistry final { void request(ComponentName componentName) const; - mutable butter::shared_mutex mutex_; + mutable std::shared_mutex mutex_; mutable std::vector> componentDescriptorRegistries_; mutable butter::map diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp index 23e0330a86016b..2d85ec352734ba 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp @@ -28,7 +28,7 @@ ComponentDescriptorRegistry::ComponentDescriptorRegistry( void ComponentDescriptorRegistry::add( ComponentDescriptorProvider componentDescriptorProvider) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); auto componentDescriptor = componentDescriptorProvider.constructor( {parameters_.eventDispatcher, @@ -59,7 +59,7 @@ void ComponentDescriptorRegistry::registerComponentDescriptor( ComponentDescriptor const &ComponentDescriptorRegistry::at( std::string const &componentName) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto unifiedComponentName = componentNameByReactViewName(componentName); @@ -96,7 +96,7 @@ ComponentDescriptor const &ComponentDescriptorRegistry::at( ComponentDescriptor const *ComponentDescriptorRegistry:: findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN( ComponentHandle componentHandle) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto iterator = _registryByHandle.find(componentHandle); if (iterator == _registryByHandle.end()) { @@ -108,14 +108,14 @@ ComponentDescriptor const *ComponentDescriptorRegistry:: ComponentDescriptor const &ComponentDescriptorRegistry::at( ComponentHandle componentHandle) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); return *_registryByHandle.at(componentHandle); } bool ComponentDescriptorRegistry::hasComponentDescriptorAt( ComponentHandle componentHandle) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto iterator = _registryByHandle.find(componentHandle); return iterator != _registryByHandle.end(); diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h index d2eeceaf60f996..4a83a4efb89475 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h @@ -8,9 +8,9 @@ #pragma once #include +#include #include -#include #include #include @@ -81,7 +81,7 @@ class ComponentDescriptorRegistry { */ void add(ComponentDescriptorProvider componentDescriptorProvider) const; - mutable butter::shared_mutex mutex_; + mutable std::shared_mutex mutex_; mutable butter::map _registryByHandle; mutable butter::map _registryByName; diff --git a/ReactCommon/react/renderer/core/EventListener.cpp b/ReactCommon/react/renderer/core/EventListener.cpp index 48f5793292dc7b..caef820b11b833 100644 --- a/ReactCommon/react/renderer/core/EventListener.cpp +++ b/ReactCommon/react/renderer/core/EventListener.cpp @@ -10,7 +10,7 @@ namespace facebook::react { bool EventListenerContainer::willDispatchEvent(const RawEvent &event) { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); bool handled = false; for (auto const &listener : eventListeners_) { @@ -21,14 +21,14 @@ bool EventListenerContainer::willDispatchEvent(const RawEvent &event) { void EventListenerContainer::addListener( const std::shared_ptr &listener) { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); eventListeners_.push_back(listener); } void EventListenerContainer::removeListener( const std::shared_ptr &listener) { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); auto it = std::find(eventListeners_.begin(), eventListeners_.end(), listener); if (it != eventListeners_.end()) { diff --git a/ReactCommon/react/renderer/core/EventListener.h b/ReactCommon/react/renderer/core/EventListener.h index f9176b514cbfa0..f72a41614c80d1 100644 --- a/ReactCommon/react/renderer/core/EventListener.h +++ b/ReactCommon/react/renderer/core/EventListener.h @@ -7,12 +7,11 @@ #pragma once +#include #include #include -#include - namespace facebook { namespace react { @@ -36,7 +35,7 @@ class EventListenerContainer { void removeListener(const std::shared_ptr &listener); private: - butter::shared_mutex mutex_; + std::shared_mutex mutex_; std::vector> eventListeners_; }; diff --git a/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp b/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp index 361a51b75ed850..2c86a2555e6c50 100644 --- a/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp +++ b/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp @@ -97,12 +97,12 @@ AncestorList ShadowNodeFamily::getAncestors( } State::Shared ShadowNodeFamily::getMostRecentState() const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); return mostRecentState_; } void ShadowNodeFamily::setMostRecentState(State::Shared const &state) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); /* * Checking and setting `isObsolete_` prevents old states to be recommitted @@ -123,7 +123,7 @@ void ShadowNodeFamily::setMostRecentState(State::Shared const &state) const { std::shared_ptr ShadowNodeFamily::getMostRecentStateIfObsolete( State const &state) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); if (!state.isObsolete_) { return {}; } diff --git a/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/ReactCommon/react/renderer/core/ShadowNodeFamily.h index f907e1913b3dd0..54016e46f4d3ad 100644 --- a/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -8,8 +8,8 @@ #pragma once #include +#include -#include #include #include @@ -108,7 +108,7 @@ class ShadowNodeFamily final { EventDispatcher::Weak eventDispatcher_; mutable std::shared_ptr mostRecentState_; - mutable butter::shared_mutex mutex_; + mutable std::shared_mutex mutex_; /* * Deprecated. diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/ReactCommon/react/renderer/mounting/ShadowTree.cpp index 318834d2494a5a..c1b66df770eed6 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -269,7 +269,7 @@ void ShadowTree::setCommitMode(CommitMode commitMode) const { auto revision = ShadowTreeRevision{}; { - std::unique_lock lock(commitMutex_); + std::unique_lock lock(commitMutex_); if (commitMode_ == commitMode) { return; } @@ -286,7 +286,7 @@ void ShadowTree::setCommitMode(CommitMode commitMode) const { } CommitMode ShadowTree::getCommitMode() const { - std::shared_lock lock(commitMutex_); + std::shared_lock lock(commitMutex_); return commitMode_; } @@ -329,7 +329,7 @@ CommitStatus ShadowTree::tryCommit( { // Reading `currentRevision_` in shared manner. - std::shared_lock lock(commitMutex_); + std::shared_lock lock(commitMutex_); commitMode = commitMode_; oldRevision = currentRevision_; } @@ -366,7 +366,7 @@ CommitStatus ShadowTree::tryCommit( { // Updating `currentRevision_` in unique manner if it hasn't changed. - std::unique_lock lock(commitMutex_); + std::unique_lock lock(commitMutex_); if (currentRevision_.number != oldRevision.number) { return CommitStatus::Failed; @@ -409,7 +409,7 @@ CommitStatus ShadowTree::tryCommit( } ShadowTreeRevision ShadowTree::getCurrentRevision() const { - std::shared_lock lock(commitMutex_); + std::shared_lock lock(commitMutex_); return currentRevision_; } diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.h b/ReactCommon/react/renderer/mounting/ShadowTree.h index 7235fa8c61cab9..b750a1a2fcf0d1 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.h +++ b/ReactCommon/react/renderer/mounting/ShadowTree.h @@ -7,7 +7,6 @@ #pragma once -#include #include #include @@ -142,7 +141,7 @@ class ShadowTree final { SurfaceId const surfaceId_; ShadowTreeDelegate const &delegate_; - mutable butter::shared_mutex commitMutex_; + mutable std::shared_mutex commitMutex_; mutable CommitMode commitMode_{ CommitMode::Normal}; // Protected by `commitMutex_`. mutable ShadowTreeRevision currentRevision_; // Protected by `commitMutex_`. diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp index 082f7ef58d2e56..365f0fb94bd879 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.cpp @@ -17,14 +17,14 @@ ShadowTreeRegistry::~ShadowTreeRegistry() { } void ShadowTreeRegistry::add(std::unique_ptr &&shadowTree) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); registry_.emplace(shadowTree->getSurfaceId(), std::move(shadowTree)); } std::unique_ptr ShadowTreeRegistry::remove( SurfaceId surfaceId) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); auto iterator = registry_.find(surfaceId); if (iterator == registry_.end()) { @@ -39,7 +39,7 @@ std::unique_ptr ShadowTreeRegistry::remove( bool ShadowTreeRegistry::visit( SurfaceId surfaceId, std::function const &callback) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto iterator = registry_.find(surfaceId); @@ -54,7 +54,7 @@ bool ShadowTreeRegistry::visit( void ShadowTreeRegistry::enumerate( std::function const &callback) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto stop = false; for (auto const &pair : registry_) { callback(*pair.second, stop); diff --git a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h index 5eab8e760afbd2..60e4295568fd4b 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h +++ b/ReactCommon/react/renderer/mounting/ShadowTreeRegistry.h @@ -7,8 +7,9 @@ #pragma once +#include + #include -#include #include #include @@ -62,7 +63,7 @@ class ShadowTreeRegistry final { &callback) const; private: - mutable butter::shared_mutex mutex_; + mutable std::shared_mutex mutex_; mutable butter::map> registry_; // Protected by `mutex_`. }; diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp b/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp index ae795699423027..b1c4426a59b1bb 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp @@ -27,13 +27,10 @@ SurfaceHandler::SurfaceHandler(SurfaceHandler &&other) noexcept { } SurfaceHandler &SurfaceHandler::operator=(SurfaceHandler &&other) noexcept { - std::unique_lock lock1(linkMutex_, std::defer_lock); - std::unique_lock lock2( - parametersMutex_, std::defer_lock); - std::unique_lock lock3( - other.linkMutex_, std::defer_lock); - std::unique_lock lock4( - other.parametersMutex_, std::defer_lock); + std::unique_lock lock1(linkMutex_, std::defer_lock); + std::unique_lock lock2(parametersMutex_, std::defer_lock); + std::unique_lock lock3(other.linkMutex_, std::defer_lock); + std::unique_lock lock4(other.parametersMutex_, std::defer_lock); std::lock(lock1, lock2, lock3, lock4); link_ = other.link_; @@ -53,13 +50,13 @@ void SurfaceHandler::setContextContainer( } Status SurfaceHandler::getStatus() const noexcept { - std::shared_lock lock(linkMutex_); + std::shared_lock lock(linkMutex_); return link_.status; } void SurfaceHandler::start() const noexcept { SystraceSection s("SurfaceHandler::start"); - std::unique_lock lock(linkMutex_); + std::unique_lock lock(linkMutex_); react_native_assert( link_.status == Status::Registered && "Surface must be registered."); react_native_assert( @@ -71,7 +68,7 @@ void SurfaceHandler::start() const noexcept { auto parameters = Parameters{}; { SystraceSection s2("SurfaceHandler::start::paramsLock"); - std::shared_lock parametersLock(parametersMutex_); + std::shared_lock parametersLock(parametersMutex_); parameters = parameters_; } @@ -98,7 +95,7 @@ void SurfaceHandler::start() const noexcept { void SurfaceHandler::stop() const noexcept { auto shadowTree = ShadowTree::Unique{}; { - std::unique_lock lock(linkMutex_); + std::unique_lock lock(linkMutex_); react_native_assert( link_.status == Status::Running && "Surface must be running."); @@ -116,7 +113,7 @@ void SurfaceHandler::stop() const noexcept { void SurfaceHandler::setDisplayMode(DisplayMode displayMode) const noexcept { { - std::unique_lock lock(parametersMutex_); + std::unique_lock lock(parametersMutex_); if (parameters_.displayMode == displayMode) { return; } @@ -125,7 +122,7 @@ void SurfaceHandler::setDisplayMode(DisplayMode displayMode) const noexcept { } { - std::shared_lock lock(linkMutex_); + std::shared_lock lock(linkMutex_); if (link_.status != Status::Running) { return; @@ -142,41 +139,41 @@ void SurfaceHandler::setDisplayMode(DisplayMode displayMode) const noexcept { } DisplayMode SurfaceHandler::getDisplayMode() const noexcept { - std::shared_lock lock(parametersMutex_); + std::shared_lock lock(parametersMutex_); return parameters_.displayMode; } #pragma mark - Accessors SurfaceId SurfaceHandler::getSurfaceId() const noexcept { - std::shared_lock lock(parametersMutex_); + std::shared_lock lock(parametersMutex_); return parameters_.surfaceId; } void SurfaceHandler::setSurfaceId(SurfaceId surfaceId) const noexcept { - std::unique_lock lock(parametersMutex_); + std::unique_lock lock(parametersMutex_); parameters_.surfaceId = surfaceId; } std::string SurfaceHandler::getModuleName() const noexcept { - std::shared_lock lock(parametersMutex_); + std::shared_lock lock(parametersMutex_); return parameters_.moduleName; } void SurfaceHandler::setProps(folly::dynamic const &props) const noexcept { SystraceSection s("SurfaceHandler::setProps"); - std::unique_lock lock(parametersMutex_); + std::unique_lock lock(parametersMutex_); parameters_.props = props; } folly::dynamic SurfaceHandler::getProps() const noexcept { - std::shared_lock lock(parametersMutex_); + std::shared_lock lock(parametersMutex_); return parameters_.props; } std::shared_ptr SurfaceHandler::getMountingCoordinator() const noexcept { - std::shared_lock lock(linkMutex_); + std::shared_lock lock(linkMutex_); react_native_assert( link_.status != Status::Unregistered && "Surface must be registered."); react_native_assert( @@ -189,7 +186,7 @@ SurfaceHandler::getMountingCoordinator() const noexcept { Size SurfaceHandler::measure( LayoutConstraints const &layoutConstraints, LayoutContext const &layoutContext) const noexcept { - std::shared_lock lock(linkMutex_); + std::shared_lock lock(linkMutex_); if (link_.status != Status::Running) { return layoutConstraints.clamp({0, 0}); @@ -215,7 +212,7 @@ void SurfaceHandler::constraintLayout( LayoutContext const &layoutContext) const noexcept { SystraceSection s("SurfaceHandler::constraintLayout"); { - std::unique_lock lock(parametersMutex_); + std::unique_lock lock(parametersMutex_); if (parameters_.layoutConstraints == layoutConstraints && parameters_.layoutContext == layoutContext) { @@ -227,7 +224,7 @@ void SurfaceHandler::constraintLayout( } { - std::shared_lock lock(linkMutex_); + std::shared_lock lock(linkMutex_); if (link_.status != Status::Running) { return; @@ -248,12 +245,12 @@ void SurfaceHandler::constraintLayout( } LayoutConstraints SurfaceHandler::getLayoutConstraints() const noexcept { - std::shared_lock lock(parametersMutex_); + std::shared_lock lock(parametersMutex_); return parameters_.layoutConstraints; } LayoutContext SurfaceHandler::getLayoutContext() const noexcept { - std::shared_lock lock(parametersMutex_); + std::shared_lock lock(parametersMutex_); return parameters_.layoutContext; } @@ -294,7 +291,7 @@ void SurfaceHandler::applyDisplayMode(DisplayMode displayMode) const noexcept { } void SurfaceHandler::setUIManager(UIManager const *uiManager) const noexcept { - std::unique_lock lock(linkMutex_); + std::unique_lock lock(linkMutex_); react_native_assert( link_.status != Status::Running && "Surface must not be running."); diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h index f550e709f59f08..2736b4effba05e 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -195,13 +196,13 @@ class SurfaceHandler { /* * `link_` and `linkMutex_` pair. */ - mutable butter::shared_mutex linkMutex_; + mutable std::shared_mutex linkMutex_; mutable Link link_; /* * `parameters_` and `parametersMutex_` pair. */ - mutable butter::shared_mutex parametersMutex_; + mutable std::shared_mutex parametersMutex_; mutable Parameters parameters_; }; diff --git a/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp b/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp index e663b68f4c1ea1..15512adca83f79 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp +++ b/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp @@ -21,7 +21,7 @@ void SurfaceManager::startSurface( LayoutConstraints const &layoutConstraints, LayoutContext const &layoutContext) const noexcept { { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); auto surfaceHandler = SurfaceHandler{moduleName, surfaceId}; surfaceHandler.setContextContainer(scheduler_.getContextContainer()); registry_.emplace(surfaceId, std::move(surfaceHandler)); @@ -44,7 +44,7 @@ void SurfaceManager::stopSurface(SurfaceId surfaceId) const noexcept { }); { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); auto iterator = registry_.find(surfaceId); registry_.erase(iterator); @@ -88,7 +88,7 @@ void SurfaceManager::visit( SurfaceId surfaceId, std::function const &callback) const noexcept { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto iterator = registry_.find(surfaceId); diff --git a/ReactCommon/react/renderer/scheduler/SurfaceManager.h b/ReactCommon/react/renderer/scheduler/SurfaceManager.h index 76dd2bf8f93a41..15a68eb81c1e10 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceManager.h +++ b/ReactCommon/react/renderer/scheduler/SurfaceManager.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -59,7 +60,7 @@ class SurfaceManager final { const noexcept; Scheduler const &scheduler_; - mutable butter::shared_mutex mutex_; // Protects `registry_`. + mutable std::shared_mutex mutex_; // Protects `registry_`. mutable butter::map registry_{}; }; diff --git a/ReactCommon/react/renderer/uimanager/UIManager.cpp b/ReactCommon/react/renderer/uimanager/UIManager.cpp index 795c9eea18f40e..78d7bc912d579c 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -496,7 +496,7 @@ ShadowTreeRegistry const &UIManager::getShadowTreeRegistry() const { void UIManager::registerCommitHook( UIManagerCommitHook const &commitHook) const { - std::unique_lock lock(commitHookMutex_); + std::unique_lock lock(commitHookMutex_); react_native_assert( std::find(commitHooks_.begin(), commitHooks_.end(), &commitHook) == commitHooks_.end()); @@ -506,7 +506,7 @@ void UIManager::registerCommitHook( void UIManager::unregisterCommitHook( UIManagerCommitHook const &commitHook) const { - std::unique_lock lock(commitHookMutex_); + std::unique_lock lock(commitHookMutex_); auto iterator = std::find(commitHooks_.begin(), commitHooks_.end(), &commitHook); react_native_assert(iterator != commitHooks_.end()); @@ -520,7 +520,7 @@ RootShadowNode::Unshared UIManager::shadowTreeWillCommit( ShadowTree const &shadowTree, RootShadowNode::Shared const &oldRootShadowNode, RootShadowNode::Unshared const &newRootShadowNode) const { - std::shared_lock lock(commitHookMutex_); + std::shared_lock lock(commitHookMutex_); auto resultRootShadowNode = newRootShadowNode; for (auto const *commitHook : commitHooks_) { diff --git a/ReactCommon/react/renderer/uimanager/UIManager.h b/ReactCommon/react/renderer/uimanager/UIManager.h index 0d4700d9313236..5aaed2dddf4222 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/ReactCommon/react/renderer/uimanager/UIManager.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -203,7 +204,7 @@ class UIManager final : public ShadowTreeDelegate { BackgroundExecutor const backgroundExecutor_{}; ContextContainer::Shared contextContainer_; - mutable butter::shared_mutex commitHookMutex_; + mutable std::shared_mutex commitHookMutex_; mutable std::vector commitHooks_; std::unique_ptr leakChecker_; diff --git a/ReactCommon/react/utils/ContextContainer.h b/ReactCommon/react/utils/ContextContainer.h index 022492f43b98ca..dd3f8391554a6d 100644 --- a/ReactCommon/react/utils/ContextContainer.h +++ b/ReactCommon/react/utils/ContextContainer.h @@ -10,10 +10,10 @@ #include #include #include +#include #include #include -#include #include #include @@ -42,7 +42,7 @@ class ContextContainer final { */ template void insert(std::string const &key, T const &instance) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); instances_.insert({key, std::make_shared(instance)}); } @@ -52,7 +52,7 @@ class ContextContainer final { * Does nothing if the instance was not found. */ void erase(std::string const &key) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); instances_.erase(key); } @@ -63,7 +63,7 @@ class ContextContainer final { * values from the given container. */ void update(ContextContainer const &contextContainer) const { - std::unique_lock lock(mutex_); + std::unique_lock lock(mutex_); for (auto const &pair : contextContainer.instances_) { instances_.erase(pair.first); @@ -78,7 +78,7 @@ class ContextContainer final { */ template T at(std::string const &key) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); react_native_assert( instances_.find(key) != instances_.end() && @@ -93,7 +93,7 @@ class ContextContainer final { */ template std::optional find(std::string const &key) const { - std::shared_lock lock(mutex_); + std::shared_lock lock(mutex_); auto iterator = instances_.find(key); if (iterator == instances_.end()) { @@ -104,7 +104,7 @@ class ContextContainer final { } private: - mutable butter::shared_mutex mutex_; + mutable std::shared_mutex mutex_; // Protected by mutex_`. mutable butter::map> instances_; }; diff --git a/ReactCommon/react/utils/SharedFunction.h b/ReactCommon/react/utils/SharedFunction.h index a4a958798bef82..e834f0cf018ee5 100644 --- a/ReactCommon/react/utils/SharedFunction.h +++ b/ReactCommon/react/utils/SharedFunction.h @@ -7,9 +7,7 @@ #include #include -#include - -#include +#include namespace facebook { namespace react { @@ -31,7 +29,7 @@ class SharedFunction { struct Pair { Pair(std::function &&function) : function(std::move(function)) {} std::function function; - butter::shared_mutex mutex{}; + std::shared_mutex mutex{}; }; public: @@ -45,12 +43,12 @@ class SharedFunction { SharedFunction &operator=(SharedFunction &&other) noexcept = default; void assign(std::function function) const { - std::unique_lock lock(pair_->mutex); + std::unique_lock lock(pair_->mutex); pair_->function = function; } ReturnT operator()(ArgumentT... args) const { - std::shared_lock lock(pair_->mutex); + std::shared_lock lock(pair_->mutex); return pair_->function(args...); } From a064de151f8314abacbd0f17127597266644fd78 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Thu, 16 Feb 2023 07:03:06 -0800 Subject: [PATCH 38/81] Reduce use of assertions in parsing accessibility props Summary: Changelog: [General][Fixed] - Reduce use of assertions when parsing accessibility props passed from JS Fixes some more cases along the same lines as D43184380 (https://github.com/facebook/react-native/commit/d16c1a04d8ceaf6b6df07d734cd54d490b6c6093) and D43184994 (https://github.com/facebook/react-native/commit/ee4714e3693a3bd88215bd7a19ff805e3262b1c8). Reviewed By: jacdebug Differential Revision: D43324899 fbshipit-source-id: fb343203f16464009931f07592e663b06dcf20e7 --- .../components/view/accessibilityPropsConversions.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h b/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h index 6659e9d7104db3..c3ebe5608ee1fc 100644 --- a/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h +++ b/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -116,7 +117,7 @@ inline void fromRawValue( result = {}; - react_native_assert(value.hasType>()); + react_native_expect(value.hasType>()); if (value.hasType>()) { auto items = (std::vector)value; for (auto &item : items) { @@ -188,7 +189,8 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, ImportantForAccessibility &result) { - react_native_assert(value.hasType()); + result = ImportantForAccessibility::Auto; + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "auto") { @@ -201,7 +203,7 @@ inline void fromRawValue( result = ImportantForAccessibility::NoHideDescendants; } else { LOG(ERROR) << "Unsupported ImportantForAccessiblity value: " << string; - react_native_assert(false); + react_native_expect(false); } } else { LOG(ERROR) << "Unsupported ImportantForAccessiblity type"; @@ -278,7 +280,8 @@ inline void fromRawValue( const PropsParserContext &context, const RawValue &value, AccessibilityLiveRegion &result) { - react_native_assert(value.hasType()); + result = AccessibilityLiveRegion::None; + react_native_expect(value.hasType()); if (value.hasType()) { auto string = (std::string)value; if (string == "none") { @@ -289,7 +292,7 @@ inline void fromRawValue( result = AccessibilityLiveRegion::Assertive; } else { LOG(ERROR) << "Unsupported AccessibilityLiveRegion value: " << string; - react_native_assert(false); + react_native_expect(false); } } else { LOG(ERROR) << "Unsupported AccessibilityLiveRegion type"; From 1d5103227851ab92de889d5e7e910393b5d8743a Mon Sep 17 00:00:00 2001 From: Ana Margarida Silva Date: Thu, 16 Feb 2023 08:09:22 -0800 Subject: [PATCH 39/81] fix: border rendering problem in Android (#36129) Summary: Fixes https://github.com/facebook/react-native/issues/36036 The problem was in `ReactViewBackgroundDrawable.java` that was not accounting for adjacent borders that add width set to 0. ## Changelog [Android] [Fixed] - Fix border rendering issue when bottom borders has no width Pull Request resolved: https://github.com/facebook/react-native/pull/36129 Test Plan: | Previously | Now with the fix | | --------------- | --------------- | | image | image | Reviewed By: cipolleschi Differential Revision: D43303228 Pulled By: javache fbshipit-source-id: cf9d30fe12a5740d9ee8974a66904fd0850e7606 --- .../view/ReactViewBackgroundDrawable.java | 10 ++++- .../rn-tester/js/examples/View/ViewExample.js | 38 ++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index eded03ee94dfb0..dc54a6ff8a3465 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -911,7 +911,10 @@ private void updatePath() { } mInnerBottomLeftCorner.x = mInnerClipTempRectForBorderRadius.left; - mInnerBottomLeftCorner.y = mInnerClipTempRectForBorderRadius.bottom * -2; + mInnerBottomLeftCorner.y = + borderWidth.bottom != 0 + ? mInnerClipTempRectForBorderRadius.bottom * -2 + : mInnerClipTempRectForBorderRadius.bottom; getEllipseIntersectionWithLine( // Ellipse Bounds @@ -963,7 +966,10 @@ private void updatePath() { } mInnerBottomRightCorner.x = mInnerClipTempRectForBorderRadius.right; - mInnerBottomRightCorner.y = mInnerClipTempRectForBorderRadius.bottom * -2; + mInnerBottomRightCorner.y = + borderWidth.bottom != 0 + ? mInnerClipTempRectForBorderRadius.bottom * -2 + : mInnerClipTempRectForBorderRadius.bottom; getEllipseIntersectionWithLine( // Ellipse Bounds diff --git a/packages/rn-tester/js/examples/View/ViewExample.js b/packages/rn-tester/js/examples/View/ViewExample.js index 8602101cf521bd..58a20c7b20980a 100644 --- a/packages/rn-tester/js/examples/View/ViewExample.js +++ b/packages/rn-tester/js/examples/View/ViewExample.js @@ -431,7 +431,7 @@ exports.examples = [ title: 'Rounded Borders', render(): React.Node { return ( - + + + + + ); }, From dff9f5bdef59d3741e11fabc667293812f87920e Mon Sep 17 00:00:00 2001 From: Joshua Selbo Date: Thu, 16 Feb 2023 10:32:11 -0800 Subject: [PATCH 40/81] Disable Android platform for ReactCommon/react/renderer/core tests (#36176) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36176 Changelog: [Internal] Reviewed By: IanChilds, javache Differential Revision: D43322808 fbshipit-source-id: ad0cd88c7dc892a12438c33ee6fe2727825926a2 --- ReactCommon/react/renderer/core/BUCK | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ReactCommon/react/renderer/core/BUCK b/ReactCommon/react/renderer/core/BUCK index 51912e149e7d20..e2f3c97c3c0666 100644 --- a/ReactCommon/react/renderer/core/BUCK +++ b/ReactCommon/react/renderer/core/BUCK @@ -33,6 +33,7 @@ rn_xplat_cxx_library( prefix = "react/renderer/core", ), compiler_flags_pedantic = True, + fbandroid_tests_override = [], fbobjc_compiler_flags = APPLE_COMPILER_FLAGS, fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(), force_static = True, @@ -74,7 +75,7 @@ fb_xplat_cxx_test( "-Wall", ], contacts = ["oncall+react_native@xmail.facebook.com"], - platforms = (ANDROID, APPLE, CXX), + platforms = (APPLE, CXX), deps = [ ":core", "//xplat/hermes/API:HermesAPI", From 1f151e0d2ff4995d296ad09ed8b96c79d2304387 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Thu, 16 Feb 2023 11:46:36 -0800 Subject: [PATCH 41/81] Back out "Add TraceUpdateOverlay to RN AppContainer" Summary: changelog: backout Original commit changeset: a1530cc6e2a9 Original Phabricator Diff: D43180893 (https://github.com/facebook/react-native/commit/89ef5bd6f9064298dfe55b0b18be4a770ee0872c) Reviewed By: Andjeliko, javache Differential Revision: D43350025 fbshipit-source-id: 896057e16c2f466b2ecf2da6b38c56963dc51020 --- .../TraceUpdateOverlay/TraceUpdateOverlay.js | 10 +--------- Libraries/ReactNative/AppContainer.js | 8 +------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js index e0318fac9c4a15..6e5914fd25b26f 100644 --- a/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js +++ b/Libraries/Components/TraceUpdateOverlay/TraceUpdateOverlay.js @@ -10,7 +10,6 @@ import type {Overlay} from './TraceUpdateOverlayNativeComponent'; -import UIManager from '../../ReactNative/UIManager'; import processColor from '../../StyleSheet/processColor'; import StyleSheet from '../../StyleSheet/StyleSheet'; import View from '../View/View'; @@ -54,8 +53,6 @@ type ReactDevToolsGlobalHook = { const {useEffect, useRef, useState} = React; const hook: ReactDevToolsGlobalHook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__; -const isNativeComponentReady = - UIManager.hasViewManagerConfig('TraceUpdateOverlay'); let devToolsAgent: ?Agent; export default function TraceUpdateOverlay(): React.Node { @@ -63,10 +60,6 @@ export default function TraceUpdateOverlay(): React.Node { // This effect is designed to be explictly shown here to avoid re-subscribe from the same // overlay component. useEffect(() => { - if (!isNativeComponentReady) { - return; - } - function attachToDevtools(agent: Agent) { devToolsAgent = agent; agent.addListener('drawTraceUpdates', onAgentDrawTraceUpdates); @@ -148,8 +141,7 @@ export default function TraceUpdateOverlay(): React.Node { useRef>(null); return ( - !overlayDisabled && - isNativeComponentReady && ( + !overlayDisabled && ( { state: State = { inspector: null, devtoolsOverlay: null, - traceUpdateOverlay: null, mainKey: 1, hasError: false, }; @@ -77,10 +75,7 @@ class AppContainer extends React.Component { const devtoolsOverlay = ( ); - const TraceUpdateOverlay = - require('../Components/TraceUpdateOverlay/TraceUpdateOverlay').default; - const traceUpdateOverlay = ; - this.setState({devtoolsOverlay, traceUpdateOverlay}); + this.setState({devtoolsOverlay}); } } } @@ -132,7 +127,6 @@ class AppContainer extends React.Component { {!this.state.hasError && innerView} - {this.state.traceUpdateOverlay} {this.state.devtoolsOverlay} {this.state.inspector} {logBox} From 321868011b51597657b602902c07f2b02dec19ce Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Thu, 16 Feb 2023 13:42:26 -0800 Subject: [PATCH 42/81] Avoid redundant copy of shared_ptr Summary: changelog: [internal] Making a copy of shared_ptr is order of magnitude more expensive than moving it. This diff avoids two redundant copies in commit phase. Reviewed By: rubennorte, cipolleschi Differential Revision: D43306245 fbshipit-source-id: cfa942cc67b1e5c91be47803b80f7c8cda2e32d8 --- .../react/renderer/mounting/MountingCoordinator.cpp | 4 ++-- .../react/renderer/mounting/MountingCoordinator.h | 2 +- ReactCommon/react/renderer/mounting/ShadowTree.cpp | 13 ++++++------- ReactCommon/react/renderer/mounting/ShadowTree.h | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp b/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp index bbd02b4cdc9871..88242a74cb5bbd 100644 --- a/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp +++ b/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp @@ -33,7 +33,7 @@ SurfaceId MountingCoordinator::getSurfaceId() const { return surfaceId_; } -void MountingCoordinator::push(ShadowTreeRevision const &revision) const { +void MountingCoordinator::push(ShadowTreeRevision revision) const { { std::lock_guard lock(mutex_); @@ -41,7 +41,7 @@ void MountingCoordinator::push(ShadowTreeRevision const &revision) const { !lastRevision_.has_value() || revision.number != lastRevision_->number); if (!lastRevision_.has_value() || lastRevision_->number < revision.number) { - lastRevision_ = revision; + lastRevision_ = std::move(revision); } } diff --git a/ReactCommon/react/renderer/mounting/MountingCoordinator.h b/ReactCommon/react/renderer/mounting/MountingCoordinator.h index d2685185660a21..188c6fb02b76d3 100644 --- a/ReactCommon/react/renderer/mounting/MountingCoordinator.h +++ b/ReactCommon/react/renderer/mounting/MountingCoordinator.h @@ -88,7 +88,7 @@ class MountingCoordinator final { private: friend class ShadowTree; - void push(ShadowTreeRevision const &revision) const; + void push(ShadowTreeRevision revision) const; /* * Revokes the last pushed `ShadowTreeRevision`. diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/ReactCommon/react/renderer/mounting/ShadowTree.cpp index c1b66df770eed6..109cada60db834 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -393,8 +393,8 @@ CommitStatus ShadowTree::tryCommit( telemetry.didCommit(); telemetry.setRevisionNumber(static_cast(newRevisionNumber)); - newRevision = - ShadowTreeRevision{newRootShadowNode, newRevisionNumber, telemetry}; + newRevision = ShadowTreeRevision{ + std::move(newRootShadowNode), newRevisionNumber, telemetry}; currentRevision_ = newRevision; } @@ -402,7 +402,7 @@ CommitStatus ShadowTree::tryCommit( emitLayoutEvents(affectedLayoutableNodes); if (commitMode == CommitMode::Normal) { - mount(newRevision, commitOptions.mountSynchronously); + mount(std::move(newRevision), commitOptions.mountSynchronously); } return CommitStatus::Succeeded; @@ -413,10 +413,9 @@ ShadowTreeRevision ShadowTree::getCurrentRevision() const { return currentRevision_; } -void ShadowTree::mount( - ShadowTreeRevision const &revision, - bool mountSynchronously) const { - mountingCoordinator_->push(revision); +void ShadowTree::mount(ShadowTreeRevision revision, bool mountSynchronously) + const { + mountingCoordinator_->push(std::move(revision)); delegate_.shadowTreeDidFinishTransaction( mountingCoordinator_, mountSynchronously); } diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.h b/ReactCommon/react/renderer/mounting/ShadowTree.h index b750a1a2fcf0d1..0e8d5f32486924 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.h +++ b/ReactCommon/react/renderer/mounting/ShadowTree.h @@ -134,7 +134,7 @@ class ShadowTree final { private: constexpr static ShadowTreeRevision::Number INITIAL_REVISION{0}; - void mount(ShadowTreeRevision const &revision, bool mountSynchronously) const; + void mount(ShadowTreeRevision revision, bool mountSynchronously) const; void emitLayoutEvents( std::vector &affectedLayoutableNodes) const; From 2cfb34f6bba204818fd514f9ccf283fb85ccbaa7 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Fri, 17 Feb 2023 05:43:22 -0800 Subject: [PATCH 43/81] log out brew install messages (#36191) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36191 Brew commands used to be piped to /dev/null. We weren't able to investigate brew install failures because of this. # Changelog: [General][Changed] - log out brew stdout messages in CircleCI Reviewed By: robhogan, cortinico Differential Revision: D43389785 fbshipit-source-id: 4dc56125ef5fb87b181ad0b8f9069995ad896812 --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e44489663a5fb8..1411550f068e6b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -203,7 +203,7 @@ commands: steps: - run: name: "Brew: Install << parameters.package >>" - command: brew install << parameters.package >> >/dev/null + command: brew install << parameters.package >> with_rntester_pods_cache_span: parameters: @@ -592,7 +592,7 @@ jobs: - run: name: "Brew: Tap wix/brew" - command: brew tap wix/brew >/dev/null + command: brew tap wix/brew - brew_install: package: applesimutils watchman From 21a0fb597a32f4829fe5545e478d78ea7862811c Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Fri, 17 Feb 2023 05:43:24 -0800 Subject: [PATCH 44/81] Add invalid props example to RNTester (#36162) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36162 Changelog: [Internal] Adds a dedicated screen to RNTester to help manually test the handling of various invalid prop values. Reviewed By: huntie Differential Revision: D43270626 fbshipit-source-id: 3fbf452955b2caace7a09fbb9c83960703fd974f --- .../InvalidProps/InvalidPropsExample.js | 161 ++++++++++++++++++ .../js/utils/RNTesterList.android.js | 4 + .../rn-tester/js/utils/RNTesterList.ios.js | 4 + 3 files changed, 169 insertions(+) create mode 100644 packages/rn-tester/js/examples/InvalidProps/InvalidPropsExample.js diff --git a/packages/rn-tester/js/examples/InvalidProps/InvalidPropsExample.js b/packages/rn-tester/js/examples/InvalidProps/InvalidPropsExample.js new file mode 100644 index 00000000000000..507268c03fc4f5 --- /dev/null +++ b/packages/rn-tester/js/examples/InvalidProps/InvalidPropsExample.js @@ -0,0 +1,161 @@ +/** + * 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 + * @flow + */ + +'use strict'; + +import * as React from 'react'; + +import {Text, View} from 'react-native'; + +export const title = 'Invalid Props'; +export const category = 'Other'; +export const description = + 'Examples of passing invalid prop values and how they fall back to expected defaults.'; + +export const examples = [ + { + title: 'View flex', + render(): React.Node { + return ( + + {flex => ( + + + + + )} + + ); + }, + }, + { + title: 'View flexDirection', + render(): React.Node { + return ( + + {flexDirection => ( + + ⬇️ + ⬇️ + + )} + + ); + }, + }, + { + title: 'Text fontVariant', + render(): React.Node { + return ( + + {fontVariant => ( + + The quick brown fox jumps over the lazy dog. + + )} + + ); + }, + }, + { + title: 'View width', + render(): React.Node { + return ( + + {width => ( + + + + )} + + ); + }, + }, + { + title: 'View background color', + render(): React.Node { + return ( + + {backgroundColor => ( + + + + )} + + ); + }, + }, + { + title: 'Malformed platform color', + render(): React.Node { + return ( + )}} + expected={undefined}> + {backgroundColor => ( + + + + )} + + ); + }, + }, +]; + +function Comparison({ + children, + actual, + expected, +}: { + children: (value: ExpectedT | ActualT) => React.Node, + actual: ActualT, + expected: ExpectedT, +}): React.Node { + return ( + <> + Actual + {children(actual)} + Expected + {children(expected)} + + ); +} diff --git a/packages/rn-tester/js/utils/RNTesterList.android.js b/packages/rn-tester/js/utils/RNTesterList.android.js index 3e590bb405fc05..c76ba8c5db39f3 100644 --- a/packages/rn-tester/js/utils/RNTesterList.android.js +++ b/packages/rn-tester/js/utils/RNTesterList.android.js @@ -188,6 +188,10 @@ const APIs: Array = [ category: 'UI', module: require('../examples/Dimensions/DimensionsExample'), }, + { + key: 'InvalidPropsExample', + module: require('../examples/InvalidProps/InvalidPropsExample'), + }, { key: 'Keyboard', category: 'Basic', diff --git a/packages/rn-tester/js/utils/RNTesterList.ios.js b/packages/rn-tester/js/utils/RNTesterList.ios.js index 651d939faa7478..7676a8831f4328 100644 --- a/packages/rn-tester/js/utils/RNTesterList.ios.js +++ b/packages/rn-tester/js/utils/RNTesterList.ios.js @@ -194,6 +194,10 @@ const APIs: Array = [ key: 'Dimensions', module: require('../examples/Dimensions/DimensionsExample'), }, + { + key: 'InvalidPropsExample', + module: require('../examples/InvalidProps/InvalidPropsExample'), + }, { key: 'Keyboard', module: require('../examples/Keyboard/KeyboardExample').default, From e42dd1593d7ec678f91deb0ab31013f9d72544a9 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 17 Feb 2023 06:19:37 -0800 Subject: [PATCH 45/81] bump package versions (#36184) Summary: We do have a lot of changes on `main` to ship to nightlies. This change bump all the packages with pending changes. ## Changelog [INTERNAL] [CHANGED] - [ci][monorepo] bump package versions Pull Request resolved: https://github.com/facebook/react-native/pull/36184 Test Plan: Will rely on CI run. Reviewed By: hoxyq Differential Revision: D43363981 Pulled By: cortinico fbshipit-source-id: eba5152dbe007eb3fad43f9088d145b3741fd94e --- package.json | 2 +- packages/babel-plugin-codegen/package.json | 2 +- packages/eslint-plugin-specs/package.json | 2 +- packages/polyfills/package.json | 2 +- packages/react-native-codegen/package.json | 2 +- packages/react-native-gradle-plugin/package.json | 2 +- packages/virtualized-lists/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index d99ef6323c5a01..9b639546fcabbd 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "@react-native/gradle-plugin": "^0.72.2", "@react-native/js-polyfills": "^0.72.0", "@react-native/normalize-colors": "^0.72.0", - "@react-native/virtualized-lists": "0.72.0", + "@react-native/virtualized-lists": "^0.72.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "base64-js": "^1.1.2", diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index 8256be94c370db..5c027994ce676e 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,5 +1,5 @@ { - "version": "0.72.1", + "version": "0.72.2", "name": "@react-native/babel-plugin-codegen", "description": "Babel plugin to generate native module and view manager code for React Native.", "repository": { diff --git a/packages/eslint-plugin-specs/package.json b/packages/eslint-plugin-specs/package.json index 20e90594d1e39c..e81a286f10651b 100644 --- a/packages/eslint-plugin-specs/package.json +++ b/packages/eslint-plugin-specs/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-plugin-specs", - "version": "0.72.1", + "version": "0.72.2", "description": "ESLint rules to validate NativeModule and Component Specs", "main": "index.js", "repository": { diff --git a/packages/polyfills/package.json b/packages/polyfills/package.json index 6dfce02834c485..bee8717d327d81 100644 --- a/packages/polyfills/package.json +++ b/packages/polyfills/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/js-polyfills", - "version": "0.72.0", + "version": "0.72.1", "description": "Polyfills for React Native.", "repository": { "type": "git", diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 7b452a08466858..3aab622baa1317 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/codegen", - "version": "0.72.1", + "version": "0.72.2", "description": "⚛️ Code generation tools for React Native", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-codegen", "repository": { diff --git a/packages/react-native-gradle-plugin/package.json b/packages/react-native-gradle-plugin/package.json index f392f1ff6ea464..9528c76da61702 100644 --- a/packages/react-native-gradle-plugin/package.json +++ b/packages/react-native-gradle-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/gradle-plugin", - "version": "0.72.2", + "version": "0.72.3", "description": "⚛️ Gradle Plugin for React Native", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin", "repository": { diff --git a/packages/virtualized-lists/package.json b/packages/virtualized-lists/package.json index 8b19cd2c199f7a..be50887d2daca5 100644 --- a/packages/virtualized-lists/package.json +++ b/packages/virtualized-lists/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/virtualized-lists", - "version": "0.72.0", + "version": "0.72.1", "description": "Virtualized lists for React Native.", "repository": { "type": "git", From 6dde1dc7cb487271567aaa9c7e093bb76c0689ad Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 17 Feb 2023 07:40:09 -0800 Subject: [PATCH 46/81] RNGP - ENTRY_FILE should resolve relative paths from root (#36193) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36193 Fixes #36186 Changelog: [Android] [Fixed] - ENTRY_FILE should resolve relative paths from root Reviewed By: cipolleschi Differential Revision: D43392121 fbshipit-source-id: ddf302d333c5fc5f822e0635a73e5b52470140ee --- .../kotlin/com/facebook/react/TaskConfiguration.kt | 3 ++- .../kotlin/com/facebook/react/utils/PathUtils.kt | 14 ++++++++++---- .../com/facebook/react/utils/PathUtilsTest.kt | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt index 24ba33b297c692..2e4e923403791e 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/TaskConfiguration.kt @@ -51,13 +51,14 @@ internal fun Project.configureReactTasks(variant: Variant, config: ReactExtensio configureJsEnginePackagingOptions(config, variant, isHermesEnabledInThisVariant) if (!isDebuggableVariant) { + val entryFileEnvVariable = System.getenv("ENTRY_FILE") val bundleTask = tasks.register("createBundle${targetName}JsAndAssets", BundleHermesCTask::class.java) { it.root.set(config.root) it.nodeExecutableAndArgs.set(config.nodeExecutableAndArgs) it.cliFile.set(cliFile) it.bundleCommand.set(config.bundleCommand) - it.entryFile.set(detectedEntryFile(config)) + it.entryFile.set(detectedEntryFile(config, entryFileEnvVariable)) it.extraPackagerArgs.set(config.extraPackagerArgs) it.bundleConfig.set(config.bundleConfig) it.bundleAssetName.set(config.bundleAssetName) diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt index 2d94bf72a04867..391c6c2868f50d 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/PathUtils.kt @@ -25,9 +25,11 @@ import org.gradle.api.file.DirectoryProperty * * @param config The [ReactExtension] configured for this project */ -internal fun detectedEntryFile(config: ReactExtension): File = +internal fun detectedEntryFile(config: ReactExtension, envVariableOverride: String? = null): File = detectEntryFile( - entryFile = config.entryFile.orNull?.asFile, reactRoot = config.root.get().asFile) + entryFile = config.entryFile.orNull?.asFile, + reactRoot = config.root.get().asFile, + envVariableOverride = envVariableOverride) /** * Computes the CLI file for React Native. The Algo follows this order: @@ -54,9 +56,13 @@ internal fun detectedCliFile(config: ReactExtension): File = internal fun detectedHermesCommand(config: ReactExtension): String = detectOSAwareHermesCommand(config.root.get().asFile, config.hermesCommand.get()) -private fun detectEntryFile(entryFile: File?, reactRoot: File): File = +private fun detectEntryFile( + entryFile: File?, + reactRoot: File, + envVariableOverride: String? = null +): File = when { - System.getenv("ENTRY_FILE") != null -> File(System.getenv("ENTRY_FILE")) + envVariableOverride != null -> File(reactRoot, envVariableOverride) entryFile != null -> entryFile File(reactRoot, "index.android.js").exists() -> File(reactRoot, "index.android.js") else -> File(reactRoot, "index.js") diff --git a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt index 1239f372f4d2bd..461a661476012b 100644 --- a/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt +++ b/packages/react-native-gradle-plugin/src/test/kotlin/com/facebook/react/utils/PathUtilsTest.kt @@ -57,6 +57,20 @@ class PathUtilsTest { assertEquals(File(tempFolder.root, "index.js"), actual) } + @Test + fun detectedEntryFile_withEnvironmentVariable() { + val extension = TestReactExtension(ProjectBuilder.builder().build()) + val expected = tempFolder.newFile("./fromenv.index.js") + // As we can't override env variable for tests, we're going to emulate them here. + val envVariable = "./fromenv.index.js" + + extension.root.set(tempFolder.root) + + val actual = detectedEntryFile(extension, envVariable) + + assertEquals(expected, actual) + } + @Test fun detectedCliPath_withCliPathFromExtensionAndFileExists_returnsIt() { val project = ProjectBuilder.builder().build() From ed8a3e08e2f227a37730b697b0e4e2c7d63e27ff Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Fri, 17 Feb 2023 08:08:39 -0800 Subject: [PATCH 47/81] brew should overwrite existing python links (#36192) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36192 Builds are failing on CI because brew bails out when it tries installing Python 3.1. The image already has an existing version of Python 3, which we should overwrite. {F876436464} This seems to be a known issue [1] with Brew. In this case it seems safe to overwrite. Changelog: [General][Changed] - Brew overwrites system Python 3. [1] https://github.com/actions/setup-python/issues/577#issuecomment-1431468702 Reviewed By: cipolleschi Differential Revision: D43391941 fbshipit-source-id: 9b0cb234eeb0b7473b17b5ebfa6ed12c6448760f --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1411550f068e6b..af45646a49a712 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -593,6 +593,11 @@ jobs: - run: name: "Brew: Tap wix/brew" command: brew tap wix/brew + - run: + # Python 3.10 already exists in the environment, this is a workaround for: + # https://github.com/actions/setup-python/issues/577 + name: "Unlink environment's Python 3.10" + command: brew unlink python@3.10 - brew_install: package: applesimutils watchman From 260aab74ce12988e83a7618c3b5c90aefbe9d1e3 Mon Sep 17 00:00:00 2001 From: Pieter Vanderwerff Date: Fri, 17 Feb 2023 13:36:03 -0800 Subject: [PATCH 48/81] Deploy presuppressions for v0.200.0 to xplat Reviewed By: mroch Differential Revision: D43377746 fbshipit-source-id: 288fe8639420931ccc2f1b50a5f35090a2f023c3 --- Libraries/Animated/NativeAnimatedHelper.js | 1 + .../js/examples/TurboModule/NativeCxxModuleExampleExample.js | 1 + 2 files changed, 2 insertions(+) diff --git a/Libraries/Animated/NativeAnimatedHelper.js b/Libraries/Animated/NativeAnimatedHelper.js index a097db20a6b081..e67a1aa2e35159 100644 --- a/Libraries/Animated/NativeAnimatedHelper.js +++ b/Libraries/Animated/NativeAnimatedHelper.js @@ -592,6 +592,7 @@ export default { // $FlowExpectedError[missing-type-arg] - unsafe getter lint suppresion get nativeEventEmitter(): NativeEventEmitter { if (!nativeEventEmitter) { + // $FlowFixMe[underconstrained-implicit-instantiation] nativeEventEmitter = new NativeEventEmitter( // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior // If you want to use the native module on other platforms, please remove this condition and test its behavior diff --git a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js index cecbacba004548..2ecdee1877977c 100644 --- a/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js +++ b/packages/rn-tester/js/examples/TurboModule/NativeCxxModuleExampleExample.js @@ -165,6 +165,7 @@ class NativeCxxModuleExampleExample extends React.Component<{||}, State> { item} renderItem={({item}: {item: Examples, ...}) => ( From 0b2bd0f62ca16d74d8e7be1af4965127012f869c Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 17 Feb 2023 14:10:15 -0800 Subject: [PATCH 49/81] Update all package usage on main after a bump (#36200) Summary: This updates all the package usages after the recent bump on main. ## Changelog [INTERNAL] - Update all package usage on main after a bump Pull Request resolved: https://github.com/facebook/react-native/pull/36200 Test Plan: Relying on CI Reviewed By: hoxyq Differential Revision: D43397084 Pulled By: cortinico fbshipit-source-id: 06a13772a627f812d7d39931f32071fa3eaa59f9 --- package.json | 6 +++--- repo-config/package.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9b639546fcabbd..15f598cb1aa1cb 100644 --- a/package.json +++ b/package.json @@ -118,10 +118,10 @@ "@react-native-community/cli-platform-android": "10.0.0", "@react-native-community/cli-platform-ios": "10.0.0", "@react-native/assets-registry": "^0.72.0", - "@react-native/gradle-plugin": "^0.72.2", - "@react-native/js-polyfills": "^0.72.0", + "@react-native/gradle-plugin": "^0.72.3", + "@react-native/js-polyfills": "^0.72.1", "@react-native/normalize-colors": "^0.72.0", - "@react-native/virtualized-lists": "^0.72.0", + "@react-native/virtualized-lists": "^0.72.1", "abort-controller": "^3.0.0", "anser": "^1.4.9", "base64-js": "^1.1.2", diff --git a/repo-config/package.json b/repo-config/package.json index 82002581f821e4..a10e4f55f43135 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -14,10 +14,10 @@ "@babel/generator": "^7.20.0", "@babel/plugin-transform-regenerator": "^7.0.0", "@definitelytyped/dtslint": "^0.0.127", - "@react-native/codegen": "^0.72.1", + "@react-native/codegen": "^0.72.2", "@react-native/eslint-config": "*", "@react-native/eslint-plugin": "*", - "@react-native/eslint-plugin-specs": "^0.72.1", + "@react-native/eslint-plugin-specs": "^0.72.2", "@reactions/component": "^2.0.2", "@types/react": "^18.0.18", "@typescript-eslint/parser": "^5.30.5", From 60f381a8b9094e7dfaf01bea1b745d576cc458f6 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 17 Feb 2023 14:50:53 -0800 Subject: [PATCH 50/81] Fix a crash when reloading the JS bundle Summary: changelog: [iOS][Fixed] Fix a crash when reloading JS bundle Do not crash if self is nil. Reviewed By: blakef Differential Revision: D43352039 fbshipit-source-id: dd53677ca152d4021e43ed8d0f1b51c071ca3365 --- React/CoreModules/RCTDevSplitBundleLoader.mm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/React/CoreModules/RCTDevSplitBundleLoader.mm b/React/CoreModules/RCTDevSplitBundleLoader.mm index 8eb756db0e0232..9dd1b0ebd3ebf2 100644 --- a/React/CoreModules/RCTDevSplitBundleLoader.mm +++ b/React/CoreModules/RCTDevSplitBundleLoader.mm @@ -63,10 +63,12 @@ + (BOOL)requiresMainQueueSetup return; } __typeof(self) strongSelf = weakSelf; - strongSelf->_loadScript(source); - RCTDevSettings *devSettings = [strongSelf->_moduleRegistry moduleForName:"RCTDevSettings"]; - [devSettings setupHMRClientWithAdditionalBundleURL:source.url]; - resolve(@YES); + if (strongSelf) { + strongSelf->_loadScript(source); + RCTDevSettings *devSettings = [strongSelf->_moduleRegistry moduleForName:"RCTDevSettings"]; + [devSettings setupHMRClientWithAdditionalBundleURL:source.url]; + resolve(@YES); + } }]; } } From 9aac13d4dc95925b57f03e7964fc7add6834e518 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 17 Feb 2023 15:19:44 -0800 Subject: [PATCH 51/81] Fix race condition in ReadableNativeMap (#36201) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36201 [Changelog][Internal] Guard call to the C++ ReadableNAtiveMap.importValues with a lock. Note that all the occurrences in this class (together with importTypes) already were protected by a lock, except of this one, which with the very high chance caused crashes in T145271136. My corresponding comment from the task, for justification: > If callstack to be trusted, the crash happens on the C++ side, in ReadableNativeMap::importValues(). It throws ArrayIndexOutOfBoundsException, which, looking at the code, seems to be only possible due to a corrupted data or race conditions. > Now, looking at the Java side of ReadableNativeMap, and the particular call site... it's very dodgy, since all other occurrences of calling to native importTypes/importValues are guarded by locks, but the one crashing isn't. NOTE: A couple of `importKeys()` instances appears to suffer from the same problem as well. Reviewed By: javache Differential Revision: D43398416 fbshipit-source-id: 0402de5dc723a2fba7d0247c8ad4aeff150d8340 --- .../react/bridge/ReadableNativeMap.java | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index 0b787014524b06..3dae1f0ba165d8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -39,15 +39,21 @@ public static int getJNIPassCounter() { return mJniCallCounter; } - private HashMap getLocalMap() { - if (mLocalMap != null) { - return mLocalMap; - } + private void ensureKeysAreImported() { synchronized (this) { if (mKeys == null) { mKeys = Assertions.assertNotNull(importKeys()); mJniCallCounter++; } + } + } + + private HashMap getLocalMap() { + if (mLocalMap != null) { + return mLocalMap; + } + ensureKeysAreImported(); + synchronized (this) { if (mLocalMap == null) { Object[] values = Assertions.assertNotNull(importValues()); mJniCallCounter++; @@ -69,11 +75,8 @@ private HashMap getLocalMap() { if (mLocalTypeMap != null) { return mLocalTypeMap; } + ensureKeysAreImported(); synchronized (this) { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - mJniCallCounter++; - } // check that no other thread has already updated if (mLocalTypeMap == null) { Object[] types = Assertions.assertNotNull(importTypes()); @@ -187,48 +190,47 @@ public int getInt(@NonNull String name) { @Override public @NonNull Iterator> getEntryIterator() { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - } + ensureKeysAreImported(); final String[] iteratorKeys = mKeys; - final Object[] iteratorValues = Assertions.assertNotNull(importValues()); - return new Iterator>() { - int currentIndex = 0; + synchronized (this) { + final Object[] iteratorValues = Assertions.assertNotNull(importValues()); - @Override - public boolean hasNext() { - return currentIndex < iteratorKeys.length; - } + return new Iterator>() { + int currentIndex = 0; - @Override - public Map.Entry next() { - final int index = currentIndex++; - return new Map.Entry() { - @Override - public String getKey() { - return iteratorKeys[index]; - } - - @Override - public Object getValue() { - return iteratorValues[index]; - } - - @Override - public Object setValue(Object value) { - throw new UnsupportedOperationException( - "Can't set a value while iterating over a ReadableNativeMap"); - } - }; - } - }; + @Override + public boolean hasNext() { + return currentIndex < iteratorKeys.length; + } + + @Override + public Map.Entry next() { + final int index = currentIndex++; + return new Map.Entry() { + @Override + public String getKey() { + return iteratorKeys[index]; + } + + @Override + public Object getValue() { + return iteratorValues[index]; + } + + @Override + public Object setValue(Object value) { + throw new UnsupportedOperationException( + "Can't set a value while iterating over a ReadableNativeMap"); + } + }; + } + }; + } } @Override public @NonNull ReadableMapKeySetIterator keySetIterator() { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - } + ensureKeysAreImported(); final String[] iteratorKeys = mKeys; return new ReadableMapKeySetIterator() { int currentIndex = 0; From a4b41d28283b90913475cab8b35a8abcd6321039 Mon Sep 17 00:00:00 2001 From: Pieter Vanderwerff Date: Fri, 17 Feb 2023 16:47:34 -0800 Subject: [PATCH 52/81] Deploy v0.200.0 to xplat Reviewed By: mroch Differential Revision: D43377809 fbshipit-source-id: fb95e86a1d5155f45104dca2a9a5989f0acea827 --- .flowconfig | 2 +- .flowconfig.android | 2 +- package.json | 2 +- repo-config/package.json | 2 +- yarn.lock | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.flowconfig b/.flowconfig index 132a3aeeda51d6..379f7bddca1229 100644 --- a/.flowconfig +++ b/.flowconfig @@ -76,4 +76,4 @@ untyped-import untyped-type-import [version] -^0.199.1 +^0.200.0 diff --git a/.flowconfig.android b/.flowconfig.android index 406d98a2231d5a..7921426e1d7085 100644 --- a/.flowconfig.android +++ b/.flowconfig.android @@ -76,4 +76,4 @@ untyped-import untyped-type-import [version] -^0.199.1 +^0.200.0 diff --git a/package.json b/package.json index 15f598cb1aa1cb..6a8c70926ad977 100644 --- a/package.json +++ b/package.json @@ -150,7 +150,7 @@ "ws": "^6.2.2" }, "devDependencies": { - "flow-bin": "^0.199.1", + "flow-bin": "^0.200.0", "hermes-eslint": "0.8.0", "mock-fs": "^5.1.4", "react": "18.2.0", diff --git a/repo-config/package.json b/repo-config/package.json index a10e4f55f43135..b83ef2e2d796da 100644 --- a/repo-config/package.json +++ b/repo-config/package.json @@ -38,7 +38,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-native": "^4.0.0", "eslint-plugin-relay": "^1.8.3", - "flow-bin": "^0.199.1", + "flow-bin": "^0.200.0", "inquirer": "^7.1.0", "jest": "^29.2.1", "jest-junit": "^10.0.0", diff --git a/yarn.lock b/yarn.lock index 215cdc9fd4b714..35516686108547 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4406,10 +4406,10 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== -flow-bin@^0.199.1: - version "0.199.1" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.199.1.tgz#678eac2303fa898227f4d103264b6ce49f4430c1" - integrity sha512-Ic0Mp9iZ2exbH0mNj/XhzUWPZa9JylHb6uQARZnnYCTRwumOpjNOP0qwyRTltWrbCpfHjnWngNO9VLaVKHz2aQ== +flow-bin@^0.200.0: + version "0.200.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.200.0.tgz#bae10e7454aca131f72f084f64371f5098c5be07" + integrity sha512-4KquALYPkCCTCZ43GIqTDZDOf4znU3/kXsigpiwwORV8l/ctqwvKkqCOhjqvGy5DtbiL6WTPBqLwGAlxeGeNIA== flow-enums-runtime@^0.0.5: version "0.0.5" From bcf493f346e320d683ced471750bb8d8e3b1a5ae Mon Sep 17 00:00:00 2001 From: Steve Alves-Blyt Date: Fri, 17 Feb 2023 18:32:18 -0800 Subject: [PATCH 53/81] fix: add width, height and crossOrigin props on Image type declaration file (#36196) Summary: According this Issue [`https://github.com/facebook/react-native/issues/36182`](https://github.com/facebook/react-native/issues/36182), the typescript compiler doesn't know the `width`, `height` and `crossOrigin` props for the `Image` component although they are taken in account in the code, [docs](https://reactnative.dev/docs/image#crossorigin) and the flow types. ## Changelog [GENERAL] [FIXED] - Fix missing `height`, `width`, `crossOrigin` props on Typescript Image.d.ts file Pull Request resolved: https://github.com/facebook/react-native/pull/36196 Reviewed By: christophpurrer Differential Revision: D43406094 Pulled By: rshest fbshipit-source-id: 547ed142d7c39c361d195275b79b0885ef829ba1 --- Libraries/Image/Image.d.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Libraries/Image/Image.d.ts b/Libraries/Image/Image.d.ts index dd2c089e75a4be..3391ad1f93a265 100644 --- a/Libraries/Image/Image.d.ts +++ b/Libraries/Image/Image.d.ts @@ -254,6 +254,28 @@ export interface ImagePropsBase * See https://reactnative.dev/docs/image#alt */ alt?: string | undefined; + + /** + * Height of the image component. + * + * See https://reactnative.dev/docs/image#height + */ + height?: number | undefined; + + /** + * Width of the image component. + * + * See https://reactnative.dev/docs/image#width + */ + width?: number | undefined; + + /** + * Adds the CORS related header to the request. + * Similar to crossorigin from HTML. + * + * See https://reactnative.dev/docs/image#crossorigin + */ + crossOrigin?: 'anonymous' | 'use-credentials'; } export interface ImageProps extends ImagePropsBase { From 1629b9f0a11f42ff12c6dd06a20afb80067e4958 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 17 Feb 2023 19:10:41 -0800 Subject: [PATCH 54/81] Refactor BUCK file for WebPerformance (use TurboModule plugins) (#36197) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36197 [Changelog][Internal] This turns NativePerformance* module dependencies into "TurboModule plugins", which allows for more streamlined client integration (as it makes them register automatically once the dependency is there). Reviewed By: rubennorte Differential Revision: D43353204 fbshipit-source-id: 01d0089750a4873088dc4aefe34fd48693ee9791 --- BUCK | 23 +++++++++++++------ .../WebPerformance/NativePerformance.cpp | 13 +++++++++-- .../NativePerformanceObserver.cpp | 11 +++++++++ tools/build_defs/oss/rn_defs.bzl | 4 ++++ 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/BUCK b/BUCK index 898094984f338c..c3fd4340e199d7 100644 --- a/BUCK +++ b/BUCK @@ -12,7 +12,6 @@ load( "//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", - "CXX", "HERMES_BYTECODE_VERSION", "IOS", "RCT_IMAGE_DATA_DECODER_SOCKET", @@ -20,6 +19,7 @@ load( "RCT_URL_REQUEST_HANDLER_SOCKET", "YOGA_CXX_TARGET", "get_react_native_ios_target_sdk_version", + "react_cxx_module_plugin_provider", "react_fabric_component_plugin_provider", "react_module_plugin_providers", "react_native_root_target", @@ -28,6 +28,7 @@ load( "rn_apple_library", "rn_apple_xplat_cxx_library", "rn_extra_build_flags", + "rn_xplat_cxx_library", "subdir_glob", ) load("//tools/build_defs/third_party:yarn_defs.bzl", "yarn_workspace") @@ -1455,7 +1456,7 @@ rn_apple_xplat_cxx_library( ], ) -rn_apple_xplat_cxx_library( +rn_xplat_cxx_library( name = "RCTWebPerformance", srcs = glob([ "Libraries/WebPerformance/**/*.cpp", @@ -1465,15 +1466,23 @@ rn_apple_xplat_cxx_library( [("Libraries/WebPerformance", "*.h")], prefix = "RCTWebPerformance", ), - fbandroid_compiler_flags = [ - "-fexceptions", - "-frtti", - ], + compiler_flags_enable_exceptions = True, + compiler_flags_enable_rtti = True, labels = [ "depslint_never_remove", "pfh:ReactNative_CommonInfrastructurePlaceholder", ], - platforms = (ANDROID, APPLE, CXX), + platforms = (ANDROID, APPLE), + plugins = [ + react_cxx_module_plugin_provider( + name = "NativePerformanceCxx", + function = "NativePerformanceModuleProvider", + ), + react_cxx_module_plugin_provider( + name = "NativePerformanceObserverCxx", + function = "NativePerformanceObserverModuleProvider", + ), + ], visibility = ["PUBLIC"], deps = [ ":FBReactNativeSpecJSI", diff --git a/Libraries/WebPerformance/NativePerformance.cpp b/Libraries/WebPerformance/NativePerformance.cpp index 94b0f4c5413a07..fdb4a5c3777951 100644 --- a/Libraries/WebPerformance/NativePerformance.cpp +++ b/Libraries/WebPerformance/NativePerformance.cpp @@ -5,11 +5,20 @@ * LICENSE file in the root directory of this source tree. */ -#include "NativePerformance.h" -#include +#include + #include +#include "NativePerformance.h" #include "PerformanceEntryReporter.h" +#include "Plugins.h" + +std::shared_ptr NativePerformanceModuleProvider( + std::shared_ptr jsInvoker) { + return std::make_shared( + std::move(jsInvoker)); +} + namespace facebook::react { NativePerformance::NativePerformance(std::shared_ptr jsInvoker) diff --git a/Libraries/WebPerformance/NativePerformanceObserver.cpp b/Libraries/WebPerformance/NativePerformanceObserver.cpp index 200140fdae1e6b..d1fa750c7eb900 100644 --- a/Libraries/WebPerformance/NativePerformanceObserver.cpp +++ b/Libraries/WebPerformance/NativePerformanceObserver.cpp @@ -5,9 +5,20 @@ * LICENSE file in the root directory of this source tree. */ +#include + #include "NativePerformanceObserver.h" #include "PerformanceEntryReporter.h" +#include "Plugins.h" + +std::shared_ptr +NativePerformanceObserverModuleProvider( + std::shared_ptr jsInvoker) { + return std::make_shared( + std::move(jsInvoker)); +} + namespace facebook::react { NativePerformanceObserver::NativePerformanceObserver( diff --git a/tools/build_defs/oss/rn_defs.bzl b/tools/build_defs/oss/rn_defs.bzl index faaa4aea094660..85e088a9f1eb30 100644 --- a/tools/build_defs/oss/rn_defs.bzl +++ b/tools/build_defs/oss/rn_defs.bzl @@ -424,6 +424,10 @@ def react_module_plugin_providers(*args, **kwargs): def react_fabric_component_plugin_provider(name, native_class_func): return None +# C++ TurboModule plugins support (stubbed) +def react_cxx_module_plugin_provider(name, function): + return None + HERMES_BYTECODE_VERSION = -1 RCT_IMAGE_DATA_DECODER_SOCKET = None From 421df9ffd58092b1a2dec455a048edb6db1739de Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Sun, 19 Feb 2023 01:55:16 -0800 Subject: [PATCH 55/81] Enable NDEBUG in production builds (#36194) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36194 This change is the iOS equivalent of D43344120 (https://github.com/facebook/react-native/commit/8486e191a170d9eae4d1d628a7539dc9e3d13ea4), but for iOS. ## Changelog: [iOS][Fixed] - Turn on NDEBUG when pods are installed for production. Reviewed By: cortinico Differential Revision: D43388881 fbshipit-source-id: 5c16d3d7b4265e4ee2f265a5f992cffee30f3887 --- .../__tests__/new_architecture-test.rb | 36 +++++++++++++++++++ scripts/cocoapods/new_architecture.rb | 14 ++++++-- scripts/react_native_pods.rb | 2 +- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/scripts/cocoapods/__tests__/new_architecture-test.rb b/scripts/cocoapods/__tests__/new_architecture-test.rb index 35394fd1ae56d7..3b92f46208d285 100644 --- a/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -111,6 +111,42 @@ def test_modifyFlagsForNewArch_whenOnNewArch_updateFlags assert_equal(yoga_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited)") end + def test_modifyFlagsForNewArch_whenOnNewArchAndIsRelease_updateFlags + # Arrange + first_xcconfig = prepare_xcconfig("First") + second_xcconfig = prepare_xcconfig("Second") + react_core_debug_config = prepare_CXX_Flags_build_configuration("Debug") + react_core_release_config = prepare_CXX_Flags_build_configuration("Release") + yoga_debug_config = prepare_CXX_Flags_build_configuration("Debug") + yoga_release_config = prepare_CXX_Flags_build_configuration("Release") + + installer = prepare_installer_for_cpp_flags( + [ first_xcconfig, second_xcconfig ], + { + "React-Core" => [ react_core_debug_config, react_core_release_config ], + "Yoga" => [ yoga_debug_config, yoga_release_config ], + } + ) + # Act + NewArchitectureHelper.modify_flags_for_new_architecture(installer, true, is_release: true) + + # Assert + assert_equal(first_xcconfig.attributes["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DNDEBUG") + assert_equal(first_xcconfig.attributes["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(first_xcconfig.save_as_invocation, ["a/path/First.xcconfig"]) + assert_equal(second_xcconfig.attributes["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DNDEBUG") + assert_equal(second_xcconfig.attributes["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(second_xcconfig.save_as_invocation, ["a/path/Second.xcconfig"]) + assert_equal(react_core_debug_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DNDEBUG") + assert_equal(react_core_debug_config.build_settings["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(react_core_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DNDEBUG") + assert_equal(react_core_release_config.build_settings["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(yoga_debug_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(yoga_debug_config.build_settings["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(yoga_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DNDEBUG") + assert_equal(yoga_release_config.build_settings["OTHER_CFLAGS"], "$(inherited) -DNDEBUG") + end + # =================================== # # Test - install Modules Dependencies # # =================================== # diff --git a/scripts/cocoapods/new_architecture.rb b/scripts/cocoapods/new_architecture.rb index 90141cd004c98e..e8c63d1618f53b 100644 --- a/scripts/cocoapods/new_architecture.rb +++ b/scripts/cocoapods/new_architecture.rb @@ -38,15 +38,17 @@ def self.set_clang_cxx_language_standard_if_needed(installer) end end - def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) + def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled, is_release: false) unless is_new_arch_enabled return end - + ndebug_flag = (is_release ? " -DNDEBUG" : "") # Add RCT_NEW_ARCH_ENABLED to Target pods xcconfig installer.aggregate_targets.each do |aggregate_target| aggregate_target.xcconfigs.each do |config_name, config_file| - config_file.attributes['OTHER_CPLUSPLUSFLAGS'] = @@new_arch_cpp_flags + config_file.attributes['OTHER_CPLUSPLUSFLAGS'] = @@new_arch_cpp_flags + ndebug_flag + config_file.attributes['OTHER_CFLAGS'] = "$(inherited)" + ndebug_flag + xcconfig_path = aggregate_target.xcconfig_path(config_name) config_file.save_as(xcconfig_path) end @@ -59,6 +61,12 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled) config.build_settings['OTHER_CPLUSPLUSFLAGS'] = @@new_arch_cpp_flags end end + + target_installation_result.native_target.build_configurations.each do |config| + current_flags = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "" + config.build_settings['OTHER_CPLUSPLUSFLAGS'] = current_flags + ndebug_flag + config.build_settings['OTHER_CFLAGS'] = "$(inherited)" + ndebug_flag + end end end diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 89c558384e2c95..cd26f9f495535c 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -218,7 +218,7 @@ def react_native_post_install(installer, react_native_path = "../node_modules/re NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1" - NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled) + NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled, is_release: ENV['PRODUCTION'] == "1") Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green end From f8d8764e8f236e8495e7e5747bfe95162f3a165a Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 20 Feb 2023 05:52:20 -0800 Subject: [PATCH 56/81] RNGP - Fix defaults for PrivateReactExtension Summary: When building from source, the PrivateReactExtension is getting no defaults (or missing defaults). Specifically root should point to ../../ (as the build from source will originate from `./node_modules/react-native`). Without that root specified, all the subsequent paths are broken, specifically, the default being `../` causes the codegen to be searched inside: ``` project/node_modules/node_modules/react-native/codegen ``` which is broken Changelog: [Internal] [Changed] - RNGP - Fix defaults for PrivateReactExtension Reviewed By: cipolleschi Differential Revision: D43435590 fbshipit-source-id: 2ed5e26c1d63fd808fc2d559ea83d6d39d106ff6 --- .../react/internal/PrivateReactExtension.kt | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt index e0de3b1ed26281..056111f7f58800 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/internal/PrivateReactExtension.kt @@ -25,11 +25,32 @@ abstract class PrivateReactExtension @Inject constructor(project: Project) { private val objects = project.objects - val root: DirectoryProperty = objects.directoryProperty() - - val reactNativeDir: DirectoryProperty = objects.directoryProperty() - - val nodeExecutableAndArgs: ListProperty = objects.listProperty(String::class.java) - - val codegenDir: DirectoryProperty = objects.directoryProperty() + val root: DirectoryProperty = + objects + .directoryProperty() + .convention( + // This is the default for the project root if the users hasn't specified anything. + // If the project is called "react-native-github" + // - We're inside the Github Repo -> root is defined by RN Tester (so no default + // needed) + // - We're inside an includedBuild as we're performing a build from source + // (then we're inside `node_modules/react-native`, so default should be ../../) + // If the project is called in any other name + // - We're inside a user project, so inside the ./android folder. Default should be + // ../ + // User can always override this default by setting a `root =` inside the template. + if (project.rootProject.name == "react-native-github") { + project.rootProject.layout.projectDirectory.dir("../../") + } else { + project.rootProject.layout.projectDirectory.dir("../") + }) + + val reactNativeDir: DirectoryProperty = + objects.directoryProperty().convention(root.dir("node_modules/react-native")) + + val nodeExecutableAndArgs: ListProperty = + objects.listProperty(String::class.java).convention(listOf("node")) + + val codegenDir: DirectoryProperty = + objects.directoryProperty().convention(root.dir("node_modules/@react-native/codegen")) } From 5d6f21d744d3a910eb82489404f0fe5dd1020d98 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 07:14:20 -0800 Subject: [PATCH 57/81] Make sure not to override user background color (#36215) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36215 When we introduced the RCTAppDelegate library, we prepared some template methods for the user to customise their views. However, after they customized their view, we were chaing the background color to match the system background. This would actually override the background color they set in their own customisation step. This change make sure that we set the background color before they apply their customisations. In this way, we set the background color and, if they want, they can change it and that changw would be honoured. This change also fixes [this issue](https://github.com/facebook/react-native/issues/35937) ## Changelog [iOS][Fixed] - Honour background color customisation in RCTAppDelegate Reviewed By: cortinico Differential Revision: D43435946 fbshipit-source-id: cdbdbd5b07082ae7843a4dab352dd1195c69e036 --- Libraries/AppDelegate/RCTAppDelegate.mm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Libraries/AppDelegate/RCTAppDelegate.mm b/Libraries/AppDelegate/RCTAppDelegate.mm index c7fc6e9b09dc76..ff822723accdcf 100644 --- a/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/Libraries/AppDelegate/RCTAppDelegate.mm @@ -54,12 +54,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( NSDictionary *initProps = [self prepareInitialProps]; UIView *rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; - if (@available(iOS 13.0, *)) { - rootView.backgroundColor = [UIColor systemBackgroundColor]; - } else { - rootView.backgroundColor = [UIColor whiteColor]; - } - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [self createRootViewController]; rootViewController.view = rootView; @@ -101,7 +95,14 @@ - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge #if RCT_NEW_ARCH_ENABLED enableFabric = self.fabricEnabled; #endif - return RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); + UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); + if (@available(iOS 13.0, *)) { + rootView.backgroundColor = [UIColor systemBackgroundColor]; + } else { + rootView.backgroundColor = [UIColor whiteColor]; + } + + return rootView; } - (UIViewController *)createRootViewController From a80578afc456c352edb52fc9b7e19899553a359a Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Mon, 20 Feb 2023 09:47:24 -0800 Subject: [PATCH 58/81] Remove `.node-version` file from repo root and template (#36208) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36208 IMO, there's no value in having `.node-version` files either in the repository or the template. I don't believe it's standard practice, the support from tooling is patchy (at least `nvm` [ignores it](https://github.com/nvm-sh/nvm/issues/794), and Node is often used without a version manager), and it's unnecessarily restrictive when it is actually enforced. In every other case, it's potentially misleading noise. Libraries should use `package.json#engines` to specify their Node JS compatibility ranges, as indeed `react-native` [already does](https://github.com/facebook/react-native/blob/1629b9f0a11f42ff12c6dd06a20afb80067e4958/package.json#L10). React Native users may wish to add one to their own projects according to their own setup or team, but we shouldn't confuse the issue by including an arbitrary one in the template. Changelog: [General][Removed] Remove `.node_version` from app template. Reviewed By: jacdebug, blakef Differential Revision: D43421085 fbshipit-source-id: 37a9b0fb7701f06fffb867dbc7ecac479b4d9c95 --- .node-version | 1 - template/_node-version | 1 - 2 files changed, 2 deletions(-) delete mode 100644 .node-version delete mode 100644 template/_node-version diff --git a/.node-version b/.node-version deleted file mode 100644 index 3c032078a4a21c..00000000000000 --- a/.node-version +++ /dev/null @@ -1 +0,0 @@ -18 diff --git a/template/_node-version b/template/_node-version deleted file mode 100644 index 3c032078a4a21c..00000000000000 --- a/template/_node-version +++ /dev/null @@ -1 +0,0 @@ -18 From afc91de79a8804696f05219214e0e67235d34d77 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Mon, 20 Feb 2023 09:47:24 -0800 Subject: [PATCH 59/81] Breaking - Bump minimum Node version from 14 to 16 (#36217) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36217 ## Bump minimum Node JS version to 16 via `react-native/package.json#engines` In https://github.com/facebook/react-native/pull/35443 we stopped running CI in Node 14 - this follows up by formally making Node 16 the minimum supported version ahead of the 0.72 cut. Node 14 [ends maintenance releases in April](https://github.com/nodejs/release#release-schedule), and bumping this minimum will allow other associated Node JS tools (CLI, Metro, Jest) to reduce their support burden. ## Insert `engines` into `template/package.json` The constraint at `react-native/package.json#engines` ensures the minimum at install/init time, with package managers providing an actionable error or warning if the constraint is not met. However, it doesn't help guide users to a supported version if on an existing project they run (e.g.) `yarn start`. Adding a constraint to the template helps prevent accidental use of an older version, as well as providing a clear reference for the current minimum. Insertion of `engines` below existing `package.json` fields is consistent with [`sort-package-json`](https://github.com/keithamus/sort-package-json/blob/main/defaultRules.md) and [`prettier-package-json`](https://github.com/cameronhunter/prettier-package-json/blob/main/src/defaultOptions.ts) - and keeps it out of the way of fields RN developers are likely to be more concerned about. ## Docs PR https://github.com/facebook/react-native-website/pull/3580 ## Changelog: [General][Breaking] Bump minimum Node JS version to 16 Reviewed By: jacdebug Differential Revision: D43436883 fbshipit-source-id: 0b369487fe44fe777e6fedc2299973a5fddd06b2 --- package.json | 2 +- template/package.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6a8c70926ad977..a57a338e3f0325 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "MIT", "repository": "github:facebook/react-native", "engines": { - "node": ">=14" + "node": ">=16" }, "types": "types", "jest-junit": { diff --git a/template/package.json b/template/package.json index cf3b10d19e9e0e..817c5fccb243cd 100644 --- a/template/package.json +++ b/template/package.json @@ -28,5 +28,8 @@ "prettier": "^2.4.1", "react-test-renderer": "18.2.0", "typescript": "4.8.4" + }, + "engines": { + "node": ">=16" } } From 1cb46ea6c14455cf8805ddf1910de9f4d360f706 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Mon, 20 Feb 2023 09:53:56 -0800 Subject: [PATCH 60/81] bump package versions (#36218) Summary: Bumping RNGP as build from source on nightlies is broken ## Changelog [INTERNAL] - bump package versions Pull Request resolved: https://github.com/facebook/react-native/pull/36218 Test Plan: n/a Reviewed By: hoxyq Differential Revision: D43438374 Pulled By: cortinico fbshipit-source-id: 871b56eaba5bc35286882e459136703778dea514 --- packages/react-native-gradle-plugin/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-gradle-plugin/package.json b/packages/react-native-gradle-plugin/package.json index 9528c76da61702..80bf289623bc8a 100644 --- a/packages/react-native-gradle-plugin/package.json +++ b/packages/react-native-gradle-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/gradle-plugin", - "version": "0.72.3", + "version": "0.72.4", "description": "⚛️ Gradle Plugin for React Native", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/react-native-gradle-plugin", "repository": { From b77841d991d5d3fe12fec563629776d3bf7d9d5f Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Mon, 20 Feb 2023 09:57:32 -0800 Subject: [PATCH 61/81] Improvements in ReadableNativeMap locking mechanism (a follow up to D43398416) Summary: [Changelog][Internal] A follow-up, based on javache comments on D43398416 (https://github.com/facebook/react-native/commit/9aac13d4dc95925b57f03e7964fc7add6834e518) (post-land) - just some minor potential improvements for locking efficiency. Reviewed By: javache Differential Revision: D43438414 fbshipit-source-id: 0cf807a045a1f132d5481d3f6115a97869e93d65 --- .../react/bridge/ReadableNativeMap.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index 3dae1f0ba165d8..dc98eb248de5fb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -40,11 +40,12 @@ public static int getJNIPassCounter() { } private void ensureKeysAreImported() { + if (mKeys != null) { + return; + } synchronized (this) { - if (mKeys == null) { - mKeys = Assertions.assertNotNull(importKeys()); - mJniCallCounter++; - } + mKeys = Assertions.assertNotNull(importKeys()); + mJniCallCounter++; } } @@ -52,8 +53,8 @@ private HashMap getLocalMap() { if (mLocalMap != null) { return mLocalMap; } - ensureKeysAreImported(); synchronized (this) { + ensureKeysAreImported(); if (mLocalMap == null) { Object[] values = Assertions.assertNotNull(importValues()); mJniCallCounter++; @@ -75,9 +76,8 @@ private HashMap getLocalMap() { if (mLocalTypeMap != null) { return mLocalTypeMap; } - ensureKeysAreImported(); synchronized (this) { - // check that no other thread has already updated + ensureKeysAreImported(); if (mLocalTypeMap == null) { Object[] types = Assertions.assertNotNull(importTypes()); mJniCallCounter++; @@ -190,9 +190,10 @@ public int getInt(@NonNull String name) { @Override public @NonNull Iterator> getEntryIterator() { - ensureKeysAreImported(); - final String[] iteratorKeys = mKeys; synchronized (this) { + ensureKeysAreImported(); + + final String[] iteratorKeys = mKeys; final Object[] iteratorValues = Assertions.assertNotNull(importValues()); return new Iterator>() { From 36a64dc2bd9de52841a52c549f35b944020bdb53 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 11:50:10 -0800 Subject: [PATCH 62/81] Move the RCTAppsetuUtils to AppDelegate Summary: This change solve a Circular Dependency where - `React-Core` depends on `ReactCommon` because `RCTAppSetupUtils.h` (in Core) imports the `RCTTurboModuleManager` (from ReactCommon) - `RCTTurboModuleManager` in `ReactCommon` depends on `React-Core` because it imports several classes from it (e.g. the `RCTBridge` class) ## Changelog: [iOS][Breaking] - Moved the RCTAppSetupUtils to the AppDelegate library to break a dependency cycle Reviewed By: sammy-SC, dmytrorykun Differential Revision: D43089183 fbshipit-source-id: d7fc36a50811962caf7cff77bb45d42b8cdd4575 --- Libraries/AppDelegate/RCTAppDelegate.mm | 2 +- {React/AppSetup => Libraries/AppDelegate}/RCTAppSetupUtils.h | 0 {React/AppSetup => Libraries/AppDelegate}/RCTAppSetupUtils.mm | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename {React/AppSetup => Libraries/AppDelegate}/RCTAppSetupUtils.h (100%) rename {React/AppSetup => Libraries/AppDelegate}/RCTAppSetupUtils.mm (100%) diff --git a/Libraries/AppDelegate/RCTAppDelegate.mm b/Libraries/AppDelegate/RCTAppDelegate.mm index ff822723accdcf..5b48b26545a673 100644 --- a/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/Libraries/AppDelegate/RCTAppDelegate.mm @@ -6,8 +6,8 @@ */ #import "RCTAppDelegate.h" -#import #import +#import "RCTAppSetupUtils.h" #if RCT_NEW_ARCH_ENABLED #import diff --git a/React/AppSetup/RCTAppSetupUtils.h b/Libraries/AppDelegate/RCTAppSetupUtils.h similarity index 100% rename from React/AppSetup/RCTAppSetupUtils.h rename to Libraries/AppDelegate/RCTAppSetupUtils.h diff --git a/React/AppSetup/RCTAppSetupUtils.mm b/Libraries/AppDelegate/RCTAppSetupUtils.mm similarity index 100% rename from React/AppSetup/RCTAppSetupUtils.mm rename to Libraries/AppDelegate/RCTAppSetupUtils.mm From b1b2b8baafa5a221115a23b89cb77a230846c1d0 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 11:50:10 -0800 Subject: [PATCH 63/81] Update podspecs with the right search paths Summary: Update podspecs with the right search paths to include the required framework by every module. ## Changelog: [iOS][Changed] - Update search paths to support `use_frameworks!` with Fabric Reviewed By: sammy-SC, dmytrorykun Differential Revision: D43089372 fbshipit-source-id: 4bbfc4b98bd289d66ce4015429d581856d9c05b3 --- .../AppDelegate/React-RCTAppDelegate.podspec | 7 ++ Libraries/Blob/React-RCTBlob.podspec | 15 +++- Libraries/Image/React-RCTImage.podspec | 15 +++- Libraries/LinkingIOS/React-RCTLinking.podspec | 15 +++- .../React-RCTAnimation.podspec | 15 +++- Libraries/Network/React-RCTNetwork.podspec | 15 +++- .../React-RCTPushNotification.podspec | 15 +++- Libraries/Settings/React-RCTSettings.podspec | 15 +++- .../Vibration/React-RCTVibration.podspec | 15 +++- React-Core.podspec | 15 +++- React/CoreModules/React-CoreModules.podspec | 14 +++- React/React-RCTFabric.podspec | 28 +++++++- ReactCommon/React-Fabric.podspec | 70 ++++++++++--------- ReactCommon/ReactCommon.podspec | 3 + .../renderer/graphics/React-graphics.podspec | 19 ++++- 15 files changed, 225 insertions(+), 51 deletions(-) diff --git a/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/Libraries/AppDelegate/React-RCTAppDelegate.podspec index bf6c9b578717c1..763ae2d9874306 100644 --- a/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -24,6 +24,7 @@ is_new_arch_enabled = ENV[new_arch_enabled_flag] == "1" other_cflags = "$(inherited) -DRN_FABRIC_ENABLED " + folly_flags + (is_new_arch_enabled ? " -D"+"RCT_NEW_ARCH_ENABLED" : "") use_hermes = ENV['USE_HERMES'] == '1' +use_frameworks = ENV['USE_FRAMEWORKS'] != nil header_search_paths = [ "$(PODS_TARGET_SRCROOT)/ReactCommon", @@ -37,6 +38,12 @@ header_search_paths = [ ].concat(use_hermes ? [ "$(PODS_ROOT)/Headers/Public/React-hermes", "$(PODS_ROOT)/Headers/Public/hermes-engine" +] : []).concat(use_frameworks ? [ + "$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.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/react/nativemodule/core", + "$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios" ] : []).map{|p| "\"#{p}\""}.join(" ") Pod::Spec.new do |s| diff --git a/Libraries/Blob/React-RCTBlob.podspec b/Libraries/Blob/React-RCTBlob.podspec index b3a557dbaeac81..478e88ac11d40d 100644 --- a/Libraries/Blob/React-RCTBlob.podspec +++ b/Libraries/Blob/React-RCTBlob.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTBlob" s.version = version @@ -35,7 +48,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.dependency "RCT-Folly", folly_version diff --git a/Libraries/Image/React-RCTImage.podspec b/Libraries/Image/React-RCTImage.podspec index 5eb0fdbcf74b0e..8d8b944500aee1 100644 --- a/Libraries/Image/React-RCTImage.podspec +++ b/Libraries/Image/React-RCTImage.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTImage" s.version = version @@ -36,7 +49,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.dependency "RCT-Folly", folly_version diff --git a/Libraries/LinkingIOS/React-RCTLinking.podspec b/Libraries/LinkingIOS/React-RCTLinking.podspec index c975d321ee2f1b..ebe116458fdce5 100644 --- a/Libraries/LinkingIOS/React-RCTLinking.podspec +++ b/Libraries/LinkingIOS/React-RCTLinking.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTLinking" s.version = version @@ -36,7 +49,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.dependency "React-Codegen", version diff --git a/Libraries/NativeAnimation/React-RCTAnimation.podspec b/Libraries/NativeAnimation/React-RCTAnimation.podspec index a1e4126d4cba22..2b56669e2eef3b 100644 --- a/Libraries/NativeAnimation/React-RCTAnimation.podspec +++ b/Libraries/NativeAnimation/React-RCTAnimation.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTAnimation" s.version = version @@ -35,7 +48,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(" ") } s.dependency "RCT-Folly", folly_version diff --git a/Libraries/Network/React-RCTNetwork.podspec b/Libraries/Network/React-RCTNetwork.podspec index 6b57d3c3d0ab0c..0a062da6d26582 100644 --- a/Libraries/Network/React-RCTNetwork.podspec +++ b/Libraries/Network/React-RCTNetwork.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTNetwork" s.version = version @@ -35,7 +48,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.frameworks = "MobileCoreServices" diff --git a/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec b/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec index ce1f9da25f0bb9..fa35dd9eadfb59 100644 --- a/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec +++ b/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTPushNotification" s.version = version @@ -36,7 +49,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.framework = "UserNotifications" diff --git a/Libraries/Settings/React-RCTSettings.podspec b/Libraries/Settings/React-RCTSettings.podspec index c721a573670552..0ad2170b75dec5 100644 --- a/Libraries/Settings/React-RCTSettings.podspec +++ b/Libraries/Settings/React-RCTSettings.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTSettings" s.version = version @@ -36,7 +49,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.dependency "RCT-Folly", folly_version diff --git a/Libraries/Vibration/React-RCTVibration.podspec b/Libraries/Vibration/React-RCTVibration.podspec index 90ec1a6f0f70e4..87dd34c4fa136b 100644 --- a/Libraries/Vibration/React-RCTVibration.podspec +++ b/Libraries/Vibration/React-RCTVibration.podspec @@ -19,6 +19,19 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV["USE_FRAMEWORKS"] + header_search_paths = header_search_paths.concat([ + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) +end + Pod::Spec.new do |s| s.name = "React-RCTVibration" s.version = version @@ -36,7 +49,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') } s.frameworks = "AudioToolbox" diff --git a/React-Core.podspec b/React-Core.podspec index 31db1b23d9a3ed..b118716fbcd726 100644 --- a/React-Core.podspec +++ b/React-Core.podspec @@ -21,6 +21,7 @@ folly_version = '2021.07.22.00' boost_compiler_flags = '-Wno-documentation' use_hermes = ENV['USE_HERMES'] == '1' +use_frameworks = ENV['USE_FRAMEWORKS'] != nil header_subspecs = { 'CoreModulesHeaders' => 'React/CoreModules/**/*.h', @@ -36,6 +37,11 @@ header_subspecs = { 'RCTVibrationHeaders' => 'Libraries/Vibration/*.h', } +frameworks_search_paths = [] +frameworks_search_paths << "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-hermes\"" if use_hermes +frameworks_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon\"" if use_frameworks +frameworks_search_paths << "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric\"" if use_frameworks + header_search_paths = [ "$(PODS_TARGET_SRCROOT)/ReactCommon", "$(PODS_ROOT)/boost", @@ -47,6 +53,10 @@ header_search_paths = [ ].concat(use_hermes ? [ "$(PODS_ROOT)/Headers/Public/React-hermes", "$(PODS_ROOT)/Headers/Public/hermes-engine" +] : []).concat(use_frameworks ? [ + "$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers", + "$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios" ] : []).map{|p| "\"#{p}\""}.join(" ") Pod::Spec.new do |s| @@ -67,9 +77,8 @@ Pod::Spec.new do |s| "DEFINES_MODULE" => "YES", "GCC_PREPROCESSOR_DEFINITIONS" => "RCT_METRO_PORT=${RCT_METRO_PORT}", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - }.merge!(use_hermes ? { - "FRAMEWORK_SEARCH_PATHS" => "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-hermes\"" - } : {}) + "FRAMEWORK_SEARCH_PATHS" => frameworks_search_paths.join(" ") + } s.user_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\""} s.default_subspec = "Default" diff --git a/React/CoreModules/React-CoreModules.podspec b/React/CoreModules/React-CoreModules.podspec index 89f79da17b46d1..0b8d2a54a60a31 100644 --- a/React/CoreModules/React-CoreModules.podspec +++ b/React/CoreModules/React-CoreModules.podspec @@ -19,6 +19,18 @@ end folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' +header_search_paths = [ + "\"$(PODS_TARGET_SRCROOT)/React/CoreModules\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" +] + +if ENV['USE_FRAMEWORKS'] + header_search_paths.append("\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"") + header_search_paths.append("\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"") +end + Pod::Spec.new do |s| s.name = "React-CoreModules" s.version = version @@ -34,7 +46,7 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/React/CoreModules\" \"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + "HEADER_SEARCH_PATHS" => header_search_paths.join(" ") } s.dependency "React-Codegen", version diff --git a/React/React-RCTFabric.podspec b/React/React-RCTFabric.podspec index 8855651666aa5f..abbba8e56511e5 100644 --- a/React/React-RCTFabric.podspec +++ b/React/React-RCTFabric.podspec @@ -21,6 +21,26 @@ folly_compiler_flags = folly_flags + ' ' + '-Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.07.22.00' boost_compiler_flags = '-Wno-documentation' +header_search_paths = [ + "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"", + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"$(PODS_ROOT)/Headers/Private/React-Core\"", + "\"$(PODS_ROOT)/Headers/Public/React-Codegen\"", + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"", + +] + +if ENV['USE_FRAMEWORKS'] + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/textlayoutmanager/platform/ios\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/textinput/iostextinput\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"" +end + Pod::Spec.new do |s| s.name = "React-RCTFabric" s.version = version @@ -37,9 +57,11 @@ Pod::Spec.new do |s| s.header_dir = "React" s.module_name = "RCTFabric" s.framework = "JavaScriptCore" - s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/Headers/Private/React-Core\" \"$(PODS_ROOT)/Headers/Public/React-Codegen\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" } - s.xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/glog\" \"$(PODS_ROOT)/RCT-Folly\"", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags } + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => header_search_paths, + "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags, + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } s.dependency "React-Core", version s.dependency "React-Fabric", version diff --git a/ReactCommon/React-Fabric.podspec b/ReactCommon/React-Fabric.podspec index c2cc021ce8d57c..773e2c9464a371 100644 --- a/ReactCommon/React-Fabric.podspec +++ b/ReactCommon/React-Fabric.podspec @@ -35,6 +35,11 @@ Pod::Spec.new do |s| s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } + if ENV['USE_FRAMEWORKS'] + s.header_mappings_dir = './' + s.module_name = 'React_Fabric' + end + s.dependency folly_dep_name, folly_version s.dependency "React-graphics", version s.dependency "React-jsiexecutor", version @@ -49,7 +54,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/animations/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/animations/tests" ss.header_dir = "react/renderer/animations" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "attributedstring" do |ss| @@ -58,7 +62,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/attributedstring/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/attributedstring/tests" ss.header_dir = "react/renderer/attributedstring" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "butter" do |ss| @@ -67,22 +70,39 @@ Pod::Spec.new do |s| ss.source_files = "butter/**/*.{m,mm,cpp,h}" ss.exclude_files = "butter/tests" ss.header_dir = "butter" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "config" do |ss| ss.source_files = "react/config/*.{m,mm,cpp,h}" ss.header_dir = "react/config" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"" } end s.subspec "core" do |ss| + header_search_path = [ + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"", + "\"$(PODS_ROOT)/RCT-Folly\"" + ] + + if ENV['USE_FRAMEWORKS'] + header_search_path = header_search_path + [ + "\"$(PODS_TARGET_SRCROOT)\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Codegen/React_Codegen.framework/Headers\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/textlayoutmanager/platform/ios\"", + "\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/iostextinput\"" + ] + end + ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags ss.source_files = "react/renderer/core/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/core/tests" ss.header_dir = "react/renderer/core" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + ss.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => header_search_path.join(" ") + } end s.subspec "componentregistry" do |ss| @@ -90,7 +110,6 @@ Pod::Spec.new do |s| ss.compiler_flags = folly_compiler_flags ss.source_files = "react/renderer/componentregistry/**/*.{m,mm,cpp,h}" ss.header_dir = "react/renderer/componentregistry" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "componentregistrynative" do |ss| @@ -98,7 +117,6 @@ Pod::Spec.new do |s| ss.compiler_flags = folly_compiler_flags ss.source_files = "react/renderer/componentregistry/native/**/*.{m,mm,cpp,h}" ss.header_dir = "react/renderer/componentregistry/native" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "components" do |ss| @@ -108,7 +126,6 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/activityindicator/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/activityindicator/tests" sss.header_dir = "react/renderer/components/activityindicator" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "image" do |sss| @@ -117,7 +134,6 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/image/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/image/tests" sss.header_dir = "react/renderer/components/image" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "inputaccessory" do |sss| @@ -126,7 +142,6 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/inputaccessory/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/inputaccessory/tests" sss.header_dir = "react/renderer/components/inputaccessory" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "legacyviewmanagerinterop" do |sss| @@ -135,7 +150,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/legacyviewmanagerinterop/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/legacyviewmanagerinterop/tests" sss.header_dir = "react/renderer/components/legacyviewmanagerinterop" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/Headers/Private/React-Core\"" } + sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/Headers/Private/React-Core\"" } end ss.subspec "modal" do |sss| @@ -144,7 +159,6 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/modal/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/modal/tests" sss.header_dir = "react/renderer/components/modal" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end ss.subspec "root" do |sss| @@ -153,7 +167,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/root/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/root/tests" sss.header_dir = "react/renderer/components/root" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end ss.subspec "safeareaview" do |sss| @@ -162,7 +176,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/safeareaview/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/safeareaview/tests" sss.header_dir = "react/renderer/components/safeareaview" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end ss.subspec "scrollview" do |sss| @@ -171,7 +185,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/scrollview/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/scrollview/tests" sss.header_dir = "react/renderer/components/scrollview" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end ss.subspec "text" do |sss| @@ -180,7 +194,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/text/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/text/tests" sss.header_dir = "react/renderer/components/text" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end ss.subspec "textinput" do |sss| @@ -189,7 +203,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/textinput/iostextinput/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/textinput/iostextinput/tests" sss.header_dir = "react/renderer/components/iostextinput" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end ss.subspec "unimplementedview" do |sss| @@ -198,7 +212,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/unimplementedview/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/unimplementedview/tests" sss.header_dir = "react/renderer/components/unimplementedview" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end ss.subspec "view" do |sss| @@ -208,7 +222,7 @@ Pod::Spec.new do |s| sss.source_files = "react/renderer/components/view/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/view/tests" sss.header_dir = "react/renderer/components/view" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end end @@ -218,7 +232,6 @@ Pod::Spec.new do |s| ss.source_files = "react/debug/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/debug/tests" ss.header_dir = "react/debug" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "debug_renderer" do |ss| @@ -227,7 +240,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/debug/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/debug/tests" ss.header_dir = "react/renderer/debug" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "imagemanager" do |ss| @@ -239,7 +251,6 @@ Pod::Spec.new do |s| "react/renderer/imagemanager/platform/android", "react/renderer/imagemanager/platform/cxx" ss.header_dir = "react/renderer/imagemanager" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "mapbuffer" do |ss| @@ -248,7 +259,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/mapbuffer/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/mapbuffer/tests" ss.header_dir = "react/renderer/mapbuffer" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "mounting" do |ss| @@ -257,7 +267,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/mounting/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/mounting/tests" ss.header_dir = "react/renderer/mounting" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "scheduler" do |ss| @@ -265,7 +274,6 @@ Pod::Spec.new do |s| ss.compiler_flags = folly_compiler_flags ss.source_files = "react/renderer/scheduler/**/*.{m,mm,cpp,h}" ss.header_dir = "react/renderer/scheduler" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "templateprocessor" do |ss| @@ -274,7 +282,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/templateprocessor/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/templateprocessor/tests" ss.header_dir = "react/renderer/templateprocessor" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "textlayoutmanager" do |ss| @@ -287,7 +294,6 @@ Pod::Spec.new do |s| "react/renderer/textlayoutmanager/platform/android", "react/renderer/textlayoutmanager/platform/cxx" ss.header_dir = "react/renderer/textlayoutmanager" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "uimanager" do |ss| @@ -296,7 +302,6 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/uimanager/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/uimanager/tests" ss.header_dir = "react/renderer/uimanager" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } end s.subspec "telemetry" do |ss| @@ -305,7 +310,7 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/telemetry/**/*.{m,mm,cpp,h}" ss.exclude_files = "react/renderer/telemetry/tests" ss.header_dir = "react/renderer/telemetry" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" } + end s.subspec "leakchecker" do |ss| @@ -314,8 +319,7 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/leakchecker/**/*.{cpp,h}" ss.exclude_files = "react/renderer/leakchecker/tests" ss.header_dir = "react/renderer/leakchecker" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"", - "GCC_WARN_PEDANTIC" => "YES" } + ss.pod_target_xcconfig = { "GCC_WARN_PEDANTIC" => "YES" } end s.subspec "runtimescheduler" do |ss| @@ -324,14 +328,12 @@ Pod::Spec.new do |s| ss.source_files = "react/renderer/runtimescheduler/**/*.{cpp,h}" ss.exclude_files = "react/renderer/runtimescheduler/tests" ss.header_dir = "react/renderer/runtimescheduler" - ss.pod_target_xcconfig = {"HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"", - "GCC_WARN_PEDANTIC" => "YES" } + ss.pod_target_xcconfig = { "GCC_WARN_PEDANTIC" => "YES" } end s.subspec "utils" do |ss| ss.source_files = "react/utils/*.{m,mm,cpp,h}" ss.header_dir = "react/utils" - ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\""} end end diff --git a/ReactCommon/ReactCommon.podspec b/ReactCommon/ReactCommon.podspec index da424368772a11..8969091249cec7 100644 --- a/ReactCommon/ReactCommon.podspec +++ b/ReactCommon/ReactCommon.podspec @@ -36,6 +36,9 @@ Pod::Spec.new do |s| "USE_HEADERMAP" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", "GCC_WARN_PEDANTIC" => "YES" } + if ENV['USE_FRAMEWORKS'] + s.header_mappings_dir = './' + end # TODO (T48588859): Restructure this target to align with dir structure: "react/nativemodule/..." # Note: Update this only when ready to minimize breaking changes. diff --git a/ReactCommon/react/renderer/graphics/React-graphics.podspec b/ReactCommon/react/renderer/graphics/React-graphics.podspec index 8b2d2bf463d995..19cc4ea84a7acf 100644 --- a/ReactCommon/react/renderer/graphics/React-graphics.podspec +++ b/ReactCommon/react/renderer/graphics/React-graphics.podspec @@ -21,6 +21,13 @@ folly_version = '2021.07.22.00' boost_compiler_flags = '-Wno-documentation' Pod::Spec.new do |s| + source_files = "**/*.{m,mm,cpp,h}" + header_search_paths = [ + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_TARGET_SRCROOT)/../../../\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + ] + s.name = "React-graphics" s.version = version s.summary = "Fabric for React Native." @@ -30,13 +37,21 @@ Pod::Spec.new do |s| s.platforms = { :ios => "12.4" } s.source = source s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags - s.source_files = "**/*.{m,mm,cpp,h}" + s.source_files = source_files s.exclude_files = "tests", "platform/android", "platform/cxx" s.header_dir = "react/renderer/graphics" - s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_TARGET_SRCROOT)/../../../\" \"$(PODS_ROOT)/RCT-Folly\"" } + if ENV['USE_FRAMEWORKS'] + s.module_name = "React_graphics" + s.header_mappings_dir = "../../.." + header_search_paths = header_search_paths + ["\"$(PODS_TARGET_SRCROOT)/platform/ios\""] + end + + s.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", "HEADER_SEARCH_PATHS" => header_search_paths.join(" ") } + + s.dependency "glog" s.dependency "RCT-Folly/Fabric", folly_version s.dependency "React-Core/Default", version end From 6d349524201e150029202134910de445328072e8 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 11:50:10 -0800 Subject: [PATCH 64/81] Update ruby scripts to install the dependencies with `use_frameworks`. Summary: This diff update the Cocoapods scripts to install the proper dependencies and search paths when `use_frameworks!` is declared together with the New Architecture. Practically, it adds the right search paths to the codegen and the project files and makes sure that third party dependencies that leverage the `install_modules_dependencies` are populated with the right search paths for Frameworks. It also adds unit tests for the changes and the new methods introduced. ## Changelog: [iOS][Changed] - Properly install dependencies with `use_frameworks!` Reviewed By: sammy-SC, dmytrorykun Differential Revision: D43089869 fbshipit-source-id: 1981b6853f774fdb3dbe8d17ea37fd5154c54b25 --- .../cocoapods/__tests__/codegen_utils-test.rb | 43 ++++++++++-- scripts/cocoapods/__tests__/fabric-test.rb | 25 +++++-- .../__tests__/new_architecture-test.rb | 4 +- scripts/cocoapods/__tests__/utils-test.rb | 67 +++++++++++++++++++ scripts/cocoapods/codegen_utils.rb | 47 ++++++++++--- scripts/cocoapods/fabric.rb | 6 +- scripts/cocoapods/new_architecture.rb | 16 ++++- scripts/cocoapods/utils.rb | 26 +++++++ scripts/react_native_pods.rb | 5 +- 9 files changed, 211 insertions(+), 28 deletions(-) diff --git a/scripts/cocoapods/__tests__/codegen_utils-test.rb b/scripts/cocoapods/__tests__/codegen_utils-test.rb index f96221bd98cd9a..ebd28119520b03 100644 --- a/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -118,6 +118,25 @@ def testGetReactCodegenSpec_whenFabricEnabledAndScriptPhases_generatesAPodspec assert_equal(Pod::UI.collected_messages, ["[Codegen] Adding script_phases to React-Codegen."]) end + def testGetReactCodegenSpec_whenUseFrameworksAndNewArch_generatesAPodspec + # Arrange + ENV["USE_FRAMEWORKS"] = "static" + FileMock.files_to_read('package.json' => '{ "version": "99.98.97"}') + + # Act + podspec = CodegenUtils.new().get_react_codegen_spec( + 'package.json', + :fabric_enabled => true, + :hermes_enabled => true, + :script_phases => nil, + :file_manager => FileMock + ) + + # Assert + assert_equal(podspec, get_podspec_when_use_frameworks()) + assert_equal(Pod::UI.collected_messages, []) + end + # =============================== # # Test - GetCodegenConfigFromFile # # =============================== # @@ -503,7 +522,9 @@ def get_podspec_no_fabric_no_script 'ios' => '11.0', }, 'source_files' => "**/*.{h,mm,cpp}", - 'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" => + 'pod_target_xcconfig' => { + "FRAMEWORK_SEARCH_PATHS" => [], + "HEADER_SEARCH_PATHS" => [ "\"$(PODS_ROOT)/boost\"", "\"$(PODS_ROOT)/RCT-Folly\"", @@ -514,15 +535,16 @@ def get_podspec_no_fabric_no_script }, 'dependencies': { "FBReactNativeSpec": [], - "React-jsiexecutor": [], "RCT-Folly": [], "RCTRequired": [], "RCTTypeSafety": [], "React-Core": [], "React-jsi": [], - "hermes-engine": [], + "React-jsiexecutor": [], + "React-rncore": [], "ReactCommon/turbomodule/bridging": [], - "ReactCommon/turbomodule/core": [] + "ReactCommon/turbomodule/core": [], + "hermes-engine": [], } } end @@ -539,4 +561,17 @@ def get_podspec_fabric_and_script_phases(script_phases) return specs end + + def get_podspec_when_use_frameworks + specs = get_podspec_no_fabric_no_script() + + specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat(["\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric\""]) + specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.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)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"") + + specs[:dependencies].merge!({ + 'React-graphics': [], + }) + + return specs + end end diff --git a/scripts/cocoapods/__tests__/fabric-test.rb b/scripts/cocoapods/__tests__/fabric-test.rb index 9ded6bd22028e7..6ea4866f5dcbf3 100644 --- a/scripts/cocoapods/__tests__/fabric-test.rb +++ b/scripts/cocoapods/__tests__/fabric-test.rb @@ -16,12 +16,13 @@ def setup def teardown podSpy_cleanUp() + ENV['RCT_NEW_ARCH_ENABLED'] = "0" end # ================== # # TEST - setupFabric # # ================== # - def test_setupFabric_installsPods + def test_setupFabric_whenNewArchDisabled_installsPods # Arrange prefix = "../.." @@ -32,14 +33,30 @@ def test_setupFabric_installsPods check_installed_pods(prefix) end - def check_installed_pods(prefix) - assert_equal($podInvocationCount, 5) + def test_setupFabric_whenNewArchEnabled_installPods + # Arrange + prefix = "../.." + ENV['RCT_NEW_ARCH_ENABLED'] = "1" + + # Act + setup_fabric!(:react_native_path => prefix, new_arch_enabled: true) + + # Assert + check_installed_pods(prefix, install_rncore: false) + end + + def check_installed_pods(prefix, install_rncore: true) + assert_equal($podInvocationCount, install_rncore ? 5 : 4) check_pod("React-Fabric", :path => "#{prefix}/ReactCommon") - check_pod("React-rncore", :path => "#{prefix}/ReactCommon") check_pod("React-graphics", :path => "#{prefix}/ReactCommon/react/renderer/graphics") check_pod("React-RCTFabric", :path => "#{prefix}/React", :modular_headers => true) check_pod("RCT-Folly/Fabric", :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec") + if install_rncore + check_pod("React-rncore", :path => "#{prefix}/ReactCommon") + else + assert_nil($podInvocation["React-rncore"]) + end end def check_pod(name, path: nil, modular_headers: nil, podspec: nil) diff --git a/scripts/cocoapods/__tests__/new_architecture-test.rb b/scripts/cocoapods/__tests__/new_architecture-test.rb index 3b92f46208d285..f716703913536b 100644 --- a/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -159,7 +159,7 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths # Assert assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags) - assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\"") + assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${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}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1") assert_equal( @@ -190,7 +190,7 @@ def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompiler # Assert assert_equal(spec.compiler_flags, "-Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}") - assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\"") + assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${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}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") assert_equal( spec.dependencies, diff --git a/scripts/cocoapods/__tests__/utils-test.rb b/scripts/cocoapods/__tests__/utils-test.rb index 4dc3c30015ea99..9bcf81b38f58d6 100644 --- a/scripts/cocoapods/__tests__/utils-test.rb +++ b/scripts/cocoapods/__tests__/utils-test.rb @@ -533,8 +533,75 @@ def test_detectUseFrameworks_whenEnvNotSetAndDynamicFrameworks_setEnvVarToDynami assert_equal(Pod::UI.collected_messages, ["Framework build type is dynamic framework"]) assert_equal(ENV['USE_FRAMEWORKS'], 'dynamic') end + + # ============================ # + # Test - Update Search Paths # + # ============================ # + def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths + # Arrange + ENV['USE_FRAMEWORKS'] = 'static' + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + ReactNativePodsUtils.update_search_paths(installer) + + # Assert + user_project_mock.build_configurations.each do |config| + received_search_path = config.build_settings["HEADER_SEARCH_PATHS"] + expected_search_path = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples" + assert_equal(expected_search_path, received_search_path) + end + end + + def test_updateSearchPaths_whenNotUseFrameworks_addsSearchPaths + # Arrange + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + ReactNativePodsUtils.update_search_paths(installer) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_nil(config.build_settings["HEADER_SEARCH_PATHS"]) + end + end end + +# ===== # +# UTILS # +# ===== # + def prepare_empty_user_project_mock return UserProjectMock.new("a/path", [ BuildConfigurationMock.new("Debug"), diff --git a/scripts/cocoapods/codegen_utils.rb b/scripts/cocoapods/codegen_utils.rb index 826c4b63196415..1b7c86eceee654 100644 --- a/scripts/cocoapods/codegen_utils.rb +++ b/scripts/cocoapods/codegen_utils.rb @@ -72,10 +72,35 @@ def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fabric_enabled: false, hermes_enabled: true, script_phases: nil, file_manager: File) package = JSON.parse(file_manager.read(package_json_file)) version = package['version'] - + new_arch_disabled = ENV['RCT_NEW_ARCH_ENABLED'] != "1" + use_frameworks = ENV['USE_FRAMEWORKS'] != nil folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' boost_compiler_flags = '-Wno-documentation' + header_search_paths = [ + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", + "\"$(PODS_ROOT)/Headers/Private/React-Fabric\"", + "\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"", + ] + framework_search_paths = [] + + if use_frameworks + header_search_paths.concat([ + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"$(PODS_TARGET_SRCROOT)\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.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)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + ]) + + framework_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric\"" + end + spec = { 'name' => "React-Codegen", 'version' => version, @@ -90,17 +115,11 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa 'ios' => '11.0', }, 'source_files' => "**/*.{h,mm,cpp}", - 'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" => - [ - "\"$(PODS_ROOT)/boost\"", - "\"$(PODS_ROOT)/RCT-Folly\"", - "\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"", - "\"$(PODS_ROOT)/Headers/Private/React-Fabric\"", - "\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"", - ].join(' ') + 'pod_target_xcconfig' => { + "HEADER_SEARCH_PATHS" => header_search_paths.join(' '), + "FRAMEWORK_SEARCH_PATHS" => framework_search_paths }, 'dependencies': { - "FBReactNativeSpec": [], "React-jsiexecutor": [], "RCT-Folly": [], "RCTRequired": [], @@ -115,7 +134,6 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa if fabric_enabled spec[:'dependencies'].merge!({ 'React-graphics': [], - 'React-rncore': [], }); end @@ -129,6 +147,13 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa }); end + if new_arch_disabled + spec[:dependencies].merge!({ + 'React-rncore': [], + 'FBReactNativeSpec': [], + }) + end + if script_phases Pod::UI.puts "[Codegen] Adding script_phases to React-Codegen." spec[:'script_phases'] = script_phases diff --git a/scripts/cocoapods/fabric.rb b/scripts/cocoapods/fabric.rb index b694bb64d97210..546933aaefba3e 100644 --- a/scripts/cocoapods/fabric.rb +++ b/scripts/cocoapods/fabric.rb @@ -7,10 +7,12 @@ # It sets up the Fabric dependencies. # # @parameter react_native_path: relative path to react-native -def setup_fabric!(react_native_path: "../node_modules/react-native") +def setup_fabric!(react_native_path: "../node_modules/react-native", new_arch_enabled: false) pod 'React-Fabric', :path => "#{react_native_path}/ReactCommon" - pod 'React-rncore', :path => "#{react_native_path}/ReactCommon" pod 'React-graphics', :path => "#{react_native_path}/ReactCommon/react/renderer/graphics" pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true pod 'RCT-Folly/Fabric', :podspec => "#{react_native_path}/third-party-podspecs/RCT-Folly.podspec" + + + pod 'React-rncore', :path => "#{react_native_path}/ReactCommon" if !new_arch_enabled end diff --git a/scripts/cocoapods/new_architecture.rb b/scripts/cocoapods/new_architecture.rb index e8c63d1618f53b..7c6d62550b48a4 100644 --- a/scripts/cocoapods/new_architecture.rb +++ b/scripts/cocoapods/new_architecture.rb @@ -79,10 +79,20 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) current_config = hash["pod_target_xcconfig"] != nil ? hash["pod_target_xcconfig"] : {} current_headers = current_config["HEADER_SEARCH_PATHS"] != nil ? current_config["HEADER_SEARCH_PATHS"] : "" - boost_search_path = "\"$(PODS_ROOT)/boost\"" - + header_search_paths = ["\"$(PODS_ROOT)/boost\""] + if ENV['USE_FRAMEWORKS'] + header_search_paths << "\"$(PODS_ROOT)/DoubleConversion\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"" + end + header_search_paths_string = header_search_paths.join(" ") spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}" - current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ? boost_search_path : "#{current_headers} #{boost_search_path}" + current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ? + header_search_paths_string : + "#{current_headers} #{header_search_paths_string}" current_config["CLANG_CXX_LANGUAGE_STANDARD"] = @@cplusplus_version diff --git a/scripts/cocoapods/utils.rb b/scripts/cocoapods/utils.rb index 1edd1284750545..bb784b42edab20 100644 --- a/scripts/cocoapods/utils.rb +++ b/scripts/cocoapods/utils.rb @@ -185,4 +185,30 @@ def self.detect_use_frameworks(target_definition) ENV['USE_FRAMEWORKS'] = nil end end + + def self.update_search_paths(installer) + return if ENV['USE_FRAMEWORKS'] == nil + + projects = installer.aggregate_targets + .map{ |t| t.user_project } + .uniq{ |p| p.path } + .push(installer.pods_project) + + projects.each do |project| + project.build_configurations.each do |config| + header_search_paths = config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited)" + + if !header_search_paths.include?("${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios") + header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios" + header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core" + header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios" + header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples" + end + + config.build_settings["HEADER_SEARCH_PATHS"] = header_search_paths + end + + project.save() + end + end end diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index cd26f9f495535c..8aa438da9bca9c 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -82,7 +82,7 @@ def use_react_native! ( # The Pods which should be included in all projects pod 'FBLazyVector', :path => "#{prefix}/Libraries/FBLazyVector" - pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec" + pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec" if !new_arch_enabled pod 'RCTRequired', :path => "#{prefix}/Libraries/RCTRequired" pod 'RCTTypeSafety', :path => "#{prefix}/Libraries/TypeSafety", :modular_headers => true pod 'React', :path => "#{prefix}/" @@ -140,7 +140,7 @@ def use_react_native! ( if fabric_enabled checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled, $CODEGEN_OUTPUT_DIR) - setup_fabric!(:react_native_path => prefix) + setup_fabric!(:react_native_path => prefix, new_arch_enabled: new_arch_enabled) else relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) build_codegen!(prefix, relative_installation_root) @@ -214,6 +214,7 @@ def react_native_post_install(installer, react_native_path = "../node_modules/re ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer) ReactNativePodsUtils.fix_library_search_paths(installer) + ReactNativePodsUtils.update_search_paths(installer) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) From 5d175c6775d0c630fb53b41df4e2a08f15bd94a4 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 11:50:10 -0800 Subject: [PATCH 65/81] Break Circular Dependency between React-Codegen and React-Fabric (#36210) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36210 One of the circular dependencies we have in OSS was between React-Codegen and React-Fabric. React-Codegen generates component which has to depends on React-Fabric because they need to use the files contained in the `react/renderer/view` folder. React-Fabric contains some components that depends on RNCore, which was generated inside the React-Codegen folder. This change generates the RNCore components inside the `ReactCommon/react/renderer/components/rncore` folder, breaking the dependency as `rncore` folder is now contained by React-Fabric itself. **Fun Fact:** That's how it always should have been. There was already a line in the `.gitignore` to exclude the content of `ReactCommon/react/renderer/components/rncore` folder. I guess that with some of the refactoring/previous projects on Codegen, this requirements has slipped. ## Changelog: [iOS][Breaking] - generates RNCore components inside the ReactCommon folder and create a new pod for platform-specific ImageManager classes Reviewed By: sammy-SC, dmytrorykun Differential Revision: D43304641 fbshipit-source-id: ebb5033ce73dbcd03f880c3e204511fdce04b816 --- React/React-RCTFabric.podspec | 2 + ReactCommon/React-Fabric.podspec | 16 +++-- ReactCommon/React-rncore.podspec | 1 + .../platform/ios/React-ImageManager.podspec | 64 +++++++++++++++++++ .../renderer/imagemanager/ImageManager.mm | 2 +- .../renderer/imagemanager/ImageRequest.cpp | 2 +- .../renderer/imagemanager/RCTImageManager.h | 2 +- .../imagemanager/RCTSyncImageManager.h | 2 +- packages/rn-tester/Podfile | 2 +- packages/rn-tester/Podfile.lock | 36 ++++++++--- .../cocoapods/__tests__/codegen_utils-test.rb | 2 + scripts/cocoapods/__tests__/fabric-test.rb | 12 ++-- scripts/cocoapods/codegen_utils.rb | 1 + scripts/cocoapods/fabric.rb | 2 +- .../codegen/generate-artifacts-executor.js | 14 ++-- scripts/react_native_pods.rb | 8 +-- 16 files changed, 130 insertions(+), 38 deletions(-) create mode 100644 ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec diff --git a/React/React-RCTFabric.podspec b/React/React-RCTFabric.podspec index abbba8e56511e5..fbd3e6b04ac100 100644 --- a/React/React-RCTFabric.podspec +++ b/React/React-RCTFabric.podspec @@ -39,6 +39,7 @@ if ENV['USE_FRAMEWORKS'] header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/imagemanager/platform/ios\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\"" end Pod::Spec.new do |s| @@ -66,6 +67,7 @@ Pod::Spec.new do |s| s.dependency "React-Core", version s.dependency "React-Fabric", version s.dependency "React-RCTImage", version + s.dependency "React-ImageManager" s.dependency "RCT-Folly/Fabric", folly_version s.test_spec 'Tests' do |test_spec| diff --git a/ReactCommon/React-Fabric.podspec b/ReactCommon/React-Fabric.podspec index 773e2c9464a371..e439a5d7e634b1 100644 --- a/ReactCommon/React-Fabric.podspec +++ b/ReactCommon/React-Fabric.podspec @@ -81,7 +81,7 @@ Pod::Spec.new do |s| header_search_path = [ "\"$(PODS_ROOT)/boost\"", "\"$(PODS_TARGET_SRCROOT)/ReactCommon\"", - "\"$(PODS_ROOT)/RCT-Folly\"" + "\"$(PODS_ROOT)/RCT-Folly\"", ] if ENV['USE_FRAMEWORKS'] @@ -161,13 +161,19 @@ Pod::Spec.new do |s| sss.header_dir = "react/renderer/components/modal" end + ss.subspec "rncore" do |sss| + sss.dependency folly_dep_name, folly_version + sss.compiler_flags = folly_compiler_flags + sss.source_files = "react/renderer/components/rncore/**/*.{m,mm,cpp,h}" + sss.header_dir = "react/renderer/components/rncore" + end + ss.subspec "root" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags sss.source_files = "react/renderer/components/root/**/*.{m,mm,cpp,h}" sss.exclude_files = "react/renderer/components/root/tests" sss.header_dir = "react/renderer/components/root" - end ss.subspec "safeareaview" do |sss| @@ -243,13 +249,9 @@ Pod::Spec.new do |s| end s.subspec "imagemanager" do |ss| - ss.dependency "React-RCTImage", version ss.dependency folly_dep_name, folly_version ss.compiler_flags = folly_compiler_flags - ss.source_files = "react/renderer/imagemanager/**/*.{m,mm,cpp,h}" - ss.exclude_files = "react/renderer/imagemanager/tests", - "react/renderer/imagemanager/platform/android", - "react/renderer/imagemanager/platform/cxx" + ss.source_files = "react/renderer/imagemanager/*.{m,mm,cpp,h}" ss.header_dir = "react/renderer/imagemanager" end diff --git a/ReactCommon/React-rncore.podspec b/ReactCommon/React-rncore.podspec index e2708f721fbe3e..201af01640e1bd 100644 --- a/ReactCommon/React-rncore.podspec +++ b/ReactCommon/React-rncore.podspec @@ -37,5 +37,6 @@ Pod::Spec.new do |s| :js_srcs_dir => "#{react_native_path}/Libraries", :library_name => "rncore", :library_type => "components", + :output_dir => "#{react_native_path}/../ReactCommon" }) end diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec b/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec new file mode 100644 index 00000000000000..71438db28e71ef --- /dev/null +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/React-ImageManager.podspec @@ -0,0 +1,64 @@ +# 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 + +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +boost_compiler_flags = '-Wno-documentation' + +Pod::Spec.new do |s| + source_files = "**/*.{m,mm,cpp,h}" + header_search_paths = [ + "\"$(PODS_ROOT)/boost\"", + "\"$(PODS_TARGET_SRCROOT)/../../../\"", + "\"$(PODS_TARGET_SRCROOT)\"", + "\"$(PODS_ROOT)/RCT-Folly\"", + ] + + s.name = "React-ImageManager" + s.version = version + s.summary = "Fabric for React Native." + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Meta Platforms, Inc. and its affiliates" + s.platforms = { :ios => "12.4" } + s.source = source + s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + s.source_files = source_files + s.header_dir = "react/renderer/imagemanager" + + if ENV['USE_FRAMEWORKS'] + s.module_name = "React_ImageManager" + s.header_mappings_dir = "./" + header_search_paths = header_search_paths + [ + "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"", + "\"$(PODS_ROOT)/DoubleConversion\"", + "\"${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\"", + ] + end + + s.pod_target_xcconfig = { + "USE_HEADERMAP" => "NO", + "HEADER_SEARCH_PATHS" => header_search_paths.join(" "), + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + + s.dependency "RCT-Folly/Fabric" + s.dependency "React-Fabric" + s.dependency "React-Core/Default" + s.dependency "React-RCTImage" +end diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageManager.mm b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageManager.mm index 9b833ae1a43d94..637f0d942d0add 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageManager.mm +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageManager.mm @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#include "ImageManager.h" +#import #import #import diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp index 1998d291731502..3961d8d6d7f223 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -#include "ImageRequest.h" +#include namespace facebook { namespace react { diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.h b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.h index 88130fe075573f..da6223a542d222 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.h +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTImageManager.h @@ -7,7 +7,7 @@ #import -#import +#import "RCTImageManagerProtocol.h" NS_ASSUME_NONNULL_BEGIN diff --git a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h index c0ef180bc22d6e..395f65b9c6b110 100644 --- a/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h +++ b/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/RCTSyncImageManager.h @@ -7,7 +7,7 @@ #import -#import +#import "RCTImageManagerProtocol.h" NS_ASSUME_NONNULL_BEGIN diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index f79da133b67c5e..e3274bb2b66aa9 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -19,7 +19,7 @@ end def pods(target_name, options = {}, use_flipper: !IN_CI && !USE_FRAMEWORKS) project 'RNTesterPods.xcodeproj' - fabric_enabled = true + fabric_enabled = ENV['USE_FRAMEWORKS'] == 'dynamic' ? false : true # Hermes is now enabled by default. # The following line will only disable Hermes if the USE_HERMES envvar is SET to a value other than 1 (e.g. USE_HERMES=0). diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index a9654da05f8da7..b04b11a90ce393 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -127,6 +127,7 @@ PODS: - RCTRequired - RCTTypeSafety - React-Core + - React-Fabric - React-graphics - React-jsi - React-jsiexecutor @@ -398,6 +399,7 @@ PODS: - React-Fabric/components/inputaccessory (= 1000.0.0) - React-Fabric/components/legacyviewmanagerinterop (= 1000.0.0) - React-Fabric/components/modal (= 1000.0.0) + - React-Fabric/components/rncore (= 1000.0.0) - React-Fabric/components/root (= 1000.0.0) - React-Fabric/components/safeareaview (= 1000.0.0) - React-Fabric/components/scrollview (= 1000.0.0) @@ -449,6 +451,14 @@ PODS: - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) + - React-Fabric/components/rncore (1000.0.0): + - RCT-Folly/Fabric (= 2021.07.22.00) + - RCTRequired (= 1000.0.0) + - RCTTypeSafety (= 1000.0.0) + - React-graphics (= 1000.0.0) + - React-jsi (= 1000.0.0) + - React-jsiexecutor (= 1000.0.0) + - ReactCommon/turbomodule/core (= 1000.0.0) - React-Fabric/components/root (1000.0.0): - RCT-Folly/Fabric (= 2021.07.22.00) - RCTRequired (= 1000.0.0) @@ -545,7 +555,6 @@ PODS: - React-graphics (= 1000.0.0) - React-jsi (= 1000.0.0) - React-jsiexecutor (= 1000.0.0) - - React-RCTImage (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) - React-Fabric/leakchecker (1000.0.0): - RCT-Folly/Fabric (= 2021.07.22.00) @@ -629,6 +638,7 @@ PODS: - React-jsiexecutor (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) - React-graphics (1000.0.0): + - glog - RCT-Folly/Fabric (= 2021.07.22.00) - React-Core/Default (= 1000.0.0) - React-hermes (1000.0.0): @@ -642,6 +652,11 @@ PODS: - React-jsiexecutor (= 1000.0.0) - React-jsinspector (= 1000.0.0) - React-perflogger (= 1000.0.0) + - React-ImageManager (1000.0.0): + - RCT-Folly/Fabric + - React-Core/Default + - React-Fabric + - React-RCTImage - React-jsi (1000.0.0): - boost (= 1.76.0) - DoubleConversion @@ -688,6 +703,7 @@ PODS: - RCT-Folly/Fabric (= 2021.07.22.00) - React-Core (= 1000.0.0) - React-Fabric (= 1000.0.0) + - React-ImageManager - React-RCTImage (= 1000.0.0) - React-RCTImage (1000.0.0): - RCT-Folly (= 2021.07.22.00) @@ -825,6 +841,7 @@ DEPENDENCIES: - React-Fabric (from `../../ReactCommon`) - React-graphics (from `../../ReactCommon/react/renderer/graphics`) - React-hermes (from `../../ReactCommon/hermes`) + - React-ImageManager (from `../../ReactCommon/react/renderer/imagemanager/platform/ios`) - React-jsi (from `../../ReactCommon/jsi`) - React-jsiexecutor (from `../../ReactCommon/jsiexecutor`) - React-jsinspector (from `../../ReactCommon/jsinspector`) @@ -904,6 +921,8 @@ EXTERNAL SOURCES: :path: "../../ReactCommon/react/renderer/graphics" React-hermes: :path: "../../ReactCommon/hermes" + React-ImageManager: + :path: "../../ReactCommon/react/renderer/imagemanager/platform/ios" React-jsi: :path: "../../ReactCommon/jsi" React-jsiexecutor: @@ -975,13 +994,14 @@ SPEC CHECKSUMS: RCTTypeSafety: a41e253b4ed644708899857d912b2f50c7b6214d React: 2fc6c4c656cccd6753016528ad41199c16fd558e React-callinvoker: a7d5e883a83bb9bd3985b08be832c5e76451d18f - React-Codegen: 4f1e911c128928e425e11698ad7859dfd0f92e20 + React-Codegen: 1d5974f7b1384b458c5e38f1aad902d0bfce1c80 React-Core: 279a6e5ee79e88faa99157169b560c49635973d7 React-CoreModules: d3ee40954b381edc514301341e8b895febfc1848 React-cxxreact: aff243750dad852080636e615d7ae5639381735b - React-Fabric: 62b9929a7345f941d8833630f37d9440b2dda438 - React-graphics: cb8a85648695c60f33a00d732b985f734d1470d8 + React-Fabric: 6b5c30b6e60a85446cc5d3702fa262fd1fc15619 + React-graphics: e70886fff4b79bec3745de761900a770029591f2 React-hermes: 7f0e87d44b1c7cfbdd11aa3c070d04435fe75d57 + React-ImageManager: c22bb185bc1b1557071da61f929070ed56fb3859 React-jsi: e4c75a1cf727c8761908ac2eeb1084e47ba88a26 React-jsiexecutor: 8361f78286021782d885e0888bb059a4045c59b9 React-jsinspector: 9b56a373a6797114e1d89a7dffa98ee98af67a8f @@ -991,7 +1011,7 @@ SPEC CHECKSUMS: React-RCTAnimation: 6741f7be3e269e057c1426074cc70f34b56e114b React-RCTAppDelegate: 0b3b2c1e02c02f952f5033535ddb23d690e3b890 React-RCTBlob: fd1ee93e48aa67b0183346a59754375de93de63d - React-RCTFabric: db1d7fe55db4811b63ae4060078e7048ebb4a918 + React-RCTFabric: 533df4e11d99af97a78d4a400b4cab44925358e9 React-RCTImage: 055685a12c88939437f6520d9e7c120cd666cbf1 React-RCTLinking: b149b3ff1f96fa93fc445230b9c171adb0e5572c React-RCTNetwork: 21abb4231182651f48b7035beaa011b1ab7ae8f4 @@ -1000,14 +1020,14 @@ SPEC CHECKSUMS: React-RCTTest: 81ebfa8c2e1b0b482effe12485e6486dc0ff70d7 React-RCTText: 4e5ae05b778a0ed2b22b012af025da5e1a1c4e54 React-RCTVibration: ecfd04c1886a9c9a4e31a466c0fbcf6b36e92fde - React-rncore: 1235cadc4feaa607c9af12ca157b8ae991ade3a5 + React-rncore: 3ef1d281e86300d2c8f97625f4a2fcea6602c5d5 React-runtimeexecutor: c7b2cd6babf6cc50340398bfbb7a9da13c93093f ReactCommon: fdc30b91d89bfd2ed919c2cbccb460435f1f43f4 - ScreenshotManager: 37152a3841a53f2de5c0013c58835b8738894553 + ScreenshotManager: fb68e0677077569df974c9cbeaeb54f764d002ba SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 1b1a12ff3d86a10565ea7cbe057d42f5e5fb2a07 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 920fb3b0e3c9dbdf8d86707f80cf0e7f2dc85c70 +PODFILE CHECKSUM: 5f0460f3a7599f90e5d4759fdec7d7343fe7923d COCOAPODS: 1.11.3 diff --git a/scripts/cocoapods/__tests__/codegen_utils-test.rb b/scripts/cocoapods/__tests__/codegen_utils-test.rb index ebd28119520b03..4e1ea5a49dd095 100644 --- a/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -555,6 +555,7 @@ def get_podspec_fabric_and_script_phases(script_phases) specs[:dependencies].merge!({ 'React-graphics': [], 'React-rncore': [], + 'React-Fabric': [], }) specs[:'script_phases'] = script_phases @@ -570,6 +571,7 @@ def get_podspec_when_use_frameworks specs[:dependencies].merge!({ 'React-graphics': [], + 'React-Fabric': [], }) return specs diff --git a/scripts/cocoapods/__tests__/fabric-test.rb b/scripts/cocoapods/__tests__/fabric-test.rb index 6ea4866f5dcbf3..0b47cd891d0b4c 100644 --- a/scripts/cocoapods/__tests__/fabric-test.rb +++ b/scripts/cocoapods/__tests__/fabric-test.rb @@ -42,21 +42,17 @@ def test_setupFabric_whenNewArchEnabled_installPods setup_fabric!(:react_native_path => prefix, new_arch_enabled: true) # Assert - check_installed_pods(prefix, install_rncore: false) + check_installed_pods(prefix) end - def check_installed_pods(prefix, install_rncore: true) - assert_equal($podInvocationCount, install_rncore ? 5 : 4) + def check_installed_pods(prefix) + assert_equal($podInvocationCount, 5) check_pod("React-Fabric", :path => "#{prefix}/ReactCommon") check_pod("React-graphics", :path => "#{prefix}/ReactCommon/react/renderer/graphics") check_pod("React-RCTFabric", :path => "#{prefix}/React", :modular_headers => true) check_pod("RCT-Folly/Fabric", :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec") - if install_rncore - check_pod("React-rncore", :path => "#{prefix}/ReactCommon") - else - assert_nil($podInvocation["React-rncore"]) - end + check_pod("React-ImageManager", :path => "#{prefix}/ReactCommon/react/renderer/imagemanager/platform/ios") end def check_pod(name, path: nil, modular_headers: nil, podspec: nil) diff --git a/scripts/cocoapods/codegen_utils.rb b/scripts/cocoapods/codegen_utils.rb index 1b7c86eceee654..50362f260bf8d8 100644 --- a/scripts/cocoapods/codegen_utils.rb +++ b/scripts/cocoapods/codegen_utils.rb @@ -134,6 +134,7 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa if fabric_enabled spec[:'dependencies'].merge!({ 'React-graphics': [], + 'React-Fabric': [], }); end diff --git a/scripts/cocoapods/fabric.rb b/scripts/cocoapods/fabric.rb index 546933aaefba3e..4f18ac3f478a73 100644 --- a/scripts/cocoapods/fabric.rb +++ b/scripts/cocoapods/fabric.rb @@ -11,8 +11,8 @@ def setup_fabric!(react_native_path: "../node_modules/react-native", new_arch_en pod 'React-Fabric', :path => "#{react_native_path}/ReactCommon" pod 'React-graphics', :path => "#{react_native_path}/ReactCommon/react/renderer/graphics" pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true + pod 'React-ImageManager', :path => "#{react_native_path}/ReactCommon/react/renderer/imagemanager/platform/ios" pod 'RCT-Folly/Fabric', :podspec => "#{react_native_path}/third-party-podspecs/RCT-Folly.podspec" - pod 'React-rncore', :path => "#{react_native_path}/ReactCommon" if !new_arch_enabled end diff --git a/scripts/codegen/generate-artifacts-executor.js b/scripts/codegen/generate-artifacts-executor.js index 38a2b8f22493c7..5fa441f9f142b9 100644 --- a/scripts/codegen/generate-artifacts-executor.js +++ b/scripts/codegen/generate-artifacts-executor.js @@ -25,13 +25,16 @@ const RN_ROOT = path.join(__dirname, '../..'); const CODEGEN_DEPENDENCY_NAME = '@react-native/codegen'; const CODEGEN_REPO_PATH = `${RN_ROOT}/packages/react-native-codegen`; const CODEGEN_NPM_PATH = `${RN_ROOT}/../${CODEGEN_DEPENDENCY_NAME}`; -const CORE_LIBRARIES = new Set(['rncore', 'FBReactNativeSpec']); +const CORE_LIBRARIES_WITH_OUTPUT_FOLDER = { + rncore: path.join(RN_ROOT, 'ReactCommon'), + FBReactNativeSpec: null, +}; const REACT_NATIVE_DEPENDENCY_NAME = 'react-native'; // HELPERS function isReactNativeCoreLibrary(libraryName) { - return CORE_LIBRARIES.has(libraryName); + return libraryName in CORE_LIBRARIES_WITH_OUTPUT_FOLDER; } function executeNodeScript(node, script) { @@ -273,7 +276,6 @@ function handleInAppLibraries( } // CodeGen - function getCodeGenCliPath() { let codegenCliPath; if (fs.existsSync(CODEGEN_REPO_PATH)) { @@ -345,8 +347,10 @@ function generateCode(iosOutputDir, library, tmpDir, node, pathToSchema) { ); // Finally, copy artifacts to the final output directory. - fs.mkdirSync(iosOutputDir, {recursive: true}); - execSync(`cp -R ${tmpOutputDir}/* ${iosOutputDir}`); + const outputDir = + CORE_LIBRARIES_WITH_OUTPUT_FOLDER[library.config.name] ?? iosOutputDir; + fs.mkdirSync(outputDir, {recursive: true}); + execSync(`cp -R ${tmpOutputDir}/* ${outputDir}`); console.log(`[Codegen] Generated artifacts: ${iosOutputDir}`); } diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 8aa438da9bca9c..7baabeacf65237 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -99,7 +99,7 @@ def use_react_native! ( pod 'React-RCTText', :path => "#{prefix}/Libraries/Text" pod 'React-RCTVibration', :path => "#{prefix}/Libraries/Vibration" pod 'React-Core/RCTWebSocket', :path => "#{prefix}/" - + pod 'React-rncore', :path => "#{prefix}/ReactCommon" pod 'React-cxxreact', :path => "#{prefix}/ReactCommon/cxxreact" if hermes_enabled @@ -311,9 +311,9 @@ def use_react_native_codegen!(spec, options={}) # The final generated files will be created when this script is invoked at Xcode build time. :script => get_script_phases_no_codegen_discovery( react_native_path: react_native_path, - codegen_output_dir: $CODEGEN_OUTPUT_DIR, - codegen_module_dir: $CODEGEN_MODULE_DIR, - codegen_component_dir: $CODEGEN_COMPONENT_DIR, + codegen_output_dir: output_dir, + codegen_module_dir: output_dir_module, + codegen_component_dir: output_dir_component, library_name: library_name, library_type: library_type, js_srcs_pattern: js_srcs_pattern, From e7becb06c16718a38570ba3a06d5059276be4b23 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 11:50:10 -0800 Subject: [PATCH 66/81] Update RCTFabric to generate headers in the `React` folder when using Frameworks Summary: By leveraging the `PUBLIC_HEADERS_FOLDER_PATH` build settings of Xcode, we can instruct cocoapods to generate the frameworks Headers in a specific folder, for example the `React` folder. This allows us to maintain the `#include`/`#import` structure, even if the framework has a different name. However, we need to update the search paths to take into account this extra folder. ## Changelog: [iOS][Changed] - Generate RCTFabric framework's headers in the React folder Reviewed By: sammy-SC, dmytrorykun Differential Revision: D43425677 fbshipit-source-id: 94a4f3a3c7de86341b3ce3457704e6b8fb9a588e --- .gitignore | 1 + .../AppDelegate/React-RCTAppDelegate.podspec | 3 +- .../RCTFabricComponentsPlugins.h | 2 +- .../Mounting/RCTComponentViewFactory.mm | 22 ++++----- .../Mounting/RCTComponentViewRegistry.mm | 6 +-- React/Fabric/Mounting/RCTMountingManager.mm | 8 ++-- React/React-RCTFabric.podspec | 5 +- scripts/cocoapods/__tests__/codegen-test.rb | 46 +++++++++---------- .../cocoapods/__tests__/codegen_utils-test.rb | 19 +++++--- .../__tests__/new_architecture-test.rb | 4 +- scripts/cocoapods/codegen.rb | 7 ++- scripts/cocoapods/codegen_utils.rb | 12 +++-- scripts/cocoapods/fabric.rb | 2 - scripts/cocoapods/new_architecture.rb | 1 + .../codegen/generate-artifacts-executor.js | 6 ++- scripts/react_native_pods.rb | 4 +- 16 files changed, 81 insertions(+), 67 deletions(-) diff --git a/.gitignore b/.gitignore index bab54701df6ae2..4db4e83235ccae 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,7 @@ package-lock.json /packages/react-native-codegen/tmp/ /ReactCommon/react/renderer/components/rncore/ /packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec* +/**/RCTThirdPartyFabricComponentsProvider.* # Additional SDKs diff --git a/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/Libraries/AppDelegate/React-RCTAppDelegate.podspec index 763ae2d9874306..ccc57afe0688d0 100644 --- a/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -43,7 +43,8 @@ header_search_paths = [ "$(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/react/nativemodule/core", - "$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios" + "$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios", + "$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers/", ] : []).map{|p| "\"#{p}\""}.join(" ") Pod::Spec.new do |s| diff --git a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h index 1a4bdaa25e3d65..6ce762210f0e99 100644 --- a/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h +++ b/React/Fabric/Mounting/ComponentViews/RCTFabricComponentsPlugins.h @@ -17,7 +17,7 @@ // OSS-compatibility layer #import -#import +#import #import #pragma GCC diagnostic push diff --git a/React/Fabric/Mounting/RCTComponentViewFactory.mm b/React/Fabric/Mounting/RCTComponentViewFactory.mm index f174ba1dfe3a90..0fe7f13d286722 100644 --- a/React/Fabric/Mounting/RCTComponentViewFactory.mm +++ b/React/Fabric/Mounting/RCTComponentViewFactory.mm @@ -23,19 +23,19 @@ #ifdef RN_DISABLE_OSS_PLUGIN_HEADER #import #else -#import "RCTFabricComponentsPlugins.h" +#import #endif -#import "RCTComponentViewClassDescriptor.h" -#import "RCTFabricComponentsPlugins.h" -#import "RCTImageComponentView.h" -#import "RCTLegacyViewManagerInteropComponentView.h" -#import "RCTMountingTransactionObserving.h" -#import "RCTParagraphComponentView.h" -#import "RCTRootComponentView.h" -#import "RCTTextInputComponentView.h" -#import "RCTUnimplementedViewComponentView.h" -#import "RCTViewComponentView.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import diff --git a/React/Fabric/Mounting/RCTComponentViewRegistry.mm b/React/Fabric/Mounting/RCTComponentViewRegistry.mm index 63bd88e0f763de..624ffec0d5d35e 100644 --- a/React/Fabric/Mounting/RCTComponentViewRegistry.mm +++ b/React/Fabric/Mounting/RCTComponentViewRegistry.mm @@ -11,9 +11,9 @@ #import #import -#import "RCTImageComponentView.h" -#import "RCTParagraphComponentView.h" -#import "RCTViewComponentView.h" +#import +#import +#import #import diff --git a/React/Fabric/Mounting/RCTMountingManager.mm b/React/Fabric/Mounting/RCTMountingManager.mm index ec5b9152c39ff1..086849f2be4951 100644 --- a/React/Fabric/Mounting/RCTMountingManager.mm +++ b/React/Fabric/Mounting/RCTMountingManager.mm @@ -22,10 +22,10 @@ #import #import -#import "RCTComponentViewProtocol.h" -#import "RCTComponentViewRegistry.h" -#import "RCTConversions.h" -#import "RCTMountingTransactionObserverCoordinator.h" +#import +#import +#import +#import using namespace facebook::react; diff --git a/React/React-RCTFabric.podspec b/React/React-RCTFabric.podspec index fbd3e6b04ac100..0f9484b00b7841 100644 --- a/React/React-RCTFabric.podspec +++ b/React/React-RCTFabric.podspec @@ -40,6 +40,7 @@ if ENV['USE_FRAMEWORKS'] header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-ImageManager/React_ImageManager.framework/Headers\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"" end Pod::Spec.new do |s| @@ -62,7 +63,9 @@ Pod::Spec.new do |s| "HEADER_SEARCH_PATHS" => header_search_paths, "OTHER_CFLAGS" => "$(inherited) -DRN_FABRIC_ENABLED" + " " + folly_flags, "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" - } + }.merge!(ENV['USE_FRAMEWORKS'] != nil ? { + "PUBLIC_HEADERS_FOLDER_PATH" => "$(CONTENTS_FOLDER_PATH)/Headers/React" + }: {}) s.dependency "React-Core", version s.dependency "React-Fabric", version diff --git a/scripts/cocoapods/__tests__/codegen-test.rb b/scripts/cocoapods/__tests__/codegen-test.rb index bcd475e0a9eecd..2141638f2eae99 100644 --- a/scripts/cocoapods/__tests__/codegen-test.rb +++ b/scripts/cocoapods/__tests__/codegen-test.rb @@ -24,7 +24,7 @@ def setup @prefix = "../.." @third_party_provider_header = "RCTThirdPartyFabricComponentsProvider.h" - @third_party_provider_implementation = "RCTThirdPartyFabricComponentsProvider.cpp" + @third_party_provider_implementation = "RCTThirdPartyFabricComponentsProvider.mm" @base_path = "~/app/ios" @tmp_schema_list_file = "tmpSchemaList.txt" Pathname.pwd!(@base_path) @@ -47,19 +47,19 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenFileAlreadyExists_doNothing( # Arrange FileMock.mocked_existing_files([ - @base_path + "/build/" + @third_party_provider_header, - @base_path + "/build/" + @third_party_provider_implementation, + @prefix + "/React/Fabric/" + @third_party_provider_header, + @prefix + "/React/Fabric/" + @third_party_provider_implementation, ]) # Act - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, 'build', dir_manager: DirMock, file_manager: FileMock) + checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) # Assert assert_equal(Pathname.pwd_invocation_count, 1) assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/build/" + @third_party_provider_header, - @base_path + "/build/" + @third_party_provider_implementation, + @prefix + "/React/Fabric/" + @third_party_provider_header, + @prefix + "/React/Fabric/" + @third_party_provider_implementation, ]) assert_equal(DirMock.exist_invocation_params, []) assert_equal(Pod::UI.collected_messages, []) @@ -77,14 +77,14 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenHeaderMissingAndCodegenMissi # Act assert_raise { - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, 'build', dir_manager: DirMock, file_manager: FileMock) + checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) } # Assert assert_equal(Pathname.pwd_invocation_count, 1) assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/build/" + @third_party_provider_header + @prefix + "/React/Fabric/" + @third_party_provider_header ]) assert_equal(DirMock.exist_invocation_params, [ @base_path + "/"+ @prefix + "/packages/react-native-codegen", @@ -100,8 +100,8 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode # Arrange FileMock.mocked_existing_files([ - @base_path + "/build/" + @third_party_provider_header, - @base_path + "/build/tmpSchemaList.txt" + @prefix + "/React/Fabric/" + @third_party_provider_header, + @prefix + "/React/Fabric/tmpSchemaList.txt" ]) DirMock.mocked_existing_dirs([ @@ -110,15 +110,15 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode ]) # Act - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, 'build', dir_manager: DirMock, file_manager: FileMock) + checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) # Assert assert_equal(Pathname.pwd_invocation_count, 1) assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/build/" + @third_party_provider_header, - @base_path + "/build/" + @third_party_provider_implementation, - @base_path + "/build/tmpSchemaList.txt", + @prefix + "/React/Fabric/" + @third_party_provider_header, + @prefix + "/React/Fabric/" + @third_party_provider_implementation, + @prefix + "/React/Fabric/tmpSchemaList.txt", ]) assert_equal(DirMock.exist_invocation_params, [ @base_path + "/"+ @prefix + "/packages/react-native-codegen", @@ -127,7 +127,7 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode assert_equal(Pod::UI.collected_messages, ["[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider"]) assert_equal($collected_commands, []) assert_equal(FileMock.open_invocation_count, 1) - assert_equal(FileMock.open_files_with_mode[@base_path + "/build/tmpSchemaList.txt"], 'w') + assert_equal(FileMock.open_files_with_mode[@prefix + "/React/Fabric/tmpSchemaList.txt"], 'w') assert_equal(FileMock.open_files[0].collected_write, ["[]"]) assert_equal(FileMock.open_files[0].fsync_invocation_count, 1) assert_equal(Pod::Executable.executed_commands[0], { @@ -135,12 +135,12 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenImplementationMissingAndCode "arguments" => [ @base_path + "/" + @prefix + "/scripts/generate-provider-cli.js", "--platform", 'ios', - "--schemaListPath", @base_path + "/build/tmpSchemaList.txt", - "--outputDir", @base_path + "/build" + "--schemaListPath", @prefix + "/React/Fabric/tmpSchemaList.txt", + "--outputDir", @prefix + "/React/Fabric" ] }) assert_equal(FileMock.delete_invocation_count, 1) - assert_equal(FileMock.deleted_files, [@base_path + "/build/tmpSchemaList.txt"]) + assert_equal(FileMock.deleted_files, [ @prefix + "/React/Fabric/tmpSchemaList.txt"]) end def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen() @@ -150,14 +150,14 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen() codegen_cli_path, ]) # Act - checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, 'build', dir_manager: DirMock, file_manager: FileMock) + checkAndGenerateEmptyThirdPartyProvider!(@prefix, false, dir_manager: DirMock, file_manager: FileMock) # Assert assert_equal(Pathname.pwd_invocation_count, 1) assert_equal(Pod::Config.instance.installation_root.relative_path_from_invocation_count, 1) assert_equal(FileMock.exist_invocation_params, [ - @base_path + "/build/" + @third_party_provider_header, - @base_path + "/build/" + @tmp_schema_list_file + @prefix + "/React/Fabric/" + @third_party_provider_header, + @prefix + "/React/Fabric/" + @tmp_schema_list_file ]) assert_equal(DirMock.exist_invocation_params, [ @base_path + "/" + @prefix + "/packages/react-native-codegen", @@ -176,8 +176,8 @@ def testCheckAndGenerateEmptyThirdPartyProvider_whenBothMissing_buildCodegen() "arguments" => [ @base_path + "/" + @prefix + "/scripts/generate-provider-cli.js", "--platform", 'ios', - "--schemaListPath", @base_path + "/build/" + @tmp_schema_list_file, - "--outputDir", @base_path + "/build" + "--schemaListPath", @prefix + "/React/Fabric/" + @tmp_schema_list_file, + "--outputDir", @prefix + "/React/Fabric" ] }) end diff --git a/scripts/cocoapods/__tests__/codegen_utils-test.rb b/scripts/cocoapods/__tests__/codegen_utils-test.rb index 4e1ea5a49dd095..147d7a8f259aa3 100644 --- a/scripts/cocoapods/__tests__/codegen_utils-test.rb +++ b/scripts/cocoapods/__tests__/codegen_utils-test.rb @@ -417,9 +417,10 @@ def testCleanUpCodegenFolder_whenFolderDoesNotExists_markAsCleanupDone CodegenUtils.set_cleanup_done(false) codegen_dir = "build/generated/ios" ios_folder = '.' + rn_path = '../node_modules/react-native' # Act - CodegenUtils.clean_up_build_folder(@base_path, ios_folder, codegen_dir, dir_manager: DirMock, file_manager: FileMock) + CodegenUtils.clean_up_build_folder(rn_path, @base_path, ios_folder, codegen_dir, dir_manager: DirMock, file_manager: FileMock) # Assert assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 0) @@ -440,17 +441,23 @@ def testCleanUpCodegenFolder_whenFolderExists_deleteItAndSetCleanupDone "#{codegen_path}/react/components/MyComponent/ShadowNode.h", "#{codegen_path}/react/components/MyComponent/ShadowNode.mm", ] + rn_path = '../node_modules/react-native' + DirMock.mocked_existing_dirs(codegen_path) DirMock.mocked_existing_globs(globs, "#{codegen_path}/*") # Act - CodegenUtils.clean_up_build_folder(@base_path, ios_folder, codegen_dir, dir_manager: DirMock, file_manager: FileMock) + CodegenUtils.clean_up_build_folder(rn_path, @base_path, ios_folder, codegen_dir, dir_manager: DirMock, file_manager: FileMock) # Assert assert_equal(DirMock.exist_invocation_params, [codegen_path, codegen_path]) assert_equal(DirMock.glob_invocation, ["#{codegen_path}/*", "#{codegen_path}/*"]) - assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 1) - assert_equal(FileUtils::FileUtilsStorage.rmrf_paths, [globs]) + assert_equal(FileUtils::FileUtilsStorage.rmrf_invocation_count, 3) + assert_equal(FileUtils::FileUtilsStorage.rmrf_paths, [ + globs, + "#{rn_path}/React/Fabric/RCTThirdPartyFabricComponentsProvider.h", + "#{rn_path}/React/Fabric/RCTThirdPartyFabricComponentsProvider.mm", + ]) assert_equal(CodegenUtils.cleanup_done(), true) end @@ -566,8 +573,8 @@ def get_podspec_fabric_and_script_phases(script_phases) def get_podspec_when_use_frameworks specs = get_podspec_no_fabric_no_script() - specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat(["\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric\""]) - specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.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)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"") + specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat([]) + specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.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)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers\"") specs[:dependencies].merge!({ 'React-graphics': [], diff --git a/scripts/cocoapods/__tests__/new_architecture-test.rb b/scripts/cocoapods/__tests__/new_architecture-test.rb index f716703913536b..b9fef9c43d8bb3 100644 --- a/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -159,7 +159,7 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths # Assert assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags) - assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${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}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"") + assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${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}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1") assert_equal( @@ -190,7 +190,7 @@ def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompiler # Assert assert_equal(spec.compiler_flags, "-Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}") - assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${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}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"") + assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${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}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"") assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17") assert_equal( spec.dependencies, diff --git a/scripts/cocoapods/codegen.rb b/scripts/cocoapods/codegen.rb index 1cbcb0c7ecd15b..51b69c9ca17d22 100644 --- a/scripts/cocoapods/codegen.rb +++ b/scripts/cocoapods/codegen.rb @@ -34,18 +34,17 @@ def build_codegen!(react_native_path, relative_installation_root, dir_manager: D # Parameters: # - react_native_path: path to the react native framework # - new_arch_enabled: whether the New Architecture is enabled or not -# - codegen_output_dir: the output directory for the codegen # - dir_manager: a class that implements the `Dir` interface. Defaults to `Dir`, the Dependency can be injected for testing purposes. # - file_manager: a class that implements the `File` interface. Defaults to `File`, the Dependency can be injected for testing purposes. -def checkAndGenerateEmptyThirdPartyProvider!(react_native_path, new_arch_enabled, codegen_output_dir, dir_manager: Dir, file_manager: File) +def checkAndGenerateEmptyThirdPartyProvider!(react_native_path, new_arch_enabled, dir_manager: Dir, file_manager: File) return if new_arch_enabled relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) - output_dir = "#{relative_installation_root}/#{codegen_output_dir}" + output_dir = "#{react_native_path}/React/Fabric" provider_h_path = "#{output_dir}/RCTThirdPartyFabricComponentsProvider.h" - provider_cpp_path ="#{output_dir}/RCTThirdPartyFabricComponentsProvider.cpp" + provider_cpp_path ="#{output_dir}/RCTThirdPartyFabricComponentsProvider.mm" if(!file_manager.exist?(provider_h_path) || !file_manager.exist?(provider_cpp_path)) # build codegen diff --git a/scripts/cocoapods/codegen_utils.rb b/scripts/cocoapods/codegen_utils.rb index 50362f260bf8d8..658c97104c7d8f 100644 --- a/scripts/cocoapods/codegen_utils.rb +++ b/scripts/cocoapods/codegen_utils.rb @@ -95,10 +95,9 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa "\"$(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)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"" + "\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"", + "\"$(PODS_CONFIGURATION_BUILD_DIR)/React-RCTFabric/RCTFabric.framework/Headers\"", ]) - - framework_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric\"" end spec = { @@ -127,7 +126,7 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa "React-Core": [], "React-jsi": [], "ReactCommon/turbomodule/bridging": [], - "ReactCommon/turbomodule/core": [] + "ReactCommon/turbomodule/core": [], } } @@ -339,7 +338,7 @@ def self.cleanup_done return @@CLEANUP_DONE end - def self.clean_up_build_folder(app_path, ios_folder, codegen_dir, dir_manager: Dir, file_manager: File) + def self.clean_up_build_folder(rn_path, app_path, ios_folder, codegen_dir, dir_manager: Dir, file_manager: File) return if CodegenUtils.cleanup_done() CodegenUtils.set_cleanup_done(true) @@ -347,6 +346,9 @@ def self.clean_up_build_folder(app_path, ios_folder, codegen_dir, dir_manager: D return if !dir_manager.exist?(codegen_path) FileUtils.rm_rf(dir_manager.glob("#{codegen_path}/*")) + base_provider_path = file_manager.join(rn_path, 'React', 'Fabric', 'RCTThirdPartyFabricComponentsProvider') + FileUtils.rm_rf("#{base_provider_path}.h") + FileUtils.rm_rf("#{base_provider_path}.mm") CodegenUtils.assert_codegen_folder_is_empty(app_path, ios_folder, codegen_dir, dir_manager: dir_manager, file_manager: file_manager) end diff --git a/scripts/cocoapods/fabric.rb b/scripts/cocoapods/fabric.rb index 4f18ac3f478a73..1bd3cb2fb9db9b 100644 --- a/scripts/cocoapods/fabric.rb +++ b/scripts/cocoapods/fabric.rb @@ -13,6 +13,4 @@ def setup_fabric!(react_native_path: "../node_modules/react-native", new_arch_en pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true pod 'React-ImageManager', :path => "#{react_native_path}/ReactCommon/react/renderer/imagemanager/platform/ios" pod 'RCT-Folly/Fabric', :podspec => "#{react_native_path}/third-party-podspecs/RCT-Folly.podspec" - - pod 'React-rncore', :path => "#{react_native_path}/ReactCommon" if !new_arch_enabled end diff --git a/scripts/cocoapods/new_architecture.rb b/scripts/cocoapods/new_architecture.rb index 7c6d62550b48a4..8cadc93b21d79e 100644 --- a/scripts/cocoapods/new_architecture.rb +++ b/scripts/cocoapods/new_architecture.rb @@ -87,6 +87,7 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\"" header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"" + header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric/RCTFabric.framework/Headers\"" end header_search_paths_string = header_search_paths.join(" ") spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}" diff --git a/scripts/codegen/generate-artifacts-executor.js b/scripts/codegen/generate-artifacts-executor.js index 5fa441f9f142b9..b006c5e597c244 100644 --- a/scripts/codegen/generate-artifacts-executor.js +++ b/scripts/codegen/generate-artifacts-executor.js @@ -401,6 +401,8 @@ function createComponentProvider( fs.closeSync(fd); console.log(`Generated schema list: ${schemaListTmpPath}`); + const outputDir = path.join(RN_ROOT, 'React', 'Fabric'); + // Generate FabricComponentProvider. // Only for iOS at this moment. executeNodeScript( @@ -409,9 +411,9 @@ function createComponentProvider( RN_ROOT, 'scripts', 'generate-provider-cli.js', - )} --platform ios --schemaListPath "${schemaListTmpPath}" --outputDir ${iosOutputDir}`, + )} --platform ios --schemaListPath "${schemaListTmpPath}" --outputDir ${outputDir}`, ); - console.log(`Generated provider in: ${iosOutputDir}`); + console.log(`Generated provider in: ${outputDir}`); } } diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 7baabeacf65237..7b66c7823d23ca 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -68,7 +68,7 @@ def use_react_native! ( # that has invoked the `use_react_native!` function. ReactNativePodsUtils.detect_use_frameworks(current_target_definition) - CodegenUtils.clean_up_build_folder(app_path, ios_folder, $CODEGEN_OUTPUT_DIR) + CodegenUtils.clean_up_build_folder(path, app_path, ios_folder, $CODEGEN_OUTPUT_DIR) # We are relying on this flag also in third parties libraries to proper install dependencies. # Better to rely and enable this environment flag if the new architecture is turned on using flags. @@ -139,7 +139,7 @@ def use_react_native! ( pod 'React-Codegen', :path => $CODEGEN_OUTPUT_DIR, :modular_headers => true if fabric_enabled - checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled, $CODEGEN_OUTPUT_DIR) + checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled) setup_fabric!(:react_native_path => prefix, new_arch_enabled: new_arch_enabled) else relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) From 23eb380f6556f97c333b8505e78bebf1e895951f Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 20 Feb 2023 11:50:10 -0800 Subject: [PATCH 67/81] Enable CircleCI tests for Use_Frameworks with the New Arch (#36148) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36148 This change enables 4 noew tests to make sure that `use_frameworks!` with the New Architecture don't break Note: We may have to publish the codegen to make this work on CircleCI properly ## Changelog: [iOS][Added] - Added tests for use_frameworks! with the new architecture Reviewed By: cortinico, dmytrorykun Differential Revision: D43271625 fbshipit-source-id: fe1fa4be660f933e0113f44a0467eaa1fa3669ca --- .circleci/config.yml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index af45646a49a712..e8b1d799f7c1f4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1659,11 +1659,6 @@ workflows: jsengine: "Hermes" flipper: "WithFlipper" use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithoutFlipper" - use_frameworks: "StaticFrameworks" - architecture: "NewArch" flavor: "Release" jsengine: "Hermes" @@ -1684,11 +1679,6 @@ workflows: jsengine: "JSC" flipper: "WithFlipper" use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithoutFlipper" - use_frameworks: "StaticFrameworks" - architecture: "NewArch" flavor: "Release" jsengine: "JSC" @@ -1729,21 +1719,11 @@ workflows: jsengine: "Hermes" flipper: "WithFlipper" use_frameworks: "StaticFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithoutFlipper" - use_frameworks: "StaticFrameworks" - architecture: "NewArch" flavor: "Debug" jsengine: "JSC" flipper: "WithFlipper" use_frameworks: "StaticFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithoutFlipper" - use_frameworks: "StaticFrameworks" - architecture: "OldArch" flavor: "Debug" jsengine: "Hermes" From 8fae37eaeab0c75c0be2885ce9198131e4d74c92 Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 21 Feb 2023 00:30:16 -0800 Subject: [PATCH 68/81] Flipper to 0.182.0 (#36221) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36221 As the title says. allow-large-files Changelog: [Android] [Changed] - Flipper to 0.182.0 Reviewed By: lblasa Differential Revision: D43444516 fbshipit-source-id: 33c2cd4bdf98dc3f7037774003bfdfde2123d8cd --- packages/rn-tester/android/app/gradle.properties | 2 +- template/android/gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rn-tester/android/app/gradle.properties b/packages/rn-tester/android/app/gradle.properties index 89a9accfeb72a3..838ca18c4c1caa 100644 --- a/packages/rn-tester/android/app/gradle.properties +++ b/packages/rn-tester/android/app/gradle.properties @@ -10,7 +10,7 @@ android.useAndroidX=true android.enableJetifier=true # Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.174.0 +FLIPPER_VERSION=0.182.0 # RN-Tester is building with NewArch always enabled newArchEnabled=true diff --git a/template/android/gradle.properties b/template/android/gradle.properties index b56dd868f96e8f..a3b2fa12490544 100644 --- a/template/android/gradle.properties +++ b/template/android/gradle.properties @@ -25,7 +25,7 @@ android.useAndroidX=true android.enableJetifier=true # Version of flipper SDK to use with React Native -FLIPPER_VERSION=0.174.0 +FLIPPER_VERSION=0.182.0 # Use this property to specify which architecture you want to build. # You can also override it from the CLI using From 0e30c7b85321dda42783c6ea09b1955d006295e7 Mon Sep 17 00:00:00 2001 From: ArthurAssuncao Date: Tue, 21 Feb 2023 01:35:46 -0800 Subject: [PATCH 69/81] fix: conditional to include rn-tester and react-native-gradle-plugin in settings.gradle.kts (#36188) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Relative path in conditional IF in settings.gradle.kts doesn't work when it try to build (`yarn install-android-jsc`) a package that isn't in root dir and needs of react-native-gradle-plugin or when it try to run rn-tester. When trying to compile rn-tester (`yarn install-android-jsc` command) the error below: ```Shell arthur@assuncao � ~/projects/react-native-test/react-native/packages/rn-tester � � main � yarn install-android-jsc yarn run v1.22.19 $ ../../gradlew :packages:rn-tester:android:app:installJscDebug Starting a Gradle Daemon (subsequent builds will be faster) FAILURE: Build failed with an exception. * What went wrong: Project directory '/home/arthur/projects/react-native-test/react-native/packages/rn-tester' is not part of the build defined by settings file '/home/arthur/projects/react-native-test/react-native/settings.gradle.kts'. If this is an unrelated build, it must have its own settings file. * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. * Get more help at https://help.gradle.org BUILD FAILED in 8s error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. ``` ## Changelog [INTERNAL] [FIXED] - Fix conditional to include rn-tester and react-native-gradle-plugin in settings.gradle.kts. Pull Request resolved: https://github.com/facebook/react-native/pull/36188 Test Plan: Execute rn-tester like [(RN-Tester Readme)](https://github.com/facebook/react-native/blob/main/packages/rn-tester/README.md). After my changes, the output of `yarn install-android-jsc` is: ```Shell [... many of the other tasks completed above] > Task :packages:rn-tester:android:app:compileJscDebugJavaWithJavac Note: Some input files use or override a deprecated API. Note: Recompile with -Xlint:deprecation for details. > Task :packages:rn-tester:android:app:stripJscDebugDebugSymbols Unable to strip the following libraries, packaging them as they are: libicu_common.so. > Task :packages:rn-tester:android:app:installJscDebug Installing APK 'app-jsc-arm64-v8a-debug.apk' on 'ASUS_Z01KD - 8.0.0' for :packages:rn-tester:android:app:jsc-debug Installed on 1 device. BUILD SUCCESSFUL in 31m 53s 121 actionable tasks: 121 executed Done in 1913.92s. ``` This PR Resolves https://github.com/facebook/react-native/issues/36187 Reviewed By: rshest Differential Revision: D43393440 Pulled By: cortinico fbshipit-source-id: 824644aa77147b3747007908db11fe9c120ad92f --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 47ea26461d5496..f4dc00a0c2295b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,7 +17,7 @@ include(":ReactAndroid", ":ReactAndroid:hermes-engine", ":ReactAndroid:external- // If the ./packages folder exists, then we're inside the React Native repository. // If not, a users is consuming this project for a build from source. -if (File("./packages").exists()) { +if (File("${rootDir}/packages").exists()) { include(":packages:rn-tester:android:app") // Include this to enable codegen Gradle plugin. includeBuild("packages/react-native-gradle-plugin/") From 18b402cbd07f459748f970447b597a966bb2f00e Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Tue, 21 Feb 2023 01:39:51 -0800 Subject: [PATCH 70/81] refactor(bump-all-updated-packages): use tag instead of custom commit message (#36220) Summary: Having custom commit message script is not an option for `main` branch, because we have internal tooling, which strips `[x]` tags from commit messages before merging them into `main` branch. Instead of constant commit message, we are now using a tag which will be concatenated with the commit message, which was entered via interactive commit dialog, see demo below. ## Changelog [Internal] - updated validation in bumping packages script Pull Request resolved: https://github.com/facebook/react-native/pull/36220 Test Plan: https://user-images.githubusercontent.com/28902667/220163767-015bf37b-6914-4df2-84d9-aa25fb2887d3.mov Reviewed By: cortinico Differential Revision: D43443597 Pulled By: hoxyq fbshipit-source-id: 08e5e08524a1d934fbb35529e025358d7bf3b203 --- ...nd-and-publish-all-bumped-packages-test.js | 4 ++-- .../bump-all-updated-packages/index.js | 19 +++++++++++++++++-- scripts/monorepo/constants.js | 4 ++-- .../find-and-publish-all-bumped-packages.js | 8 ++++---- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js b/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js index 0a50307646d6b7..7ef3f9ca0de7e4 100644 --- a/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js +++ b/scripts/monorepo/__tests__/find-and-publish-all-bumped-packages-test.js @@ -9,7 +9,7 @@ const {spawnSync} = require('child_process'); -const {BUMP_COMMIT_MESSAGE} = require('../constants'); +const {PUBLISH_PACKAGES_TAG} = require('../constants'); const forEachPackage = require('../for-each-package'); const findAndPublishAllBumpedPackages = require('../find-and-publish-all-bumped-packages'); @@ -31,7 +31,7 @@ describe('findAndPublishAllBumpedPackages', () => { })); spawnSync.mockImplementationOnce(() => ({ - stdout: BUMP_COMMIT_MESSAGE, + stdout: `This is my commit message\n\n${PUBLISH_PACKAGES_TAG}`, })); expect(() => findAndPublishAllBumpedPackages()).toThrow( diff --git a/scripts/monorepo/bump-all-updated-packages/index.js b/scripts/monorepo/bump-all-updated-packages/index.js index 953851d7db1d5f..f3569660a99638 100644 --- a/scripts/monorepo/bump-all-updated-packages/index.js +++ b/scripts/monorepo/bump-all-updated-packages/index.js @@ -8,12 +8,13 @@ */ const chalk = require('chalk'); +const {execSync} = require('child_process'); const inquirer = require('inquirer'); const path = require('path'); const {echo, exec, exit} = require('shelljs'); const yargs = require('yargs'); -const {BUMP_COMMIT_MESSAGE} = require('../constants'); +const {PUBLISH_PACKAGES_TAG} = require('../constants'); const forEachPackage = require('../for-each-package'); const checkForGitChanges = require('../check-for-git-changes'); const bumpPackageVersion = require('./bump-package-version'); @@ -167,7 +168,21 @@ const main = async () => { return; } - exec(`git commit -a -m "${BUMP_COMMIT_MESSAGE}"`, {cwd: ROOT_LOCATION}); + // exec from shelljs currently does not support interactive input + // https://github.com/shelljs/shelljs/wiki/FAQ#running-interactive-programs-with-exec + execSync('git commit -a', {cwd: ROOT_LOCATION, stdio: 'inherit'}); + + const enteredCommitMessage = exec('git log -n 1 --format=format:%B', { + cwd: ROOT_LOCATION, + silent: true, + }).stdout.trim(); + const commitMessageWithTag = + enteredCommitMessage + `\n\n${PUBLISH_PACKAGES_TAG}`; + + exec(`git commit --amend -m "${commitMessageWithTag}"`, { + cwd: ROOT_LOCATION, + silent: true, + }); }) .then(() => echo()); } diff --git a/scripts/monorepo/constants.js b/scripts/monorepo/constants.js index fcbc5c51e3c16d..bc6188600cee5a 100644 --- a/scripts/monorepo/constants.js +++ b/scripts/monorepo/constants.js @@ -8,6 +8,6 @@ * @format */ -const BUMP_COMMIT_MESSAGE = '[ci][monorepo] bump package versions'; +const PUBLISH_PACKAGES_TAG = '@publish-packages-to-npm'; -module.exports = {BUMP_COMMIT_MESSAGE}; +module.exports = {PUBLISH_PACKAGES_TAG}; diff --git a/scripts/monorepo/find-and-publish-all-bumped-packages.js b/scripts/monorepo/find-and-publish-all-bumped-packages.js index f700f5c9c9889d..51d782d5c269a3 100644 --- a/scripts/monorepo/find-and-publish-all-bumped-packages.js +++ b/scripts/monorepo/find-and-publish-all-bumped-packages.js @@ -10,7 +10,7 @@ const path = require('path'); const {spawnSync} = require('child_process'); -const {BUMP_COMMIT_MESSAGE} = require('./constants'); +const {PUBLISH_PACKAGES_TAG} = require('./constants'); const forEachPackage = require('./for-each-package'); const ROOT_LOCATION = path.join(__dirname, '..', '..'); @@ -79,10 +79,10 @@ const findAndPublishAllBumpedPackages = () => { process.exit(1); } - const hasSpecificCommitMessage = - commitMessage.startsWith(BUMP_COMMIT_MESSAGE); + const hasSpecificPublishTag = + commitMessage.includes(PUBLISH_PACKAGES_TAG); - if (!hasSpecificCommitMessage) { + if (!hasSpecificPublishTag) { throw new Error( `Package ${packageManifest.name} was updated, but not through CI script`, ); From 726a40ce2878cac2387cbc057b1f03ca5b54ff82 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 21 Feb 2023 02:46:18 -0800 Subject: [PATCH 71/81] Fix catalyst instance lifecycle warnings on shutdown Summary: Callling `getReactApplicationContextIfActiveOrWarn` from `invalidate` will always warn because the context is deactivated, which is preventing us from cleaning up these listeners. Changelog: [Internal] Reviewed By: jehartzog Differential Revision: D43352929 fbshipit-source-id: f29564a290a6c93b2304865d445829f5e486d84f --- .../react/animated/NativeAnimatedModule.java | 13 +++++-------- .../react/bridge/ReactContextBaseJavaModule.java | 6 +++--- .../react/modules/appstate/AppStateModule.java | 5 +---- .../react/modules/deviceinfo/DeviceInfoModule.java | 8 ++++---- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java index 1c8f94d831a476..ed49e736c5c038 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java @@ -265,11 +265,9 @@ protected void doFrameGuarded(final long frameTimeNanos) { @Override public void initialize() { - ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); + super.initialize(); - if (reactApplicationContext != null) { - reactApplicationContext.addLifecycleEventListener(this); - } + getReactApplicationContext().addLifecycleEventListener(this); } @Override @@ -981,10 +979,9 @@ public void execute(NativeAnimatedNodesManager animatedNodesManager) { @Override public void invalidate() { - ReactApplicationContext context = getReactApplicationContextIfActiveOrWarn(); - if (context != null) { - context.removeLifecycleEventListener(this); - } + super.invalidate(); + + getReactApplicationContext().removeLifecycleEventListener(this); } /** diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContextBaseJavaModule.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContextBaseJavaModule.java index 2cb9fe9177afea..6aacb484a53647 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContextBaseJavaModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContextBaseJavaModule.java @@ -14,6 +14,7 @@ import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.ThreadConfined; +import com.facebook.react.common.ReactConstants; import com.facebook.react.common.build.ReactBuildConfig; /** @@ -59,11 +60,10 @@ protected final ReactApplicationContext getReactApplicationContext() { // We want to collect data about how often this happens, but SoftExceptions will cause a crash // in debug mode, which isn't usually desirable. String msg = "Catalyst Instance has already disappeared: requested by " + this.getName(); - String tag = "ReactContextBaseJavaModule"; if (ReactBuildConfig.DEBUG) { - FLog.w(tag, msg); + FLog.w(ReactConstants.TAG, msg); } else { - ReactSoftExceptionLogger.logSoftException(tag, new RuntimeException(msg)); + ReactSoftExceptionLogger.logSoftException(ReactConstants.TAG, new RuntimeException(msg)); } return null; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.java index 7474163298f481..aa9d02850dd42c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/appstate/AppStateModule.java @@ -117,9 +117,6 @@ public void removeListeners(double count) { public void invalidate() { super.invalidate(); - ReactApplicationContext applicationContext = getReactApplicationContextIfActiveOrWarn(); - if (applicationContext != null) { - applicationContext.removeLifecycleEventListener(this); - } + getReactApplicationContext().removeLifecycleEventListener(this); } } diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/DeviceInfoModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/DeviceInfoModule.java index 18290c82cc453a..f1bf37ee20e993 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/DeviceInfoModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/DeviceInfoModule.java @@ -26,7 +26,8 @@ @ReactModule(name = NativeDeviceInfoSpec.NAME) public class DeviceInfoModule extends NativeDeviceInfoSpec implements LifecycleEventListener { - private @Nullable ReactApplicationContext mReactApplicationContext; + private final @Nullable ReactApplicationContext mReactApplicationContext; + private float mFontScale; private @Nullable ReadableMap mPreviousDisplayMetrics; @@ -104,9 +105,8 @@ public void emitUpdateDimensionsEvent() { public void invalidate() { super.invalidate(); - ReactApplicationContext applicationContext = getReactApplicationContextIfActiveOrWarn(); - if (applicationContext != null) { - applicationContext.removeLifecycleEventListener(this); + if (mReactApplicationContext != null) { + mReactApplicationContext.removeLifecycleEventListener(this); } } } From 8be9dbfcc1a569f9fd0b2f22de6aaff7bd34acad Mon Sep 17 00:00:00 2001 From: Tarun Chauhan Date: Tue, 21 Feb 2023 03:46:38 -0800 Subject: [PATCH 72/81] consolidate parsers component schema to common root (#36219) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: > [Codegen 85] The parses/flow/components/schema.js and parses/typescript/components/schema.js are the same. Move the schema.js from the one of the two folders to the parsers common root. Delete the other. Update the references to use the shared file. Part of the Codegen ☂️ Issue https://github.com/facebook/react-native/issues/34872 ## Changelog [Internal] [Changed] - Consolidated the schema.js files for parses/flow/components and parses/typescript/components to a common root. Pull Request resolved: https://github.com/facebook/react-native/pull/36219 Test Plan: Run ```yarn jest react-native-codegen``` Reviewed By: christophpurrer Differential Revision: D43444666 Pulled By: cipolleschi fbshipit-source-id: 24d791fd3a8110730d3f6054497ea3a31549a5a5 --- .../parsers/__tests__/parsers-commons-test.js | 2 +- .../src/parsers/flow/components/index.js | 2 +- .../src/parsers/flow/parser.js | 2 +- .../src/parsers/parsers-commons.js | 2 +- .../parsers/{flow/components => }/schema.js | 4 +- .../parsers/typescript/components/index.js | 2 +- .../parsers/typescript/components/schema.js | 62 ------------------- .../src/parsers/typescript/parser.js | 2 +- 8 files changed, 8 insertions(+), 70 deletions(-) rename packages/react-native-codegen/src/parsers/{flow/components => }/schema.js (97%) delete mode 100644 packages/react-native-codegen/src/parsers/typescript/components/schema.js diff --git a/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js b/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js index 95ef4306ebee73..2d8d96175e8769 100644 --- a/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js +++ b/packages/react-native-codegen/src/parsers/__tests__/parsers-commons-test.js @@ -23,7 +23,7 @@ import { import type {ParserType} from '../errors'; const {Visitor} = require('../flow/Visitor'); -const {wrapComponentSchema} = require('../flow/components/schema'); +const {wrapComponentSchema} = require('../schema.js'); const {buildComponentSchema} = require('../flow/components'); const {buildModuleSchema} = require('../flow/modules'); const {isModuleRegistryCall} = require('../utils.js'); diff --git a/packages/react-native-codegen/src/parsers/flow/components/index.js b/packages/react-native-codegen/src/parsers/flow/components/index.js index 50026ebf6c1f7d..35106bcab38162 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/index.js +++ b/packages/react-native-codegen/src/parsers/flow/components/index.js @@ -11,7 +11,7 @@ 'use strict'; import type {TypeDeclarationMap} from '../../utils'; import type {CommandOptions} from './options'; -import type {ComponentSchemaBuilderConfig} from './schema.js'; +import type {ComponentSchemaBuilderConfig} from '../../schema.js'; const {getTypes} = require('../utils'); const {getCommands} = require('./commands'); diff --git a/packages/react-native-codegen/src/parsers/flow/parser.js b/packages/react-native-codegen/src/parsers/flow/parser.js index bdcaf3b9eca91a..1e12d7daae8fe2 100644 --- a/packages/react-native-codegen/src/parsers/flow/parser.js +++ b/packages/react-native-codegen/src/parsers/flow/parser.js @@ -28,7 +28,7 @@ const flowParser = require('flow-parser'); const {buildSchema} = require('../parsers-commons'); const {Visitor} = require('./Visitor'); const {buildComponentSchema} = require('./components'); -const {wrapComponentSchema} = require('./components/schema'); +const {wrapComponentSchema} = require('../schema.js'); const {buildModuleSchema} = require('./modules'); const fs = require('fs'); diff --git a/packages/react-native-codegen/src/parsers/parsers-commons.js b/packages/react-native-codegen/src/parsers/parsers-commons.js index 2509d384da96e8..0a674eb85f49ac 100644 --- a/packages/react-native-codegen/src/parsers/parsers-commons.js +++ b/packages/react-native-codegen/src/parsers/parsers-commons.js @@ -26,7 +26,7 @@ import type { import type {Parser} from './parser'; import type {ParserType} from './errors'; import type {ParserErrorCapturer, TypeDeclarationMap} from './utils'; -import type {ComponentSchemaBuilderConfig} from './flow/components/schema'; +import type {ComponentSchemaBuilderConfig} from './schema.js'; const { getConfigType, diff --git a/packages/react-native-codegen/src/parsers/flow/components/schema.js b/packages/react-native-codegen/src/parsers/schema.js similarity index 97% rename from packages/react-native-codegen/src/parsers/flow/components/schema.js rename to packages/react-native-codegen/src/parsers/schema.js index ec9447251c1d35..0fdf3c3751148a 100644 --- a/packages/react-native-codegen/src/parsers/flow/components/schema.js +++ b/packages/react-native-codegen/src/parsers/schema.js @@ -4,8 +4,8 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict * @format + * @flow strict */ 'use strict'; @@ -18,7 +18,7 @@ import type { ExtendsPropsShape, SchemaType, OptionsShape, -} from '../../../CodegenSchema.js'; +} from '../CodegenSchema.js'; export type ComponentSchemaBuilderConfig = $ReadOnly<{ filename: string, diff --git a/packages/react-native-codegen/src/parsers/typescript/components/index.js b/packages/react-native-codegen/src/parsers/typescript/components/index.js index d6c66d49a6330f..41b5c0e41c2e2e 100644 --- a/packages/react-native-codegen/src/parsers/typescript/components/index.js +++ b/packages/react-native-codegen/src/parsers/typescript/components/index.js @@ -12,7 +12,7 @@ import type {ExtendsPropsShape} from '../../../CodegenSchema.js'; import type {TypeDeclarationMap} from '../../utils'; import type {CommandOptions} from './options'; -import type {ComponentSchemaBuilderConfig} from './schema.js'; +import type {ComponentSchemaBuilderConfig} from '../../schema.js'; const {getTypes} = require('../utils'); const {getCommands} = require('./commands'); diff --git a/packages/react-native-codegen/src/parsers/typescript/components/schema.js b/packages/react-native-codegen/src/parsers/typescript/components/schema.js deleted file mode 100644 index ab165031cd25fb..00000000000000 --- a/packages/react-native-codegen/src/parsers/typescript/components/schema.js +++ /dev/null @@ -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 - * @flow strict - */ - -'use strict'; - -import type { - EventTypeShape, - NamedShape, - CommandTypeAnnotation, - PropTypeAnnotation, - ExtendsPropsShape, - SchemaType, - OptionsShape, -} from '../../../CodegenSchema.js'; - -export type ComponentSchemaBuilderConfig = $ReadOnly<{ - filename: string, - componentName: string, - extendsProps: $ReadOnlyArray, - events: $ReadOnlyArray, - props: $ReadOnlyArray>, - commands: $ReadOnlyArray>, - options?: ?OptionsShape, -}>; - -function wrapComponentSchema({ - filename, - componentName, - extendsProps, - events, - props, - options, - commands, -}: ComponentSchemaBuilderConfig): SchemaType { - return { - modules: { - [filename]: { - type: 'Component', - components: { - [componentName]: { - ...(options || {}), - extendsProps, - events, - props, - commands, - }, - }, - }, - }, - }; -} - -module.exports = { - wrapComponentSchema, -}; diff --git a/packages/react-native-codegen/src/parsers/typescript/parser.js b/packages/react-native-codegen/src/parsers/typescript/parser.js index 9b40a7da55b70a..84b2dc4c159be3 100644 --- a/packages/react-native-codegen/src/parsers/typescript/parser.js +++ b/packages/react-native-codegen/src/parsers/typescript/parser.js @@ -28,7 +28,7 @@ const babelParser = require('@babel/parser'); const {buildSchema} = require('../parsers-commons'); const {Visitor} = require('./Visitor'); const {buildComponentSchema} = require('./components'); -const {wrapComponentSchema} = require('./components/schema'); +const {wrapComponentSchema} = require('../schema.js'); const {buildModuleSchema} = require('./modules'); const fs = require('fs'); From 3e88fd01cecfa9c627506c8ab0081d1e4865862a Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 21 Feb 2023 04:17:26 -0800 Subject: [PATCH 73/81] Install the RuntimeScheduler when the New Architecture is enabled (#36209) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36209 ThisChange automatically enable the RuntimeScheduler when the new architecture is enabled, both on RNester and in the Template app. Note that no migration steps are required. ## Changelog [iOS][Changed] - Automatically install the RuntimeScheduler Reviewed By: sammy-SC Differential Revision: D43392059 fbshipit-source-id: 609ded9bdc3db13a0d54ff44d0d4687dfc8617a5 --- Libraries/AppDelegate/RCTAppDelegate.mm | 23 +++++--- Libraries/AppDelegate/RCTAppSetupUtils.h | 8 ++- Libraries/AppDelegate/RCTAppSetupUtils.mm | 25 +++++---- packages/rn-tester/RNTester/AppDelegate.mm | 37 ++++++++++--- scripts/cocoapods/__tests__/utils-test.rb | 62 ++++++++++++++++++++++ scripts/cocoapods/utils.rb | 22 ++++++++ scripts/react_native_pods.rb | 3 ++ 7 files changed, 154 insertions(+), 26 deletions(-) diff --git a/Libraries/AppDelegate/RCTAppDelegate.mm b/Libraries/AppDelegate/RCTAppDelegate.mm index 5b48b26545a673..d211a8732c8f33 100644 --- a/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/Libraries/AppDelegate/RCTAppDelegate.mm @@ -17,12 +17,15 @@ #import #import #import +#import +#import static NSString *const kRNConcurrentRoot = @"concurrentRoot"; @interface RCTAppDelegate () { std::shared_ptr _reactNativeConfig; facebook::react::ContextContainer::Shared _contextContainer; + std::shared_ptr _runtimeScheduler; } @end @@ -35,6 +38,10 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( BOOL enableTM = NO; #if RCT_NEW_ARCH_ENABLED enableTM = self.turboModuleEnabled; + + _contextContainer = std::make_shared(); + _reactNativeConfig = std::make_shared(); + _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); #endif RCTAppSetupPrepareApp(application, enableTM); @@ -43,9 +50,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; } #if RCT_NEW_ARCH_ENABLED - _contextContainer = std::make_shared(); - _reactNativeConfig = std::make_shared(); - _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge contextContainer:_contextContainer]; self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; @@ -112,13 +116,16 @@ - (UIViewController *)createRootViewController #if RCT_NEW_ARCH_ENABLED #pragma mark - RCTCxxBridgeDelegate - - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge { - self.turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge - delegate:self - jsInvoker:bridge.jsCallInvoker]; - return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager); + _runtimeScheduler = _runtimeScheduler = + std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); + std::shared_ptr callInvoker = + std::make_shared(_runtimeScheduler); + self.turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge delegate:self jsInvoker:callInvoker]; + _contextContainer->erase("RuntimeScheduler"); + _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); + return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager, _runtimeScheduler); } #pragma mark RCTTurboModuleManagerDelegate diff --git a/Libraries/AppDelegate/RCTAppSetupUtils.h b/Libraries/AppDelegate/RCTAppSetupUtils.h index 06e12d7317c421..990fb77ef1a224 100644 --- a/Libraries/AppDelegate/RCTAppSetupUtils.h +++ b/Libraries/AppDelegate/RCTAppSetupUtils.h @@ -31,11 +31,17 @@ #endif #if RCT_NEW_ARCH_ENABLED +// Forward declaration to decrease compilation coupling +namespace facebook::react { +class RuntimeScheduler; +} + RCT_EXTERN id RCTAppSetupDefaultModuleFromClass(Class moduleClass); std::unique_ptr RCTAppSetupDefaultJsExecutorFactory( RCTBridge *bridge, - RCTTurboModuleManager *turboModuleManager); + RCTTurboModuleManager *turboModuleManager, + std::shared_ptr const &runtimeScheduler); #endif #endif // __cplusplus diff --git a/Libraries/AppDelegate/RCTAppSetupUtils.mm b/Libraries/AppDelegate/RCTAppSetupUtils.mm index 4d58caebfe2e13..c7701867ecf9c7 100644 --- a/Libraries/AppDelegate/RCTAppSetupUtils.mm +++ b/Libraries/AppDelegate/RCTAppSetupUtils.mm @@ -21,6 +21,8 @@ // Fabric #import +#import +#import #endif #ifdef FB_SONARKIT_ENABLED @@ -96,7 +98,8 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) std::unique_ptr RCTAppSetupDefaultJsExecutorFactory( RCTBridge *bridge, - RCTTurboModuleManager *turboModuleManager) + RCTTurboModuleManager *turboModuleManager, + std::shared_ptr const &runtimeScheduler) { // Necessary to allow NativeModules to lookup TurboModules [bridge setRCTTurboModuleRegistry:turboModuleManager]; @@ -118,14 +121,18 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled) #else return std::make_unique( #endif - facebook::react::RCTJSIExecutorRuntimeInstaller([turboModuleManager, bridge](facebook::jsi::Runtime &runtime) { - if (!bridge || !turboModuleManager) { - return; - } - facebook::react::RuntimeExecutor syncRuntimeExecutor = - [&](std::function &&callback) { callback(runtime); }; - [turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; - })); + facebook::react::RCTJSIExecutorRuntimeInstaller( + [turboModuleManager, bridge, runtimeScheduler](facebook::jsi::Runtime &runtime) { + if (!bridge || !turboModuleManager) { + return; + } + if (runtimeScheduler) { + facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler); + } + facebook::react::RuntimeExecutor syncRuntimeExecutor = + [&](std::function &&callback) { callback(runtime); }; + [turboModuleManager installJSBindingWithRuntimeExecutor:syncRuntimeExecutor]; + })); } #endif diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 8fafba034302ba..a969c28201ae62 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -15,6 +15,10 @@ #endif #endif +#ifdef RCT_NEW_ARCH_ENABLED +#define RN_FABRIC_ENABLED +#endif + #if RCT_USE_HERMES #import #else @@ -48,6 +52,9 @@ #import #import +#import +#import +#import #endif #if DEBUG @@ -70,6 +77,7 @@ @interface AppDelegate () RCTSurfacePresenterBridgeAdapter *_bridgeAdapter; std::shared_ptr _reactNativeConfig; facebook::react::ContextContainer::Shared _contextContainer; + std::shared_ptr _runtimeScheduler; #endif RCTTurboModuleManager *_turboModuleManager; @@ -84,17 +92,18 @@ - (BOOL)application:(__unused UIApplication *)application didFinishLaunchingWith { RCTEnableTurboModule(YES); +#ifdef RN_FABRIC_ENABLED + _contextContainer = std::make_shared(); + _reactNativeConfig = std::make_shared(); + _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); +#endif + _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; // Appetizer.io params check NSDictionary *initProps = [self prepareInitialProps]; #ifdef RN_FABRIC_ENABLED - _contextContainer = std::make_shared(); - _reactNativeConfig = std::make_shared(); - - _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); - _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer]; _bridge.surfacePresenter = _bridgeAdapter.surfacePresenter; @@ -174,11 +183,19 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge #pragma mark - RCTCxxBridgeDelegate +// This function is called during +// `[[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];` - (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge { - _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge - delegate:self - jsInvoker:bridge.jsCallInvoker]; + std::shared_ptr callInvoker = bridge.jsCallInvoker; + +#ifdef RCT_NEW_ARCH_ENABLED + _runtimeScheduler = std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); + _contextContainer->erase("RuntimeScheduler"); + _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); + callInvoker = std::make_shared(_runtimeScheduler); +#endif + _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge delegate:self jsInvoker:callInvoker]; [bridge setRCTTurboModuleRegistry:_turboModuleManager]; #if RCT_DEV @@ -190,6 +207,7 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge #endif __weak __typeof(self) weakSelf = self; + #if RCT_USE_HERMES return std::make_unique( #else @@ -200,6 +218,9 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge return; } __typeof(self) strongSelf = weakSelf; + if (strongSelf && strongSelf->_runtimeScheduler) { + facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, strongSelf->_runtimeScheduler); + } if (strongSelf) { facebook::react::RuntimeExecutor syncRuntimeExecutor = [&](std::function &&callback) { callback(runtime); }; diff --git a/scripts/cocoapods/__tests__/utils-test.rb b/scripts/cocoapods/__tests__/utils-test.rb index 9bcf81b38f58d6..765c3426db35e5 100644 --- a/scripts/cocoapods/__tests__/utils-test.rb +++ b/scripts/cocoapods/__tests__/utils-test.rb @@ -597,6 +597,68 @@ def test_updateSearchPaths_whenNotUseFrameworks_addsSearchPaths end end +# ============================= # +# Test - Apply Flags For Fabric # +# ============================= # +def test_applyFlagsForFabric_whenFabricEnabled_addsTheFlag + # Arrange + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: true) + + # Assert + user_project_mock.build_configurations.each do |config| + received_cflags = config.build_settings["OTHER_CFLAGS"] + expected_cflags = "$(inherited) -DRN_FABRIC_ENABLED" + assert_equal(received_cflags, expected_cflags) + end + +end + +def test_applyFlagsForFabric_whenFabricDisabled_doNothing + # Arrange + first_target = prepare_target("FirstTarget") + second_target = prepare_target("SecondTarget") + third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle") + user_project_mock = UserProjectMock.new("a/path", [ + prepare_config("Debug"), + prepare_config("Release"), + ], + :native_targets => [ + first_target, + second_target + ] + ) + pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}}) + installer = InstallerMock.new(pods_projects_mock, [ + AggregatedProjectMock.new(user_project_mock) + ]) + + # Act + ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: false) + + # Assert + user_project_mock.build_configurations.each do |config| + assert_nil(config.build_settings["OTHER_CFLAGS"]) + end +end + # ===== # # UTILS # diff --git a/scripts/cocoapods/utils.rb b/scripts/cocoapods/utils.rb index bb784b42edab20..b8d29042d9c81a 100644 --- a/scripts/cocoapods/utils.rb +++ b/scripts/cocoapods/utils.rb @@ -131,6 +131,28 @@ def self.apply_mac_catalyst_patches(installer) end end + def self.apply_flags_for_fabric(installer, fabric_enabled: false) + return if !fabric_enabled + + fabric_flag = "-DRN_FABRIC_ENABLED" + projects = installer.aggregate_targets + .map{ |t| t.user_project } + .uniq{ |p| p.path } + .push(installer.pods_project) + + projects.each do |project| + project.build_configurations.each do |config| + cflags = config.build_settings["OTHER_CFLAGS"] ? config.build_settings["OTHER_CFLAGS"] : "$(inherited)" + + if !cflags.include?(fabric_flag) + cflags = "#{cflags} #{fabric_flag}" + end + config.build_settings["OTHER_CFLAGS"] = cflags + end + project.save() + end + end + private def self.fix_library_search_path(config) diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 7b66c7823d23ca..c83df4f397d29a 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -212,10 +212,13 @@ def react_native_post_install(installer, react_native_path = "../node_modules/re flipper_post_install(installer) end + fabric_enabled = ReactNativePodsUtils.has_pod(installer, 'React-Fabric') + ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer) ReactNativePodsUtils.fix_library_search_paths(installer) ReactNativePodsUtils.update_search_paths(installer) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) + ReactNativePodsUtils.apply_flags_for_fabric(installer, fabric_enabled: fabric_enabled) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1" From 753bccc47adc54e2b1b72997b296bce36bec276a Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 21 Feb 2023 05:46:37 -0800 Subject: [PATCH 74/81] Forward dynamic values where possibe Summary: Changelog: [Internal] Reviewed By: rshest Differential Revision: D42961391 fbshipit-source-id: d07f8627a59d43e762bddb0641b3961806e9a7ec --- .../react/bridge/ReadableNativeMap.java | 19 +------------------ .../jni/react/fabric/StateWrapperImpl.cpp | 10 +++------- .../src/main/jni/react/jni/NativeArray.cpp | 4 +--- .../src/main/jni/react/jni/NativeArray.h | 16 +++++++++++++--- .../src/main/jni/react/jni/NativeMap.cpp | 4 ++-- .../src/main/jni/react/jni/NativeMap.h | 14 ++++++++++---- .../jni/react/jni/ReadableNativeArray.cpp | 6 ------ .../main/jni/react/jni/ReadableNativeArray.h | 5 ++++- .../main/jni/react/jni/ReadableNativeMap.cpp | 18 +++++++++++------- 9 files changed, 45 insertions(+), 51 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index dc98eb248de5fb..0ade85c10090f1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -195,6 +195,7 @@ public int getInt(@NonNull String name) { final String[] iteratorKeys = mKeys; final Object[] iteratorValues = Assertions.assertNotNull(importValues()); + mJniCallCounter++; return new Iterator>() { int currentIndex = 0; @@ -289,22 +290,4 @@ public boolean equals(Object obj) { } return hashMap; } - - private static class ReadableNativeMapKeySetIterator implements ReadableMapKeySetIterator { - private final Iterator mIterator; - - public ReadableNativeMapKeySetIterator(ReadableNativeMap readableNativeMap) { - mIterator = readableNativeMap.getLocalMap().keySet().iterator(); - } - - @Override - public boolean hasNextKey() { - return mIterator.hasNext(); - } - - @Override - public String nextKey() { - return mIterator.next(); - } - } } diff --git a/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp b/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp index c336df5d9aa686..49e3f3ef825a4e 100644 --- a/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp +++ b/ReactAndroid/src/main/jni/react/fabric/StateWrapperImpl.cpp @@ -27,24 +27,20 @@ jni::local_ref StateWrapperImpl::initHybrid( jni::local_ref StateWrapperImpl::getStateDataImpl() { folly::dynamic map = state_->getDynamic(); - local_ref readableNativeMap = - ReadableNativeMap::newObjectCxxArgs(map); - return readableNativeMap; + return ReadableNativeMap::newObjectCxxArgs(std::move(map)); } jni::local_ref StateWrapperImpl::getStateMapBufferDataImpl() { MapBuffer map = state_->getMapBuffer(); - auto readableMapBuffer = - JReadableMapBuffer::createWithContents(std::move(map)); - return readableMapBuffer; + return JReadableMapBuffer::createWithContents(std::move(map)); } void StateWrapperImpl::updateStateImpl(NativeMap *map) { // Get folly::dynamic from map auto dynamicMap = map->consume(); // Set state - state_->updateState(dynamicMap); + state_->updateState(std::move(dynamicMap)); } void StateWrapperImpl::registerNatives() { diff --git a/ReactAndroid/src/main/jni/react/jni/NativeArray.cpp b/ReactAndroid/src/main/jni/react/jni/NativeArray.cpp index 09dd34c2652ffd..6d4337877e0e7b 100644 --- a/ReactAndroid/src/main/jni/react/jni/NativeArray.cpp +++ b/ReactAndroid/src/main/jni/react/jni/NativeArray.cpp @@ -7,7 +7,6 @@ #include "NativeArray.h" -#include #include using namespace facebook::jni; @@ -15,8 +14,7 @@ using namespace facebook::jni; namespace facebook { namespace react { -NativeArray::NativeArray(folly::dynamic array) - : isConsumed(false), array_(std::move(array)) { +void NativeArray::assertInternalType() { if (!array_.isArray()) { throwNewJavaException( exceptions::gUnexpectedNativeTypeExceptionClass, diff --git a/ReactAndroid/src/main/jni/react/jni/NativeArray.h b/ReactAndroid/src/main/jni/react/jni/NativeArray.h index b42083083a6bab..1e48e742c6bfe8 100644 --- a/ReactAndroid/src/main/jni/react/jni/NativeArray.h +++ b/ReactAndroid/src/main/jni/react/jni/NativeArray.h @@ -17,7 +17,7 @@ namespace react { class NativeArray : public jni::HybridClass { public: - static constexpr const char *kJavaDescriptor = + static auto constexpr *kJavaDescriptor = "Lcom/facebook/react/bridge/NativeArray;"; jni::local_ref toString(); @@ -27,7 +27,6 @@ class NativeArray : public jni::HybridClass { // Whether this array has been added to another array or map and no longer // has a valid array value. bool isConsumed; - void throwIfConsumed(); static void registerNatives(); @@ -35,7 +34,18 @@ class NativeArray : public jni::HybridClass { folly::dynamic array_; friend HybridBase; - explicit NativeArray(folly::dynamic array); + + template + explicit NativeArray(Dyn &&array) + : isConsumed(false), array_(std::forward(array)) { + assertInternalType(); + } + + void assertInternalType(); + void throwIfConsumed(); + + NativeArray(const NativeArray &) = delete; + NativeArray &operator=(const NativeArray &) = delete; }; } // namespace react diff --git a/ReactAndroid/src/main/jni/react/jni/NativeMap.cpp b/ReactAndroid/src/main/jni/react/jni/NativeMap.cpp index 9783ac15f4cb9c..ee581634e6d53c 100644 --- a/ReactAndroid/src/main/jni/react/jni/NativeMap.cpp +++ b/ReactAndroid/src/main/jni/react/jni/NativeMap.cpp @@ -14,9 +14,9 @@ using namespace facebook::jni; namespace facebook { namespace react { -std::string NativeMap::toString() { +local_ref NativeMap::toString() { throwIfConsumed(); - return ("{ NativeMap: " + folly::toJson(map_) + " }").c_str(); + return make_jstring(folly::toJson(map_).c_str()); } void NativeMap::registerNatives() { diff --git a/ReactAndroid/src/main/jni/react/jni/NativeMap.h b/ReactAndroid/src/main/jni/react/jni/NativeMap.h index 2318ca28caeb61..39a42b236270d5 100644 --- a/ReactAndroid/src/main/jni/react/jni/NativeMap.h +++ b/ReactAndroid/src/main/jni/react/jni/NativeMap.h @@ -20,14 +20,13 @@ class NativeMap : public jni::HybridClass { static auto constexpr kJavaDescriptor = "Lcom/facebook/react/bridge/NativeMap;"; - std::string toString(); + jni::local_ref toString(); RN_EXPORT folly::dynamic consume(); // Whether this map has been added to another array or map and no longer // has a valid map value. bool isConsumed; - void throwIfConsumed(); static void registerNatives(); @@ -35,8 +34,15 @@ class NativeMap : public jni::HybridClass { folly::dynamic map_; friend HybridBase; - friend struct ReadableNativeMapKeySetIterator; - explicit NativeMap(folly::dynamic s) : isConsumed(false), map_(s) {} + + template + explicit NativeMap(Dyn &&map) + : isConsumed(false), map_(std::forward(map)) {} + + void throwIfConsumed(); + + NativeMap(const NativeMap &) = delete; + NativeMap &operator=(const NativeMap &) = delete; }; } // namespace react diff --git a/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.cpp b/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.cpp index 8eab88e9ded65d..397108b9642f81 100644 --- a/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.cpp @@ -14,12 +14,6 @@ using namespace facebook::jni; namespace facebook { namespace react { -// This attribute exports the ctor symbol, so ReadableNativeArray to be -// constructed from other DSOs. -__attribute__((visibility("default"))) -ReadableNativeArray::ReadableNativeArray(folly::dynamic array) - : HybridBase(std::move(array)) {} - // TODO T112842309: Remove after fbjni upgraded in OSS void ReadableNativeArray::mapException(const std::exception &ex) { if (dynamic_cast(&ex) != nullptr) { diff --git a/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.h b/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.h index f077907d087837..0242a4907be9ba 100644 --- a/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.h +++ b/ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.h @@ -24,7 +24,10 @@ class ReadableNativeArray : public jni::HybridClass { protected: friend HybridBase; - explicit ReadableNativeArray(folly::dynamic array); + + template + explicit ReadableNativeArray(Dyn &&array) + : HybridBase(std::forward(array)) {} public: static constexpr const char *kJavaDescriptor = diff --git a/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp b/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp index 365c0dea7e41ff..f55a92dffb928e 100644 --- a/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp +++ b/ReactAndroid/src/main/jni/react/jni/ReadableNativeMap.cpp @@ -69,17 +69,17 @@ void addDynamicToJArray( } local_ref> ReadableNativeMap::importKeys() { + throwIfConsumed(); + keys_ = folly::dynamic::array(); if (map_ == nullptr) { return JArrayClass::newArray(0); } - auto pairs = map_.items(); - jint size = map_.size(); - auto jarray = JArrayClass::newArray(size); + auto jarray = JArrayClass::newArray(map_.size()); jint i = 0; - for (auto &pair : pairs) { + for (auto &pair : map_.items()) { auto value = pair.first.asString(); - keys_.value().push_back(value); + (*keys_).push_back(value); (*jarray)[i++] = make_jstring(value); } @@ -87,20 +87,24 @@ local_ref> ReadableNativeMap::importKeys() { } local_ref> ReadableNativeMap::importValues() { + throwIfConsumed(); + jint size = keys_.value().size(); auto jarray = JArrayClass::newArray(size); for (jint ii = 0; ii < size; ii++) { - const std::string &key = keys_.value()[ii].getString(); + const std::string &key = (*keys_)[ii].getString(); addDynamicToJArray(jarray, ii, map_.at(key)); } return jarray; } local_ref> ReadableNativeMap::importTypes() { + throwIfConsumed(); + jint size = keys_.value().size(); auto jarray = JArrayClass::newArray(size); for (jint ii = 0; ii < size; ii++) { - const std::string &key = keys_.value()[ii].getString(); + const std::string &key = (*keys_)[ii].getString(); (*jarray)[ii] = ReadableType::getType(map_.at(key).type()); } return jarray; From 39e1a3c3a60b8a6c3295bc0c7071b6fe6cfc18af Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 21 Feb 2023 09:22:09 -0800 Subject: [PATCH 75/81] RNGP - Fix RNTester crashing for JSC and safeguard against fetching JSC from Maven Central (#36232) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36232 Seems like RN Tester is crashing for JSC debug/release. This happens because RN Tester ends up fetching JSC from Maven Central which contains older versions of the artifacts (r17) which are not compatible with our setup AND are missing `libjsc.so`. This is happening as our file layout is a bit different than a regular NPM project so the repository declaration for JSC, being `../jsc-android/dist` from React Native root ends in the wrong folder. In this specifically I: - Add an excludeModule for "org.webkit:android-jsc" on Maven Central inside RNGP - Remove the allproject{repositories{}} block which was overriding RNGP configuration - Add a specific repository declaration inside RN Tester to point to where JSC effectively lives Changelog: [Internal] [Changed] - RNGP - Fix RNTester crashing for JSC and safeguard against fetching JSC from Maven Central Reviewed By: sshic Differential Revision: D43462015 fbshipit-source-id: db830d7567bbf7dd91412df417418aa61a0ca8fe --- build.gradle.kts | 7 ------- .../kotlin/com/facebook/react/utils/DependencyUtils.kt | 5 ++++- packages/rn-tester/android/app/build.gradle | 6 ++++++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e9b1924d538c2f..f6acfcb367f616 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,13 +43,6 @@ nexusPublishing { } } -allprojects { - repositories { - google() - mavenCentral() - } -} - tasks.register("cleanAll", Delete::class.java) { description = "Remove all the build files and intermediate build outputs" dependsOn(gradle.includedBuild("react-native-gradle-plugin").task(":clean")) diff --git a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt index c8760f644d8dbe..6679aba9c216eb 100644 --- a/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt +++ b/packages/react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/DependencyUtils.kt @@ -28,7 +28,10 @@ internal object DependencyUtils { } // We add the snapshot for users on nightlies. mavenRepoFromUrl("https://oss.sonatype.org/content/repositories/snapshots/") - repositories.mavenCentral() + repositories.mavenCentral { repo -> + // We don't want to fetch JSC from Maven Central as there are older versions there. + repo.content { it.excludeModule("org.webkit", "android-jsc") } + } // Android JSC is installed from npm mavenRepoFromURI(File(reactNativeDir, "../jsc-android/dist").toURI()) repositories.google() diff --git a/packages/rn-tester/android/app/build.gradle b/packages/rn-tester/android/app/build.gradle index 7e409761fab2c9..0069ab9958f19f 100644 --- a/packages/rn-tester/android/app/build.gradle +++ b/packages/rn-tester/android/app/build.gradle @@ -90,6 +90,12 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } +repositories { + maven { + url rootProject.file("node_modules/jsc-android/dist") + } +} + android { buildToolsVersion = "33.0.0" compileSdkVersion 33 From dba8cb71bd5122acecfde25ed33e6eb726af27bd Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 21 Feb 2023 09:46:02 -0800 Subject: [PATCH 76/81] Bump Flipper to 0.182.0 Summary: This change bumps Flipper to 0.182.0, mirroring the [Android Commit](https://github.com/facebook/react-native/commit/8fae37eaeab0c75c0be2885ce9198131e4d74c92) allow-large-files ## Changelog: [iOS][Changed] - Bump Flipper to 0.182.0 Reviewed By: dmytrorykun Differential Revision: D43454236 fbshipit-source-id: c852520d1e7f3a386a2fac11318a9fb6e868b520 --- packages/rn-tester/Podfile.lock | 78 ++++++++++++++++----------------- scripts/cocoapods/flipper.rb | 2 +- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index b04b11a90ce393..304c41947c46f4 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -10,7 +10,7 @@ PODS: - React-Core (= 1000.0.0) - React-jsi (= 1000.0.0) - ReactCommon/turbomodule/core (= 1000.0.0) - - Flipper (0.174.0): + - Flipper (0.182.0): - Flipper-Folly (~> 2.6) - Flipper-Boost-iOSX (1.76.0.1.11) - Flipper-DoubleConversion (3.2.0.1) @@ -24,48 +24,48 @@ PODS: - OpenSSL-Universal (= 1.1.1100) - Flipper-Glog (0.5.0.5) - Flipper-PeerTalk (0.0.4) - - FlipperKit (0.174.0): - - FlipperKit/Core (= 0.174.0) - - FlipperKit/Core (0.174.0): - - Flipper (~> 0.174.0) + - FlipperKit (0.182.0): + - FlipperKit/Core (= 0.182.0) + - FlipperKit/Core (0.182.0): + - Flipper (~> 0.182.0) - FlipperKit/CppBridge - FlipperKit/FBCxxFollyDynamicConvert - FlipperKit/FBDefines - FlipperKit/FKPortForwarding - SocketRocket (~> 0.6.0) - - FlipperKit/CppBridge (0.174.0): - - Flipper (~> 0.174.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.174.0): + - FlipperKit/CppBridge (0.182.0): + - Flipper (~> 0.182.0) + - FlipperKit/FBCxxFollyDynamicConvert (0.182.0): - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.174.0) - - FlipperKit/FKPortForwarding (0.174.0): + - FlipperKit/FBDefines (0.182.0) + - FlipperKit/FKPortForwarding (0.182.0): - CocoaAsyncSocket (~> 7.6) - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.174.0) - - FlipperKit/FlipperKitLayoutHelpers (0.174.0): + - FlipperKit/FlipperKitHighlightOverlay (0.182.0) + - FlipperKit/FlipperKitLayoutHelpers (0.182.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.174.0): + - FlipperKit/FlipperKitLayoutIOSDescriptors (0.182.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutPlugin (0.174.0): + - FlipperKit/FlipperKitLayoutPlugin (0.182.0): - FlipperKit/Core - FlipperKit/FlipperKitHighlightOverlay - FlipperKit/FlipperKitLayoutHelpers - FlipperKit/FlipperKitLayoutIOSDescriptors - FlipperKit/FlipperKitLayoutTextSearchable - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutTextSearchable (0.174.0) - - FlipperKit/FlipperKitNetworkPlugin (0.174.0): + - FlipperKit/FlipperKitLayoutTextSearchable (0.182.0) + - FlipperKit/FlipperKitNetworkPlugin (0.182.0): - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.174.0): + - FlipperKit/FlipperKitReactPlugin (0.182.0): - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.174.0): + - FlipperKit/FlipperKitUserDefaultsPlugin (0.182.0): - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.174.0): + - FlipperKit/SKIOSNetworkPlugin (0.182.0): - FlipperKit/Core - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) @@ -802,26 +802,26 @@ DEPENDENCIES: - DoubleConversion (from `../../third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../../Libraries/FBLazyVector`) - FBReactNativeSpec (from `../../React/FBReactNativeSpec`) - - Flipper (= 0.174.0) + - Flipper (= 0.182.0) - Flipper-Boost-iOSX (= 1.76.0.1.11) - Flipper-DoubleConversion (= 3.2.0.1) - Flipper-Fmt (= 7.1.7) - Flipper-Folly (= 2.6.10) - Flipper-Glog (= 0.5.0.5) - Flipper-PeerTalk (= 0.0.4) - - FlipperKit (= 0.174.0) - - FlipperKit/Core (= 0.174.0) - - FlipperKit/CppBridge (= 0.174.0) - - FlipperKit/FBCxxFollyDynamicConvert (= 0.174.0) - - FlipperKit/FBDefines (= 0.174.0) - - FlipperKit/FKPortForwarding (= 0.174.0) - - FlipperKit/FlipperKitHighlightOverlay (= 0.174.0) - - FlipperKit/FlipperKitLayoutPlugin (= 0.174.0) - - FlipperKit/FlipperKitLayoutTextSearchable (= 0.174.0) - - FlipperKit/FlipperKitNetworkPlugin (= 0.174.0) - - FlipperKit/FlipperKitReactPlugin (= 0.174.0) - - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.174.0) - - FlipperKit/SKIOSNetworkPlugin (= 0.174.0) + - FlipperKit (= 0.182.0) + - FlipperKit/Core (= 0.182.0) + - FlipperKit/CppBridge (= 0.182.0) + - FlipperKit/FBCxxFollyDynamicConvert (= 0.182.0) + - FlipperKit/FBDefines (= 0.182.0) + - FlipperKit/FKPortForwarding (= 0.182.0) + - FlipperKit/FlipperKitHighlightOverlay (= 0.182.0) + - FlipperKit/FlipperKitLayoutPlugin (= 0.182.0) + - FlipperKit/FlipperKitLayoutTextSearchable (= 0.182.0) + - FlipperKit/FlipperKitNetworkPlugin (= 0.182.0) + - FlipperKit/FlipperKitReactPlugin (= 0.182.0) + - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.182.0) + - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) - glog (from `../../third-party-podspecs/glog.podspec`) - hermes-engine (from `../../sdks/hermes/hermes-engine.podspec`) - libevent (~> 2.1.12) @@ -975,18 +975,18 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: d68947eddece25638eb0f642d1b957c90388afd1 - FBReactNativeSpec: dbfbd06ef9022b1a0198d14654ca3f4d8bbdea04 - Flipper: 186214d97e5c24edd706f39faf933e5acaaa8644 + FBReactNativeSpec: bfaf9508748c07260662ac4f7d773617856c3d45 + Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - FlipperKit: b353b63cb4048a5747529412524407d6efa68336 + FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b - hermes-engine: c6856cfc0143b20743bc478ca77fc086d74b7bfe + hermes-engine: bd42a017cf90ea36e8d9afbb18c986f043285fdf libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 @@ -1001,7 +1001,7 @@ SPEC CHECKSUMS: React-Fabric: 6b5c30b6e60a85446cc5d3702fa262fd1fc15619 React-graphics: e70886fff4b79bec3745de761900a770029591f2 React-hermes: 7f0e87d44b1c7cfbdd11aa3c070d04435fe75d57 - React-ImageManager: c22bb185bc1b1557071da61f929070ed56fb3859 + React-ImageManager: 9fd3521fb8871cd5bea83d2d282da27d6ef91199 React-jsi: e4c75a1cf727c8761908ac2eeb1084e47ba88a26 React-jsiexecutor: 8361f78286021782d885e0888bb059a4045c59b9 React-jsinspector: 9b56a373a6797114e1d89a7dffa98ee98af67a8f @@ -1011,7 +1011,7 @@ SPEC CHECKSUMS: React-RCTAnimation: 6741f7be3e269e057c1426074cc70f34b56e114b React-RCTAppDelegate: 0b3b2c1e02c02f952f5033535ddb23d690e3b890 React-RCTBlob: fd1ee93e48aa67b0183346a59754375de93de63d - React-RCTFabric: 533df4e11d99af97a78d4a400b4cab44925358e9 + React-RCTFabric: 179b2203e1b8b89b6ec8fa6104071beb553b1684 React-RCTImage: 055685a12c88939437f6520d9e7c120cd666cbf1 React-RCTLinking: b149b3ff1f96fa93fc445230b9c171adb0e5572c React-RCTNetwork: 21abb4231182651f48b7035beaa011b1ab7ae8f4 diff --git a/scripts/cocoapods/flipper.rb b/scripts/cocoapods/flipper.rb index 0d59b538cab440..2465a5be891f0f 100644 --- a/scripts/cocoapods/flipper.rb +++ b/scripts/cocoapods/flipper.rb @@ -6,7 +6,7 @@ # Default versions of Flipper and related dependencies. # Update this map to bump the dependencies. $flipper_default_versions = { - 'Flipper' => '0.174.0', + 'Flipper' => '0.182.0', 'Flipper-Boost-iOSX' => '1.76.0.1.11', 'Flipper-DoubleConversion' => '3.2.0.1', 'Flipper-Fmt' => '7.1.7', From d147bbbe84c2fbb6b4cc7f578c5c1f1e9eeb5cee Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Tue, 21 Feb 2023 09:56:07 -0800 Subject: [PATCH 77/81] Bump RNGP to 0.72.4 (#36233) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36233 Bump RNGP to 0.72.4 Changelog: [Internal] [Changed] - Bump RNGP to 0.72.4 Reviewed By: cipolleschi, hoxyq Differential Revision: D43445016 fbshipit-source-id: 4d8b0b05da44fb433909ec6be64156234c4e0051 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a57a338e3f0325..aa3292d2ac590c 100644 --- a/package.json +++ b/package.json @@ -118,7 +118,7 @@ "@react-native-community/cli-platform-android": "10.0.0", "@react-native-community/cli-platform-ios": "10.0.0", "@react-native/assets-registry": "^0.72.0", - "@react-native/gradle-plugin": "^0.72.3", + "@react-native/gradle-plugin": "^0.72.4", "@react-native/js-polyfills": "^0.72.1", "@react-native/normalize-colors": "^0.72.0", "@react-native/virtualized-lists": "^0.72.1", From 817948e0aa25fa55c26c338384af236bf8ed0027 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 21 Feb 2023 15:03:14 -0800 Subject: [PATCH 78/81] Add "Text Styles" TextInput Example Summary: This adds a series of examples for TextInput styles to screenshot test, specifically the ones which are projected to Android as spans. This will be used in refactoring to verify we do not change visual output. Changelog: [Internal][Added] - Add "Text Styles" TextInput Example Reviewed By: cortinico Differential Revision: D43158004 fbshipit-source-id: adaecf0e37941e66e280db282e2631a95b08b27a --- .../rn-tester/js/components/RNTesterButton.js | 3 +- .../TextInput/TextInputSharedExamples.js | 267 +++++++++++++++++- 2 files changed, 258 insertions(+), 12 deletions(-) diff --git a/packages/rn-tester/js/components/RNTesterButton.js b/packages/rn-tester/js/components/RNTesterButton.js index 0e5acdf2946a24..0bff3bf6da6ef3 100644 --- a/packages/rn-tester/js/components/RNTesterButton.js +++ b/packages/rn-tester/js/components/RNTesterButton.js @@ -18,6 +18,7 @@ import type {PressEvent} from 'react-native/Libraries/Types/CoreEventTypes'; type Props = $ReadOnly<{| testID?: string, + textTestID?: string, children?: React.Node, onPress?: ?(event: PressEvent) => mixed, |}>; @@ -30,7 +31,7 @@ class RNTesterButton extends React.Component { onPress={this.props.onPress} style={styles.button} underlayColor="grey"> - {this.props.children} + {this.props.children} ); } diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index e5b1c4f580bfcb..353379409ffe6a 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -10,17 +10,20 @@ 'use strict'; -const React = require('react'); - -const { +import * as React from 'react'; +import {useContext, useState} from 'react'; +import { Button, Platform, Text, TextInput, View, StyleSheet, -} = require('react-native'); +} from 'react-native'; +import type {TextStyle} from 'react-native/Libraries/StyleSheet/StyleSheet'; +import RNTesterButton from '../../components/RNTesterButton'; +import {RNTesterThemeContext} from '../../components/RNTesterTheme'; import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; const styles = StyleSheet.create({ @@ -49,9 +52,10 @@ const styles = StyleSheet.create({ }, label: { width: 115, - alignItems: 'flex-end', + textAlign: 'right', marginRight: 10, paddingTop: 2, + fontSize: 12, }, inputContainer: { flex: 1, @@ -80,15 +84,20 @@ const styles = StyleSheet.create({ fontSize: 13, padding: 4, }, + screenshotArea: { + position: 'absolute', + top: -5, + left: 120, + right: -5, + bottom: -5, + }, }); class WithLabel extends React.Component<$FlowFixMeProps> { render(): React.Node { return ( - - {this.props.label} - + {this.props.label} {this.props.children} ); @@ -592,6 +601,239 @@ function UncontrolledExample() { ); } +const TextStylesExample = React.memo(() => { + const theme = useContext(RNTesterThemeContext); + + return ( + + ); +}); + +type TextStylesContainerProps = { + examples: $ReadOnlyArray<{ + name: string, + textStyles: $ReadOnlyArray, + multiline?: boolean, + }>, +}; + +function TextStylesContainer({examples}: TextStylesContainerProps) { + const [offset, setOffset] = useState(0); + + const MAX_CYCLES = 6; + + return ( + + setOffset((offset + 1) % MAX_CYCLES)}> + Cycle {offset + 1}/{MAX_CYCLES} + + + + {examples.map(({name, multiline, textStyles}) => ( + + {multiline ? ( + + ) : ( + + )} + + ))} + + + ); +} + +type StyledTextInputProps = { + name: string, + textStyles: $ReadOnlyArray, + styleOffset: number, +}; + +function StyledTextInput({ + name, + textStyles, + styleOffset, +}: StyledTextInputProps) { + return ( + + He + ll + + o, + + + Wo + rl + d! + + ); +} + +function MultilineStyledTextInput({ + name, + textStyles, + styleOffset, +}: StyledTextInputProps) { + return ( + + Hel{'\n'} + + lo {'\n'} + + + Wor{'\n'} + + ld! + + ); +} + module.exports = ([ { title: 'Auto-focus', @@ -867,8 +1109,11 @@ module.exports = ([ { title: 'Uncontrolled component with layout changes', name: 'uncontrolledComponent', - render: function (): React.Node { - return ; - }, + render: () => , + }, + { + title: 'Text styles', + name: 'textStyles', + render: () => , }, ]: Array); From 407fb5c2384b13abba677789b8d86b21b6ace190 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 21 Feb 2023 15:15:31 -0800 Subject: [PATCH 79/81] Implement ability to emit device events from C++ TurboModules Summary: [Changelog][Internal] This adds a method, `emitDeviceEvent` to the C++ API of TurboModules, which allows to make calls to JS's `RCTDeviceEventEmitter.emit` from a C++ TurboModules. This is a very common pattern, specifically for the VR apps, but not only for them - e.g. Desktop fork also has a [custom implementation for this](https://www.internalfb.com/code/fbsource/third-party/microsoft-fork-of-react-native/react-native-utils/RCTEventEmitter.cpp). Note that my original intent was to actually backport the latter, however there are some complications with wiring things in a robust way, without exposing too much stuff and relying on singletons or folly::dynamic. So I ended up adding it to the TurboModule API itself and use the scheduler/JSI facilities instead. This approach is arguably well self-contained, uses high level APIs, and shouldn't be abusable much. Since I was trying to avoid usage of folly::dynamic in this case, I used a kind of "value factory" pattern instead in order to send the arguments to the JS thread in a thread safe way (see [the discussion here](https://fb.workplace.com/groups/rn.fabric/permalink/1398711453593610/)). Reviewed By: christophpurrer Differential Revision: D43466326 fbshipit-source-id: a3cb8359d08a46421559edd0f854772863cb5c39 --- .../EventEmitter/RCTDeviceEventEmitter.js | 10 +++++++- .../core/ReactCommon/TurboModule.cpp | 24 +++++++++++++++++++ .../core/ReactCommon/TurboModule.h | 20 ++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Libraries/EventEmitter/RCTDeviceEventEmitter.js b/Libraries/EventEmitter/RCTDeviceEventEmitter.js index 65fe57da7b3a3c..256983291888be 100644 --- a/Libraries/EventEmitter/RCTDeviceEventEmitter.js +++ b/Libraries/EventEmitter/RCTDeviceEventEmitter.js @@ -21,4 +21,12 @@ type RCTDeviceEventDefinitions = $FlowFixMe; * * NativeModules that emit events should instead subclass `NativeEventEmitter`. */ -export default (new EventEmitter(): IEventEmitter); +const RCTDeviceEventEmitter: IEventEmitter = + new EventEmitter(); + +Object.defineProperty(global, '__rctDeviceEventEmitter', { + configurable: true, + value: RCTDeviceEventEmitter, +}); + +export default (RCTDeviceEventEmitter: IEventEmitter); diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp index 89ac90bcd8362a..87e0eabcd55f51 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp @@ -36,5 +36,29 @@ jsi::Value TurboModule::get( return result; } +void TurboModule::emitDeviceEvent( + jsi::Runtime &runtime, + const std::string &eventName, + ArgFactory argFactory) { + jsInvoker_->invokeAsync([&runtime, eventName, argFactory]() { + jsi::Value emitter = + runtime.global().getProperty(runtime, "__rctDeviceEventEmitter"); + if (!emitter.isUndefined()) { + jsi::Object emitterObject = emitter.asObject(runtime); + // TODO: consider caching these + jsi::Function emitFunction = + emitterObject.getPropertyAsFunction(runtime, "emit"); + std::vector args; + args.emplace_back( + jsi::String::createFromAscii(runtime, eventName.c_str())); + if (argFactory) { + argFactory(runtime, args); + } + emitFunction.callWithThis( + runtime, emitterObject, (const jsi::Value *)args.data(), args.size()); + } + }); +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h index 866a0b4d4921d5..6a8bba7b5fa742 100644 --- a/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h +++ b/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h @@ -83,6 +83,26 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { }; std::unordered_map methodMap_; + using ArgFactory = + std::function &args)>; + + /** + * Calls RCTDeviceEventEmitter.emit to JavaScript, with given event name and + * an optional list of arguments. + * If present, argFactory is a callback used to construct extra arguments, + * e.g. + * + * emitDeviceEvent(rt, "myCustomEvent", + * [](jsi::Runtime& rt, std::vector& args) { + * args.emplace_back(jsi::Value(true)); + * args.emplace_back(jsi::Value(42)); + * }); + */ + void emitDeviceEvent( + jsi::Runtime &runtime, + const std::string &eventName, + ArgFactory argFactory = nullptr); + private: friend class TurboCxxModule; friend class TurboModuleBinding; From bc749a16238d37336d8912f7b5cd54fc1ea5b212 Mon Sep 17 00:00:00 2001 From: Genki Kondo Date: Tue, 21 Feb 2023 16:17:30 -0800 Subject: [PATCH 80/81] Early exit during matching in EventAnimationDriverMatchSpec Summary: Simple optimization to exit before iterating through the hit path if the event name doesn't match. Changelog: [Android][Internal] - Optimization for natively-driven Animated PointerEvents to early exit during matching in EventAnimationDriverMatchSpec. This should have no effect if you are not using PointerEvents Reviewed By: lunaleaps Differential Revision: D43400457 fbshipit-source-id: fe8d811d371c78622cd4f3f9cd469cff9ccce585 --- .../com/facebook/react/uimanager/events/PointerEvent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java index 3d46a854982dce..704859c8f273d1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/PointerEvent.java @@ -124,14 +124,14 @@ public Event.EventAnimationDriverMatchSpec getEventAnimationDriverMatchSpec() { new EventAnimationDriverMatchSpec() { @Override public boolean match(int viewTag, String eventName) { - if (!PointerEventHelper.isBubblingEvent(eventName)) { + if (!eventName.equals(mEventName) || !PointerEventHelper.isBubblingEvent(eventName)) { return false; } List viewTargets = mEventState.getHitPathForActivePointer(); for (TouchTargetHelper.ViewTarget viewTarget : viewTargets) { - if (viewTarget.getViewId() == viewTag && eventName.equals(mEventName)) { + if (viewTarget.getViewId() == viewTag) { return true; } } From 31a8e92caddcdbef9fe74de53e7f412a7e998591 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 22 Feb 2023 03:17:24 -0800 Subject: [PATCH 81/81] Fix TextView alignment being reset on state updates Summary: Changelog: [Android][Fixed] Resolved bug with Text components in new arch losing text alignment state. Reviewed By: mdvacca Differential Revision: D34108943 fbshipit-source-id: 3992e9406345be919b5e3595fc1f9e61cf67a699 --- .../react/views/text/ReactTextView.java | 16 ++++++---- .../views/text/ReactTextViewManager.java | 18 ++++++++--- .../react/views/text/TextAttributeProps.java | 32 +++++++++---------- .../react/views/textinput/ReactEditText.java | 5 +++ .../textinput/ReactTextInputManager.java | 21 ++++++------ 5 files changed, 55 insertions(+), 37 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java index e5e405682f005c..6e742793eafe49 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java @@ -54,7 +54,6 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie private boolean mContainsImages; private final int mDefaultGravityHorizontal; private final int mDefaultGravityVertical; - private int mTextAlign; private int mNumberOfLines; private TextUtils.TruncateAt mEllipsizeLocation; private boolean mAdjustsFontSizeToFit; @@ -69,8 +68,7 @@ public ReactTextView(Context context) { super(context); // Get these defaults only during the constructor - these should never be set otherwise - mDefaultGravityHorizontal = - getGravity() & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + mDefaultGravityHorizontal = getGravityHorizontal(); mDefaultGravityVertical = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; initView(); @@ -89,10 +87,10 @@ private void initView() { mReactBackgroundManager = new ReactViewBackgroundManager(this); - mTextAlign = Gravity.NO_GRAVITY; mNumberOfLines = ViewDefaults.NUMBER_OF_LINES; mAdjustsFontSizeToFit = false; mLinkifyMaskType = 0; + mNotifyOnInlineViewLayout = false; mTextIsSelectable = false; mEllipsizeLocation = TextUtils.TruncateAt.END; @@ -392,10 +390,9 @@ public void setText(ReactTextUpdate update) { } int nextTextAlign = update.getTextAlign(); - if (mTextAlign != nextTextAlign) { - mTextAlign = nextTextAlign; + if (nextTextAlign != getGravityHorizontal()) { + setGravityHorizontal(nextTextAlign); } - setGravityHorizontal(mTextAlign); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (getBreakStrategy() != update.getTextBreakStrategy()) { setBreakStrategy(update.getTextBreakStrategy()); @@ -552,6 +549,11 @@ public boolean hasOverlappingRendering() { return false; } + /* package */ int getGravityHorizontal() { + return getGravity() + & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + } + /* package */ void setGravityHorizontal(int gravityHorizontal) { if (gravityHorizontal == 0) { gravityHorizontal = mDefaultGravityHorizontal; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index 0c8a7f0621b9ea..705223f832d4c8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -8,6 +8,7 @@ package com.facebook.react.views.text; import android.content.Context; +import android.os.Build; import android.text.Spannable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -23,6 +24,7 @@ import com.facebook.react.uimanager.ReactStylesDiffMap; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewProps; import com.facebook.yoga.YogaMeasureMode; import java.util.HashMap; import java.util.Map; @@ -148,15 +150,19 @@ public Object updateState( view.setSpanned(spanned); int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return new ReactTextUpdate( spanned, state.hasKey("mostRecentEventCount") ? state.getInt("mostRecentEventCount") : -1, false, // TODO add this into local Data - TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), + TextAttributeProps.getTextAlignment( + props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props)); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } private Object getReactTextUpdate(ReactTextView view, ReactStylesDiffMap props, MapBuffer state) { @@ -171,15 +177,17 @@ private Object getReactTextUpdate(ReactTextView view, ReactStylesDiffMap props, int textBreakStrategy = TextAttributeProps.getTextBreakStrategy( paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return new ReactTextUpdate( spanned, -1, // UNUSED FOR TEXT false, // TODO add this into local Data TextAttributeProps.getTextAlignment( - props, TextLayoutManagerMapBuffer.isRTL(attributedString)), + props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props)); + TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } @Override diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 822969ad8d8fc9..d503a641808853 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -250,36 +250,36 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) { return result; } - public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL) { - @Nullable - String textAlignPropValue = - props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null; - int textAlignment; + public static int getTextAlignment(ReactStylesDiffMap props, boolean isRTL, int defaultValue) { + if (!props.hasKey(ViewProps.TEXT_ALIGN)) { + return defaultValue; + } + String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN); if ("justify".equals(textAlignPropValue)) { - textAlignment = Gravity.LEFT; + return Gravity.LEFT; } else { if (textAlignPropValue == null || "auto".equals(textAlignPropValue)) { - textAlignment = Gravity.NO_GRAVITY; + return Gravity.NO_GRAVITY; } else if ("left".equals(textAlignPropValue)) { - textAlignment = isRTL ? Gravity.RIGHT : Gravity.LEFT; + return isRTL ? Gravity.RIGHT : Gravity.LEFT; } else if ("right".equals(textAlignPropValue)) { - textAlignment = isRTL ? Gravity.LEFT : Gravity.RIGHT; + return isRTL ? Gravity.LEFT : Gravity.RIGHT; } else if ("center".equals(textAlignPropValue)) { - textAlignment = Gravity.CENTER_HORIZONTAL; + return Gravity.CENTER_HORIZONTAL; } else { FLog.w(ReactConstants.TAG, "Invalid textAlign: " + textAlignPropValue); - textAlignment = Gravity.NO_GRAVITY; + return Gravity.NO_GRAVITY; } } - return textAlignment; } - public static int getJustificationMode(ReactStylesDiffMap props) { - @Nullable - String textAlignPropValue = - props.hasKey(ViewProps.TEXT_ALIGN) ? props.getString(ViewProps.TEXT_ALIGN) : null; + public static int getJustificationMode(ReactStylesDiffMap props, int defaultValue) { + if (!props.hasKey(ViewProps.TEXT_ALIGN)) { + return defaultValue; + } + String textAlignPropValue = props.getString(ViewProps.TEXT_ALIGN); if ("justify".equals(textAlignPropValue) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return Layout.JUSTIFICATION_MODE_INTER_WORD; } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 3bcff03e5f4be4..6e2e24cc29eaa1 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -845,6 +845,11 @@ private void setIntrinsicContentSize() { } } + /* package */ int getGravityHorizontal() { + return getGravity() + & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + } + /* package */ void setGravityHorizontal(int gravityHorizontal) { if (gravityHorizontal == 0) { gravityHorizontal = mDefaultGravityHorizontal; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index ddbc072e20d38b..7059ca3ed48846 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -1315,10 +1315,7 @@ public Object updateState( } ReadableNativeMap state = stateWrapper.getStateData(); - if (state == null) { - return null; - } - if (!state.hasKey("attributedString")) { + if (state == null || !state.hasKey("attributedString")) { return null; } @@ -1336,14 +1333,18 @@ public Object updateState( attributedString.getArray("fragments").toArrayList().size() > 1; int textBreakStrategy = - TextAttributeProps.getTextBreakStrategy(paragraphAttributes.getString("textBreakStrategy")); + TextAttributeProps.getTextBreakStrategy( + paragraphAttributes.getString(ViewProps.TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return ReactTextUpdate.buildReactTextUpdateFromState( spanned, state.getInt("mostRecentEventCount"), - TextAttributeProps.getTextAlignment(props, TextLayoutManager.isRTL(attributedString)), + TextAttributeProps.getTextAlignment( + props, TextLayoutManager.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props), + TextAttributeProps.getJustificationMode(props, currentJustificationMode), containsMultipleFragments); } @@ -1371,14 +1372,16 @@ public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, M int textBreakStrategy = TextAttributeProps.getTextBreakStrategy( paragraphAttributes.getString(TextLayoutManagerMapBuffer.PA_KEY_TEXT_BREAK_STRATEGY)); + int currentJustificationMode = + Build.VERSION.SDK_INT < Build.VERSION_CODES.O ? 0 : view.getJustificationMode(); return ReactTextUpdate.buildReactTextUpdateFromState( spanned, state.getInt(TX_STATE_KEY_MOST_RECENT_EVENT_COUNT), TextAttributeProps.getTextAlignment( - props, TextLayoutManagerMapBuffer.isRTL(attributedString)), + props, TextLayoutManagerMapBuffer.isRTL(attributedString), view.getGravityHorizontal()), textBreakStrategy, - TextAttributeProps.getJustificationMode(props), + TextAttributeProps.getJustificationMode(props, currentJustificationMode), containsMultipleFragments); } }