react-native-reanimated 4.2.1 → 4.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.cpp +0 -4
  2. package/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.h +0 -1
  3. package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +3 -1
  4. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +12 -0
  5. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +1 -0
  6. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +463 -416
  7. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +3 -1
  8. package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +7 -2
  9. package/android/src/main/cpp/reanimated/android/NativeProxy.h +2 -1
  10. package/android/src/main/java/com/swmansion/reanimated/DrawPassDetector.java +82 -0
  11. package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +4 -2
  12. package/android/src/main/java/com/swmansion/reanimated/NodesManager.java +32 -4
  13. package/apple/reanimated/apple/native/NativeProxy.mm +1 -1
  14. package/compatibility.json +3 -3
  15. package/lib/module/common/style/processors/colors.js +1 -1
  16. package/lib/module/common/style/processors/colors.js.map +1 -1
  17. package/lib/module/createAnimatedComponent/AnimatedComponent.js +10 -6
  18. package/lib/module/createAnimatedComponent/AnimatedComponent.js.map +1 -1
  19. package/lib/module/hook/useComposedEventHandler.js +1 -1
  20. package/lib/module/hook/useComposedEventHandler.js.map +1 -1
  21. package/lib/module/hook/useHandler.js +3 -8
  22. package/lib/module/hook/useHandler.js.map +1 -1
  23. package/lib/module/hook/utils.js +27 -6
  24. package/lib/module/hook/utils.js.map +1 -1
  25. package/lib/module/jestUtils/common.js +18 -0
  26. package/lib/module/jestUtils/common.js.map +1 -0
  27. package/lib/module/{jestUtils.js → jestUtils/index.js} +6 -3
  28. package/lib/module/jestUtils/index.js.map +1 -0
  29. package/lib/module/{jestUtils.web.js → jestUtils/index.web.js} +2 -1
  30. package/lib/module/jestUtils/index.web.js.map +1 -0
  31. package/lib/module/platform-specific/jsVersion.js +1 -1
  32. package/lib/typescript/createAnimatedComponent/AnimatedComponent.d.ts.map +1 -1
  33. package/lib/typescript/hook/utils.d.ts +1 -1
  34. package/lib/typescript/hook/utils.d.ts.map +1 -1
  35. package/lib/typescript/jestUtils/common.d.ts +12 -0
  36. package/lib/typescript/jestUtils/common.d.ts.map +1 -0
  37. package/lib/typescript/{jestUtils.d.ts → jestUtils/index.d.ts} +4 -2
  38. package/lib/typescript/jestUtils/index.d.ts.map +1 -0
  39. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  40. package/package.json +21 -15
  41. package/scripts/worklets-version.json +1 -4
  42. package/src/common/style/processors/colors.ts +1 -1
  43. package/src/createAnimatedComponent/AnimatedComponent.tsx +12 -10
  44. package/src/hook/useComposedEventHandler.ts +1 -1
  45. package/src/hook/useHandler.ts +4 -14
  46. package/src/hook/utils.ts +38 -8
  47. package/src/jestUtils/common.ts +24 -0
  48. package/src/{jestUtils.ts → jestUtils/index.ts} +8 -4
  49. package/src/{jestUtils.web.ts → jestUtils/index.web.ts} +2 -0
  50. package/src/platform-specific/jsVersion.ts +1 -1
  51. package/lib/module/jestUtils.js.map +0 -1
  52. package/lib/module/jestUtils.web.js.map +0 -1
  53. package/lib/typescript/jestUtils.d.ts.map +0 -1
@@ -38,6 +38,83 @@ static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
38
38
  }
39
39
  #endif
40
40
 
41
+ namespace {
42
+
43
+ #ifdef ANDROID
44
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
45
+ return StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
46
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS");
47
+ }
48
+ #elif __APPLE__
49
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
50
+ return StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
51
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS");
52
+ }
53
+ #else
54
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
55
+ return false;
56
+ }
57
+ #endif
58
+
59
+ std::pair<UpdatesBatch, UpdatesBatch> partitionUpdates(
60
+ const UpdatesBatch &updatesBatch,
61
+ const std::unordered_set<std::string> &synchronousPropNames,
62
+ const bool shouldRequireIntegerColors = false,
63
+ const bool allowPartialViews = false) {
64
+ UpdatesBatch synchronousUpdatesBatch;
65
+ UpdatesBatch shadowTreeUpdatesBatch;
66
+
67
+ for (const auto &[shadowNode, props] : updatesBatch) {
68
+ if (allowPartialViews) {
69
+ folly::dynamic synchronousProps = folly::dynamic::object();
70
+ folly::dynamic shadowTreeProps = folly::dynamic::object();
71
+
72
+ for (const auto &[key, value] : props.items()) {
73
+ const auto keyStr = key.asString();
74
+ const bool isColorProp = keyStr == "color" || keyStr.find("Color") != std::string::npos;
75
+ const bool isSynchronous =
76
+ synchronousPropNames.contains(keyStr) && (!shouldRequireIntegerColors || !isColorProp || value.isInt());
77
+ if (isSynchronous) {
78
+ synchronousProps[keyStr] = value;
79
+ } else {
80
+ shadowTreeProps[keyStr] = value;
81
+ }
82
+ }
83
+
84
+ if (!synchronousProps.empty()) {
85
+ synchronousUpdatesBatch.emplace_back(shadowNode, std::move(synchronousProps));
86
+ }
87
+
88
+ if (!shadowTreeProps.empty()) {
89
+ shadowTreeUpdatesBatch.emplace_back(shadowNode, std::move(shadowTreeProps));
90
+ }
91
+ } else {
92
+ bool hasOnlySynchronousProps = true;
93
+
94
+ for (const auto &[key, value] : props.items()) {
95
+ const auto keyStr = key.asString();
96
+ const bool isColorProp = keyStr == "color" || keyStr.find("Color") != std::string::npos;
97
+ const bool isSynchronous =
98
+ synchronousPropNames.contains(keyStr) && (!shouldRequireIntegerColors || !isColorProp || value.isInt());
99
+ if (!isSynchronous) {
100
+ hasOnlySynchronousProps = false;
101
+ break;
102
+ }
103
+ }
104
+
105
+ if (hasOnlySynchronousProps) {
106
+ synchronousUpdatesBatch.emplace_back(shadowNode, props);
107
+ } else {
108
+ shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
109
+ }
110
+ }
111
+ }
112
+
113
+ return {std::move(synchronousUpdatesBatch), std::move(shadowTreeUpdatesBatch)};
114
+ }
115
+
116
+ } // namespace
117
+
41
118
  ReanimatedModuleProxy::ReanimatedModuleProxy(
42
119
  const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
43
120
  jsi::Runtime &rnRuntime,
@@ -556,7 +633,7 @@ bool ReanimatedModuleProxy::handleRawEvent(const RawEvent &rawEvent, double curr
556
633
  // (res == true), but for now handleEvent always returns false. Thankfully,
557
634
  // performOperations does not trigger a lot of code if there is nothing to
558
635
  // be done so this is fine for now.
559
- performOperations(true);
636
+ performOperations();
560
637
  return res;
561
638
  }
562
639
 
@@ -605,15 +682,13 @@ double ReanimatedModuleProxy::getCssTimestamp() {
605
682
  return currentCssTimestamp_;
606
683
  }
607
684
 
608
- void ReanimatedModuleProxy::performOperations(const bool isTriggeredByEvent) {
685
+ void ReanimatedModuleProxy::performOperations() {
609
686
  ReanimatedSystraceSection s("ReanimatedModuleProxy::performOperations");
610
687
 
611
- if (!isTriggeredByEvent) {
612
- auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
613
- for (const auto surfaceId : flushRequestsCopy) {
614
- uiManager_->getShadowTreeRegistry().visit(
615
- surfaceId, [](const ShadowTree &shadowTree) { shadowTree.notifyDelegatesOfUpdates(); });
616
- }
688
+ auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
689
+ for (const auto surfaceId : flushRequestsCopy) {
690
+ uiManager_->getShadowTreeRegistry().visit(
691
+ surfaceId, [](const ShadowTree &shadowTree) { shadowTree.notifyDelegatesOfUpdates(); });
617
692
  }
618
693
 
619
694
  jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
@@ -647,479 +722,451 @@ void ReanimatedModuleProxy::performOperations(const bool isTriggeredByEvent) {
647
722
 
648
723
  shouldUpdateCssAnimations_ = false;
649
724
 
650
- #ifdef ANDROID
651
- if constexpr (
652
- StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
653
- !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
654
- static const std::unordered_set<std::string> synchronousProps = {
655
- "opacity",
656
- "elevation",
657
- "zIndex",
658
- // "shadowOpacity", // not supported on Android
659
- // "shadowRadius", // not supported on Android
660
- "backgroundColor",
661
- // "color", // TODO: fix animating color of Animated.Text
662
- "tintColor",
663
- "borderRadius",
664
- "borderTopLeftRadius",
665
- "borderTopRightRadius",
666
- "borderTopStartRadius",
667
- "borderTopEndRadius",
668
- "borderBottomLeftRadius",
669
- "borderBottomRightRadius",
670
- "borderBottomStartRadius",
671
- "borderBottomEndRadius",
672
- "borderStartStartRadius",
673
- "borderStartEndRadius",
674
- "borderEndStartRadius",
675
- "borderEndEndRadius",
676
- "borderColor",
677
- "borderTopColor",
678
- "borderBottomColor",
679
- "borderLeftColor",
680
- "borderRightColor",
681
- "borderStartColor",
682
- "borderEndColor",
683
- "transform",
684
- };
725
+ if constexpr (shouldUseSynchronousUpdatesInPerformOperations()) {
726
+ applySynchronousUpdates(updatesBatch);
727
+ }
685
728
 
686
- // NOTE: Keep in sync with NativeProxy.java
687
- static constexpr auto CMD_START_OF_VIEW = 1;
688
- static constexpr auto CMD_START_OF_TRANSFORM = 2;
689
- static constexpr auto CMD_END_OF_TRANSFORM = 3;
690
- static constexpr auto CMD_END_OF_VIEW = 4;
691
-
692
- static constexpr auto CMD_OPACITY = 10;
693
- static constexpr auto CMD_ELEVATION = 11;
694
- static constexpr auto CMD_Z_INDEX = 12;
695
- static constexpr auto CMD_SHADOW_OPACITY = 13;
696
- static constexpr auto CMD_SHADOW_RADIUS = 14;
697
- static constexpr auto CMD_BACKGROUND_COLOR = 15;
698
- static constexpr auto CMD_COLOR = 16;
699
- static constexpr auto CMD_TINT_COLOR = 17;
700
-
701
- static constexpr auto CMD_BORDER_RADIUS = 20;
702
- static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
703
- static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
704
- static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
705
- static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
706
- static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
707
- static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
708
- static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
709
- static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
710
- static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
711
- static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
712
- static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
713
- static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
714
-
715
- static constexpr auto CMD_BORDER_COLOR = 40;
716
- static constexpr auto CMD_BORDER_TOP_COLOR = 41;
717
- static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
718
- static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
719
- static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
720
- static constexpr auto CMD_BORDER_START_COLOR = 45;
721
- static constexpr auto CMD_BORDER_END_COLOR = 46;
722
-
723
- static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
724
- static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
725
- static constexpr auto CMD_TRANSFORM_SCALE = 102;
726
- static constexpr auto CMD_TRANSFORM_SCALE_X = 103;
727
- static constexpr auto CMD_TRANSFORM_SCALE_Y = 104;
728
- static constexpr auto CMD_TRANSFORM_ROTATE = 105;
729
- static constexpr auto CMD_TRANSFORM_ROTATE_X = 106;
730
- static constexpr auto CMD_TRANSFORM_ROTATE_Y = 107;
731
- static constexpr auto CMD_TRANSFORM_ROTATE_Z = 108;
732
- static constexpr auto CMD_TRANSFORM_SKEW_X = 109;
733
- static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
734
- static constexpr auto CMD_TRANSFORM_MATRIX = 111;
735
- static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
729
+ if ((updatesBatch.size() > 0) && updatesRegistryManager_->shouldReanimatedSkipCommit()) {
730
+ updatesRegistryManager_->pleaseCommitAfterPause();
731
+ }
732
+ }
736
733
 
737
- static constexpr auto CMD_UNIT_DEG = 200;
738
- static constexpr auto CMD_UNIT_RAD = 201;
739
- static constexpr auto CMD_UNIT_PX = 202;
740
- static constexpr auto CMD_UNIT_PERCENT = 203;
734
+ if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
735
+ // It may happen that `performOperations` is called on the UI thread
736
+ // while React Native tries to commit a new tree on the JS thread.
737
+ // In this case, we should skip the commit here and let React Native do
738
+ // it. The commit will include the current values from the updates manager
739
+ // which will be applied in ReanimatedCommitHook.
740
+ return;
741
+ }
741
742
 
742
- const auto propNameToCommand = [](const std::string &name) {
743
- if (name == "opacity")
744
- return CMD_OPACITY;
743
+ commitUpdates(rt, updatesBatch);
745
744
 
746
- if (name == "elevation")
747
- return CMD_ELEVATION;
745
+ // Clear the entire cache after the commit
746
+ // (we don't know if the view is updated from outside of Reanimated
747
+ // so we have to clear the entire cache)
748
+ viewStylesRepository_->clearNodesCache();
749
+ }
748
750
 
749
- if (name == "zIndex")
750
- return CMD_Z_INDEX;
751
+ void ReanimatedModuleProxy::performNonLayoutOperations() {
752
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::performNonLayoutOperations");
751
753
 
752
- if (name == "shadowOpacity")
753
- return CMD_SHADOW_OPACITY;
754
+ UpdatesBatch updatesBatch = animatedPropsRegistry_->getPendingUpdates();
754
755
 
755
- if (name == "shadowRadius")
756
- return CMD_SHADOW_RADIUS;
756
+ applySynchronousUpdates(updatesBatch, true);
757
+ }
757
758
 
758
- if (name == "backgroundColor")
759
- return CMD_BACKGROUND_COLOR;
759
+ void ReanimatedModuleProxy::applySynchronousUpdates(UpdatesBatch &updatesBatch, const bool allowPartialUpdates) {
760
+ #ifdef ANDROID
761
+ static const std::unordered_set<std::string> synchronousProps = {
762
+ "opacity",
763
+ "elevation",
764
+ "zIndex",
765
+ // "shadowOpacity", // not supported on Android
766
+ // "shadowRadius", // not supported on Android
767
+ "backgroundColor",
768
+ // "color", // TODO: fix animating color of Animated.Text,
769
+ "tintColor",
770
+ "borderRadius",
771
+ "borderTopLeftRadius",
772
+ "borderTopRightRadius",
773
+ "borderTopStartRadius",
774
+ "borderTopEndRadius",
775
+ "borderBottomLeftRadius",
776
+ "borderBottomRightRadius",
777
+ "borderBottomStartRadius",
778
+ "borderBottomEndRadius",
779
+ "borderStartStartRadius",
780
+ "borderStartEndRadius",
781
+ "borderEndStartRadius",
782
+ "borderEndEndRadius",
783
+ "borderColor",
784
+ "borderTopColor",
785
+ "borderBottomColor",
786
+ "borderLeftColor",
787
+ "borderRightColor",
788
+ "borderStartColor",
789
+ "borderEndColor",
790
+ "transform",
791
+ };
760
792
 
761
- if (name == "color")
762
- return CMD_COLOR;
793
+ // NOTE: Keep in sync with NativeProxy.java
794
+ static constexpr auto CMD_START_OF_VIEW = 1;
795
+ static constexpr auto CMD_START_OF_TRANSFORM = 2;
796
+ static constexpr auto CMD_END_OF_TRANSFORM = 3;
797
+ static constexpr auto CMD_END_OF_VIEW = 4;
798
+
799
+ static constexpr auto CMD_OPACITY = 10;
800
+ static constexpr auto CMD_ELEVATION = 11;
801
+ static constexpr auto CMD_Z_INDEX = 12;
802
+ static constexpr auto CMD_SHADOW_OPACITY = 13;
803
+ static constexpr auto CMD_SHADOW_RADIUS = 14;
804
+ static constexpr auto CMD_BACKGROUND_COLOR = 15;
805
+ static constexpr auto CMD_COLOR = 16;
806
+ static constexpr auto CMD_TINT_COLOR = 17;
807
+
808
+ static constexpr auto CMD_BORDER_RADIUS = 20;
809
+ static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
810
+ static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
811
+ static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
812
+ static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
813
+ static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
814
+ static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
815
+ static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
816
+ static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
817
+ static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
818
+ static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
819
+ static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
820
+ static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
821
+
822
+ static constexpr auto CMD_BORDER_COLOR = 40;
823
+ static constexpr auto CMD_BORDER_TOP_COLOR = 41;
824
+ static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
825
+ static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
826
+ static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
827
+ static constexpr auto CMD_BORDER_START_COLOR = 45;
828
+ static constexpr auto CMD_BORDER_END_COLOR = 46;
829
+
830
+ static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
831
+ static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
832
+ static constexpr auto CMD_TRANSFORM_SCALE = 102;
833
+ static constexpr auto CMD_TRANSFORM_SCALE_X = 103;
834
+ static constexpr auto CMD_TRANSFORM_SCALE_Y = 104;
835
+ static constexpr auto CMD_TRANSFORM_ROTATE = 105;
836
+ static constexpr auto CMD_TRANSFORM_ROTATE_X = 106;
837
+ static constexpr auto CMD_TRANSFORM_ROTATE_Y = 107;
838
+ static constexpr auto CMD_TRANSFORM_ROTATE_Z = 108;
839
+ static constexpr auto CMD_TRANSFORM_SKEW_X = 109;
840
+ static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
841
+ static constexpr auto CMD_TRANSFORM_MATRIX = 111;
842
+ static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
763
843
 
764
- if (name == "tintColor")
765
- return CMD_TINT_COLOR;
844
+ static constexpr auto CMD_UNIT_DEG = 200;
845
+ static constexpr auto CMD_UNIT_RAD = 201;
846
+ static constexpr auto CMD_UNIT_PX = 202;
847
+ static constexpr auto CMD_UNIT_PERCENT = 203;
766
848
 
767
- if (name == "borderRadius")
768
- return CMD_BORDER_RADIUS;
849
+ const auto propNameToCommand = [](const std::string &name) {
850
+ if (name == "opacity")
851
+ return CMD_OPACITY;
769
852
 
770
- if (name == "borderTopLeftRadius")
771
- return CMD_BORDER_TOP_LEFT_RADIUS;
853
+ if (name == "elevation")
854
+ return CMD_ELEVATION;
772
855
 
773
- if (name == "borderTopRightRadius")
774
- return CMD_BORDER_TOP_RIGHT_RADIUS;
856
+ if (name == "zIndex")
857
+ return CMD_Z_INDEX;
775
858
 
776
- if (name == "borderTopStartRadius")
777
- return CMD_BORDER_TOP_START_RADIUS;
859
+ if (name == "shadowOpacity")
860
+ return CMD_SHADOW_OPACITY;
778
861
 
779
- if (name == "borderTopEndRadius")
780
- return CMD_BORDER_TOP_END_RADIUS;
862
+ if (name == "shadowRadius")
863
+ return CMD_SHADOW_RADIUS;
781
864
 
782
- if (name == "borderBottomLeftRadius")
783
- return CMD_BORDER_BOTTOM_LEFT_RADIUS;
865
+ if (name == "backgroundColor")
866
+ return CMD_BACKGROUND_COLOR;
784
867
 
785
- if (name == "borderBottomRightRadius")
786
- return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
787
-
788
- if (name == "borderBottomStartRadius")
789
- return CMD_BORDER_BOTTOM_START_RADIUS;
868
+ if (name == "color")
869
+ return CMD_COLOR;
790
870
 
791
- if (name == "borderBottomEndRadius")
792
- return CMD_BORDER_BOTTOM_END_RADIUS;
871
+ if (name == "tintColor")
872
+ return CMD_TINT_COLOR;
793
873
 
794
- if (name == "borderStartStartRadius")
795
- return CMD_BORDER_START_START_RADIUS;
874
+ if (name == "borderRadius")
875
+ return CMD_BORDER_RADIUS;
796
876
 
797
- if (name == "borderStartEndRadius")
798
- return CMD_BORDER_START_END_RADIUS;
877
+ if (name == "borderTopLeftRadius")
878
+ return CMD_BORDER_TOP_LEFT_RADIUS;
799
879
 
800
- if (name == "borderEndStartRadius")
801
- return CMD_BORDER_END_START_RADIUS;
880
+ if (name == "borderTopRightRadius")
881
+ return CMD_BORDER_TOP_RIGHT_RADIUS;
802
882
 
803
- if (name == "borderEndEndRadius")
804
- return CMD_BORDER_END_END_RADIUS;
883
+ if (name == "borderTopStartRadius")
884
+ return CMD_BORDER_TOP_START_RADIUS;
805
885
 
806
- if (name == "borderColor")
807
- return CMD_BORDER_COLOR;
886
+ if (name == "borderTopEndRadius")
887
+ return CMD_BORDER_TOP_END_RADIUS;
808
888
 
809
- if (name == "borderTopColor")
810
- return CMD_BORDER_TOP_COLOR;
889
+ if (name == "borderBottomLeftRadius")
890
+ return CMD_BORDER_BOTTOM_LEFT_RADIUS;
811
891
 
812
- if (name == "borderBottomColor")
813
- return CMD_BORDER_BOTTOM_COLOR;
892
+ if (name == "borderBottomRightRadius")
893
+ return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
894
+
895
+ if (name == "borderBottomStartRadius")
896
+ return CMD_BORDER_BOTTOM_START_RADIUS;
814
897
 
815
- if (name == "borderLeftColor")
816
- return CMD_BORDER_LEFT_COLOR;
898
+ if (name == "borderBottomEndRadius")
899
+ return CMD_BORDER_BOTTOM_END_RADIUS;
817
900
 
818
- if (name == "borderRightColor")
819
- return CMD_BORDER_RIGHT_COLOR;
901
+ if (name == "borderStartStartRadius")
902
+ return CMD_BORDER_START_START_RADIUS;
820
903
 
821
- if (name == "borderStartColor")
822
- return CMD_BORDER_START_COLOR;
904
+ if (name == "borderStartEndRadius")
905
+ return CMD_BORDER_START_END_RADIUS;
823
906
 
824
- if (name == "borderEndColor")
825
- return CMD_BORDER_END_COLOR;
907
+ if (name == "borderEndStartRadius")
908
+ return CMD_BORDER_END_START_RADIUS;
826
909
 
827
- if (name == "transform")
828
- return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
910
+ if (name == "borderEndEndRadius")
911
+ return CMD_BORDER_END_END_RADIUS;
829
912
 
830
- throw std::runtime_error("[Reanimated] Unsupported style: " + name);
831
- };
913
+ if (name == "borderColor")
914
+ return CMD_BORDER_COLOR;
832
915
 
833
- const auto transformNameToCommand = [](const std::string &name) {
834
- if (name == "translateX")
835
- return CMD_TRANSFORM_TRANSLATE_X;
916
+ if (name == "borderTopColor")
917
+ return CMD_BORDER_TOP_COLOR;
836
918
 
837
- if (name == "translateY")
838
- return CMD_TRANSFORM_TRANSLATE_Y;
919
+ if (name == "borderBottomColor")
920
+ return CMD_BORDER_BOTTOM_COLOR;
839
921
 
840
- if (name == "scale")
841
- return CMD_TRANSFORM_SCALE;
922
+ if (name == "borderLeftColor")
923
+ return CMD_BORDER_LEFT_COLOR;
842
924
 
843
- if (name == "scaleX")
844
- return CMD_TRANSFORM_SCALE_X;
925
+ if (name == "borderRightColor")
926
+ return CMD_BORDER_RIGHT_COLOR;
845
927
 
846
- if (name == "scaleY")
847
- return CMD_TRANSFORM_SCALE_Y;
928
+ if (name == "borderStartColor")
929
+ return CMD_BORDER_START_COLOR;
848
930
 
849
- if (name == "rotate")
850
- return CMD_TRANSFORM_ROTATE;
931
+ if (name == "borderEndColor")
932
+ return CMD_BORDER_END_COLOR;
851
933
 
852
- if (name == "rotateX")
853
- return CMD_TRANSFORM_ROTATE_X;
934
+ if (name == "transform")
935
+ return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
854
936
 
855
- if (name == "rotateY")
856
- return CMD_TRANSFORM_ROTATE_Y;
937
+ throw std::runtime_error("[Reanimated] Unsupported style: " + name);
938
+ };
857
939
 
858
- if (name == "rotateZ")
859
- return CMD_TRANSFORM_ROTATE_Z;
940
+ const auto transformNameToCommand = [](const std::string &name) {
941
+ if (name == "translateX")
942
+ return CMD_TRANSFORM_TRANSLATE_X;
860
943
 
861
- if (name == "skewX")
862
- return CMD_TRANSFORM_SKEW_X;
944
+ if (name == "translateY")
945
+ return CMD_TRANSFORM_TRANSLATE_Y;
863
946
 
864
- if (name == "skewY")
865
- return CMD_TRANSFORM_SKEW_Y;
947
+ if (name == "scale")
948
+ return CMD_TRANSFORM_SCALE;
866
949
 
867
- if (name == "matrix")
868
- return CMD_TRANSFORM_MATRIX;
950
+ if (name == "scaleX")
951
+ return CMD_TRANSFORM_SCALE_X;
869
952
 
870
- if (name == "perspective")
871
- return CMD_TRANSFORM_PERSPECTIVE;
953
+ if (name == "scaleY")
954
+ return CMD_TRANSFORM_SCALE_Y;
872
955
 
873
- throw std::runtime_error("[Reanimated] Unsupported transform: " + name);
874
- };
956
+ if (name == "rotate")
957
+ return CMD_TRANSFORM_ROTATE;
875
958
 
876
- UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
959
+ if (name == "rotateX")
960
+ return CMD_TRANSFORM_ROTATE_X;
877
961
 
878
- for (const auto &[shadowNode, props] : updatesBatch) {
879
- bool hasOnlySynchronousProps = true;
880
- for (const auto &[key, value] : props.items()) {
881
- const auto keyStr = key.asString();
882
- if (!synchronousProps.contains(keyStr) ||
883
- ((keyStr == "color" || keyStr.find("Color") != std::string::npos) && !value.isInt())) {
884
- hasOnlySynchronousProps = false;
885
- break;
886
- }
887
- }
888
- if (hasOnlySynchronousProps) {
889
- synchronousUpdatesBatch.emplace_back(shadowNode, props);
890
- } else {
891
- shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
892
- }
893
- }
962
+ if (name == "rotateY")
963
+ return CMD_TRANSFORM_ROTATE_Y;
894
964
 
895
- if (!synchronousUpdatesBatch.empty()) {
896
- std::vector<int> intBuffer;
897
- std::vector<double> doubleBuffer;
898
- intBuffer.reserve(1024);
899
- doubleBuffer.reserve(1024);
900
-
901
- for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
902
- intBuffer.push_back(CMD_START_OF_VIEW);
903
- intBuffer.push_back(shadowNode->getTag());
904
- for (const auto &[key, value] : props.items()) {
905
- const auto command = propNameToCommand(key.getString());
906
- switch (command) {
907
- case CMD_OPACITY:
908
- case CMD_ELEVATION:
909
- case CMD_Z_INDEX:
910
- case CMD_SHADOW_OPACITY:
911
- case CMD_SHADOW_RADIUS:
912
- intBuffer.push_back(command);
913
- doubleBuffer.push_back(value.asDouble());
914
- break;
915
-
916
- case CMD_BACKGROUND_COLOR:
917
- case CMD_COLOR:
918
- case CMD_TINT_COLOR:
919
- case CMD_BORDER_COLOR:
920
- case CMD_BORDER_TOP_COLOR:
921
- case CMD_BORDER_BOTTOM_COLOR:
922
- case CMD_BORDER_LEFT_COLOR:
923
- case CMD_BORDER_RIGHT_COLOR:
924
- case CMD_BORDER_START_COLOR:
925
- case CMD_BORDER_END_COLOR:
926
- intBuffer.push_back(command);
927
- intBuffer.push_back(value.asInt());
928
- break;
929
-
930
- case CMD_BORDER_RADIUS:
931
- case CMD_BORDER_TOP_LEFT_RADIUS:
932
- case CMD_BORDER_TOP_RIGHT_RADIUS:
933
- case CMD_BORDER_TOP_START_RADIUS:
934
- case CMD_BORDER_TOP_END_RADIUS:
935
- case CMD_BORDER_BOTTOM_LEFT_RADIUS:
936
- case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
937
- case CMD_BORDER_BOTTOM_START_RADIUS:
938
- case CMD_BORDER_BOTTOM_END_RADIUS:
939
- case CMD_BORDER_START_START_RADIUS:
940
- case CMD_BORDER_START_END_RADIUS:
941
- case CMD_BORDER_END_START_RADIUS:
942
- case CMD_BORDER_END_END_RADIUS:
943
- intBuffer.push_back(command);
944
- if (value.isDouble()) {
945
- intBuffer.push_back(CMD_UNIT_PX);
946
- doubleBuffer.push_back(value.getDouble());
947
- } else if (value.isString()) {
948
- const auto &valueStr = value.getString();
949
- if (!valueStr.ends_with("%")) {
950
- throw std::runtime_error("[Reanimated] Border radius string must be a percentage");
951
- }
952
- intBuffer.push_back(CMD_UNIT_PERCENT);
953
- doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
954
- } else {
955
- throw std::runtime_error("[Reanimated] Border radius value must be either a number or a string");
956
- }
957
- break;
958
-
959
- case CMD_START_OF_TRANSFORM:
960
- intBuffer.push_back(command);
961
- react_native_assert(value.isArray() && "[Reanimated] Transform value must be an array");
962
- for (const auto &item : value) {
963
- react_native_assert(item.isObject() && "[Reanimated] Transform array item must be an object");
964
- react_native_assert(
965
- item.size() == 1 && "[Reanimated] Transform array item must have exactly one key-value pair");
966
- const auto transformCommand = transformNameToCommand(item.keys().begin()->getString());
967
- const auto &transformValue = *item.values().begin();
968
- switch (transformCommand) {
969
- case CMD_TRANSFORM_SCALE:
970
- case CMD_TRANSFORM_SCALE_X:
971
- case CMD_TRANSFORM_SCALE_Y:
972
- case CMD_TRANSFORM_PERSPECTIVE: {
973
- intBuffer.push_back(transformCommand);
974
- doubleBuffer.push_back(transformValue.asDouble());
975
- break;
976
- }
965
+ if (name == "rotateZ")
966
+ return CMD_TRANSFORM_ROTATE_Z;
977
967
 
978
- case CMD_TRANSFORM_TRANSLATE_X:
979
- case CMD_TRANSFORM_TRANSLATE_Y: {
980
- intBuffer.push_back(transformCommand);
981
- if (transformValue.isDouble()) {
982
- intBuffer.push_back(CMD_UNIT_PX);
983
- doubleBuffer.push_back(transformValue.getDouble());
984
- } else if (transformValue.isString()) {
985
- const auto &transformValueStr = transformValue.getString();
986
- if (!transformValueStr.ends_with("%")) {
987
- throw std::runtime_error("[Reanimated] String translate must be a percentage");
988
- }
989
- intBuffer.push_back(CMD_UNIT_PERCENT);
990
- doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -1)));
991
- } else {
992
- throw std::runtime_error("[Reanimated] Translate value must be either a number or a string");
993
- }
994
- break;
995
- }
968
+ if (name == "skewX")
969
+ return CMD_TRANSFORM_SKEW_X;
996
970
 
997
- case CMD_TRANSFORM_ROTATE:
998
- case CMD_TRANSFORM_ROTATE_X:
999
- case CMD_TRANSFORM_ROTATE_Y:
1000
- case CMD_TRANSFORM_ROTATE_Z:
1001
- case CMD_TRANSFORM_SKEW_X:
1002
- case CMD_TRANSFORM_SKEW_Y: {
1003
- const auto &transformValueStr = transformValue.getString();
1004
- intBuffer.push_back(transformCommand);
1005
- if (transformValueStr.ends_with("deg")) {
1006
- intBuffer.push_back(CMD_UNIT_DEG);
1007
- } else if (transformValueStr.ends_with("rad")) {
1008
- intBuffer.push_back(CMD_UNIT_RAD);
1009
- } else {
1010
- throw std::runtime_error("[Reanimated] Unsupported rotation unit: " + transformValueStr);
1011
- }
1012
- doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -3)));
1013
- break;
1014
- }
971
+ if (name == "skewY")
972
+ return CMD_TRANSFORM_SKEW_Y;
973
+
974
+ if (name == "matrix")
975
+ return CMD_TRANSFORM_MATRIX;
976
+
977
+ if (name == "perspective")
978
+ return CMD_TRANSFORM_PERSPECTIVE;
1015
979
 
1016
- case CMD_TRANSFORM_MATRIX: {
1017
- intBuffer.push_back(transformCommand);
1018
- react_native_assert(transformValue.isArray() && "[Reanimated] Matrix must be an array");
1019
- int size = transformValue.size();
1020
- intBuffer.push_back(size);
1021
- for (int i = 0; i < size; i++) {
1022
- doubleBuffer.push_back(transformValue[i].asDouble());
1023
- }
1024
- break;
980
+ throw std::runtime_error("[Reanimated] Unsupported transform: " + name);
981
+ };
982
+
983
+ auto [synchronousUpdatesBatch, shadowTreeUpdatesBatch] =
984
+ partitionUpdates(updatesBatch, synchronousProps, true, allowPartialUpdates);
985
+
986
+ if (!synchronousUpdatesBatch.empty()) {
987
+ std::vector<int> intBuffer;
988
+ std::vector<double> doubleBuffer;
989
+ intBuffer.reserve(1024);
990
+ doubleBuffer.reserve(1024);
991
+
992
+ for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
993
+ intBuffer.push_back(CMD_START_OF_VIEW);
994
+ intBuffer.push_back(shadowNode->getTag());
995
+ for (const auto &[key, value] : props.items()) {
996
+ const auto command = propNameToCommand(key.getString());
997
+ switch (command) {
998
+ case CMD_OPACITY:
999
+ case CMD_ELEVATION:
1000
+ case CMD_Z_INDEX:
1001
+ case CMD_SHADOW_OPACITY:
1002
+ case CMD_SHADOW_RADIUS:
1003
+ intBuffer.push_back(command);
1004
+ doubleBuffer.push_back(value.asDouble());
1005
+ break;
1006
+
1007
+ case CMD_BACKGROUND_COLOR:
1008
+ case CMD_COLOR:
1009
+ case CMD_TINT_COLOR:
1010
+ case CMD_BORDER_COLOR:
1011
+ case CMD_BORDER_TOP_COLOR:
1012
+ case CMD_BORDER_BOTTOM_COLOR:
1013
+ case CMD_BORDER_LEFT_COLOR:
1014
+ case CMD_BORDER_RIGHT_COLOR:
1015
+ case CMD_BORDER_START_COLOR:
1016
+ case CMD_BORDER_END_COLOR:
1017
+ intBuffer.push_back(command);
1018
+ intBuffer.push_back(value.asInt());
1019
+ break;
1020
+
1021
+ case CMD_BORDER_RADIUS:
1022
+ case CMD_BORDER_TOP_LEFT_RADIUS:
1023
+ case CMD_BORDER_TOP_RIGHT_RADIUS:
1024
+ case CMD_BORDER_TOP_START_RADIUS:
1025
+ case CMD_BORDER_TOP_END_RADIUS:
1026
+ case CMD_BORDER_BOTTOM_LEFT_RADIUS:
1027
+ case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
1028
+ case CMD_BORDER_BOTTOM_START_RADIUS:
1029
+ case CMD_BORDER_BOTTOM_END_RADIUS:
1030
+ case CMD_BORDER_START_START_RADIUS:
1031
+ case CMD_BORDER_START_END_RADIUS:
1032
+ case CMD_BORDER_END_START_RADIUS:
1033
+ case CMD_BORDER_END_END_RADIUS:
1034
+ intBuffer.push_back(command);
1035
+ if (value.isDouble()) {
1036
+ intBuffer.push_back(CMD_UNIT_PX);
1037
+ doubleBuffer.push_back(value.getDouble());
1038
+ } else if (value.isString()) {
1039
+ const auto &valueStr = value.getString();
1040
+ if (!valueStr.ends_with("%")) {
1041
+ throw std::runtime_error("[Reanimated] Border radius string must be a percentage");
1042
+ }
1043
+ intBuffer.push_back(CMD_UNIT_PERCENT);
1044
+ doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
1045
+ } else {
1046
+ throw std::runtime_error("[Reanimated] Border radius value must be either a number or a string");
1047
+ }
1048
+ break;
1049
+
1050
+ case CMD_START_OF_TRANSFORM:
1051
+ intBuffer.push_back(command);
1052
+ react_native_assert(value.isArray() && "[Reanimated] Transform value must be an array");
1053
+ for (const auto &item : value) {
1054
+ react_native_assert(item.isObject() && "[Reanimated] Transform array item must be an object");
1055
+ react_native_assert(
1056
+ item.size() == 1 && "[Reanimated] Transform array item must have exactly one key-value pair");
1057
+ const auto transformCommand = transformNameToCommand(item.keys().begin()->getString());
1058
+ const auto &transformValue = *item.values().begin();
1059
+ switch (transformCommand) {
1060
+ case CMD_TRANSFORM_SCALE:
1061
+ case CMD_TRANSFORM_SCALE_X:
1062
+ case CMD_TRANSFORM_SCALE_Y:
1063
+ case CMD_TRANSFORM_PERSPECTIVE: {
1064
+ intBuffer.push_back(transformCommand);
1065
+ doubleBuffer.push_back(transformValue.asDouble());
1066
+ break;
1067
+ }
1068
+ case CMD_TRANSFORM_TRANSLATE_X:
1069
+ case CMD_TRANSFORM_TRANSLATE_Y: {
1070
+ intBuffer.push_back(transformCommand);
1071
+ if (transformValue.isDouble()) {
1072
+ intBuffer.push_back(CMD_UNIT_PX);
1073
+ doubleBuffer.push_back(transformValue.getDouble());
1074
+ } else if (transformValue.isString()) {
1075
+ const auto &transformValueStr = transformValue.getString();
1076
+ if (!transformValueStr.ends_with("%")) {
1077
+ throw std::runtime_error("[Reanimated] String translate must be a percentage");
1025
1078
  }
1079
+ intBuffer.push_back(CMD_UNIT_PERCENT);
1080
+ doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -1)));
1081
+ } else {
1082
+ throw std::runtime_error("[Reanimated] Translate value must be either a number or a string");
1083
+ }
1084
+ break;
1085
+ }
1086
+ case CMD_TRANSFORM_ROTATE:
1087
+ case CMD_TRANSFORM_ROTATE_X:
1088
+ case CMD_TRANSFORM_ROTATE_Y:
1089
+ case CMD_TRANSFORM_ROTATE_Z:
1090
+ case CMD_TRANSFORM_SKEW_X:
1091
+ case CMD_TRANSFORM_SKEW_Y: {
1092
+ const auto &transformValueStr = transformValue.getString();
1093
+ intBuffer.push_back(transformCommand);
1094
+ if (transformValueStr.ends_with("deg")) {
1095
+ intBuffer.push_back(CMD_UNIT_DEG);
1096
+ } else if (transformValueStr.ends_with("rad")) {
1097
+ intBuffer.push_back(CMD_UNIT_RAD);
1098
+ } else {
1099
+ throw std::runtime_error("[Reanimated] Unsupported rotation unit: " + transformValueStr);
1100
+ }
1101
+ doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -3)));
1102
+ break;
1103
+ }
1104
+ case CMD_TRANSFORM_MATRIX: {
1105
+ intBuffer.push_back(transformCommand);
1106
+ react_native_assert(transformValue.isArray() && "[Reanimated] Matrix must be an array");
1107
+ int size = transformValue.size();
1108
+ intBuffer.push_back(size);
1109
+ for (int i = 0; i < size; i++) {
1110
+ doubleBuffer.push_back(transformValue[i].asDouble());
1026
1111
  }
1112
+ break;
1027
1113
  }
1028
- intBuffer.push_back(CMD_END_OF_TRANSFORM);
1029
- break;
1114
+ }
1030
1115
  }
1031
- }
1032
- intBuffer.push_back(CMD_END_OF_VIEW);
1116
+ intBuffer.push_back(CMD_END_OF_TRANSFORM);
1117
+ break;
1033
1118
  }
1034
- synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
1035
1119
  }
1036
-
1037
- updatesBatch = std::move(shadowTreeUpdatesBatch);
1120
+ intBuffer.push_back(CMD_END_OF_VIEW);
1038
1121
  }
1122
+ synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
1123
+ }
1124
+
1125
+ updatesBatch = std::move(shadowTreeUpdatesBatch);
1039
1126
  #endif // ANDROID
1040
1127
 
1041
1128
  #if __APPLE__
1042
- if constexpr (
1043
- StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
1044
- !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
1045
- static const std::unordered_set<std::string> synchronousProps = {
1046
- "opacity",
1047
- "elevation",
1048
- "zIndex",
1049
- "shadowOpacity",
1050
- "shadowRadius",
1051
- "backgroundColor",
1052
- // "color", // TODO: fix animating color of Animated.Text
1053
- "tintColor",
1054
- "borderRadius",
1055
- "borderTopLeftRadius",
1056
- "borderTopRightRadius",
1057
- "borderTopStartRadius",
1058
- "borderTopEndRadius",
1059
- "borderBottomLeftRadius",
1060
- "borderBottomRightRadius",
1061
- "borderBottomStartRadius",
1062
- "borderBottomEndRadius",
1063
- "borderStartStartRadius",
1064
- "borderStartEndRadius",
1065
- "borderEndStartRadius",
1066
- "borderEndEndRadius",
1067
- "borderColor",
1068
- "borderTopColor",
1069
- "borderBottomColor",
1070
- "borderLeftColor",
1071
- "borderRightColor",
1072
- "borderStartColor",
1073
- "borderEndColor",
1074
- "transform",
1075
- };
1076
-
1077
- UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
1078
-
1079
- for (const auto &[shadowNode, props] : updatesBatch) {
1080
- bool hasOnlySynchronousProps = true;
1081
- for (const auto &key : props.keys()) {
1082
- const auto keyStr = key.asString();
1083
- if (!synchronousProps.contains(keyStr)) {
1084
- hasOnlySynchronousProps = false;
1085
- break;
1086
- }
1087
- }
1088
- if (hasOnlySynchronousProps) {
1089
- synchronousUpdatesBatch.emplace_back(shadowNode, props);
1090
- } else {
1091
- shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
1092
- }
1093
- }
1129
+ static const std::unordered_set<std::string> synchronousProps = {
1130
+ "opacity",
1131
+ "elevation",
1132
+ "zIndex",
1133
+ "shadowOpacity",
1134
+ "shadowRadius",
1135
+ "backgroundColor",
1136
+ // "color", // TODO: fix animating color of Animated.Text
1137
+ "tintColor",
1138
+ "borderRadius",
1139
+ "borderTopLeftRadius",
1140
+ "borderTopRightRadius",
1141
+ "borderTopStartRadius",
1142
+ "borderTopEndRadius",
1143
+ "borderBottomLeftRadius",
1144
+ "borderBottomRightRadius",
1145
+ "borderBottomStartRadius",
1146
+ "borderBottomEndRadius",
1147
+ "borderStartStartRadius",
1148
+ "borderStartEndRadius",
1149
+ "borderEndStartRadius",
1150
+ "borderEndEndRadius",
1151
+ "borderColor",
1152
+ "borderTopColor",
1153
+ "borderBottomColor",
1154
+ "borderLeftColor",
1155
+ "borderRightColor",
1156
+ "borderStartColor",
1157
+ "borderEndColor",
1158
+ "transform",
1159
+ };
1094
1160
 
1095
- for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
1096
- synchronouslyUpdateUIPropsFunction_(shadowNode->getTag(), props);
1097
- }
1161
+ auto [synchronousUpdatesBatch, shadowTreeUpdatesBatch] =
1162
+ partitionUpdates(updatesBatch, synchronousProps, false, allowPartialUpdates);
1098
1163
 
1099
- updatesBatch = std::move(shadowTreeUpdatesBatch);
1100
- }
1101
- #endif // __APPLE__
1102
-
1103
- if ((updatesBatch.size() > 0) && updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1104
- updatesRegistryManager_->pleaseCommitAfterPause();
1105
- }
1164
+ for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
1165
+ synchronouslyUpdateUIPropsFunction_(shadowNode->getTag(), props);
1106
1166
  }
1107
1167
 
1108
- if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1109
- // It may happen that `performOperations` is called on the UI thread
1110
- // while React Native tries to commit a new tree on the JS thread.
1111
- // In this case, we should skip the commit here and let React Native do
1112
- // it. The commit will include the current values from the updates manager
1113
- // which will be applied in ReanimatedCommitHook.
1114
- return;
1115
- }
1116
-
1117
- commitUpdates(rt, updatesBatch);
1118
-
1119
- // Clear the entire cache after the commit
1120
- // (we don't know if the view is updated from outside of Reanimated
1121
- // so we have to clear the entire cache)
1122
- viewStylesRepository_->clearNodesCache();
1168
+ updatesBatch = std::move(shadowTreeUpdatesBatch);
1169
+ #endif // __APPLE__
1123
1170
  }
1124
1171
 
1125
1172
  void ReanimatedModuleProxy::requestFlushRegistry() {