react-native-reanimated 4.3.1 → 4.3.2

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 (67) hide show
  1. package/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +12 -5
  2. package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +59 -37
  3. package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +11 -8
  4. package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +4 -0
  5. package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +17 -4
  6. package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +5 -0
  7. package/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +5 -0
  8. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +25 -12
  9. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
  10. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +38 -0
  11. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +106 -33
  12. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +165 -92
  13. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +2 -6
  14. package/android/CMakeLists.txt +4 -1
  15. package/android/build.gradle +2 -0
  16. package/android/generate-stub-pch.gradle.kts +84 -0
  17. package/android/src/main/cpp/ReanimatedPCH.h +46 -0
  18. package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +14 -1
  19. package/android/src/main/java/com/swmansion/reanimated/keyboard/KeyboardAnimationCallback.java +9 -1
  20. package/apple/reanimated/apple/ReanimatedModule.mm +12 -1
  21. package/lib/module/common/constants/platform.js +5 -5
  22. package/lib/module/common/constants/platform.js.map +1 -1
  23. package/lib/module/createAnimatedComponent/getViewInfo.js +3 -1
  24. package/lib/module/createAnimatedComponent/getViewInfo.js.map +1 -1
  25. package/lib/module/css/component/AnimatedComponent.js +0 -2
  26. package/lib/module/css/component/AnimatedComponent.js.map +1 -1
  27. package/lib/module/css/native/managers/CSSManager.js +5 -5
  28. package/lib/module/css/native/managers/CSSManager.js.map +1 -1
  29. package/lib/module/css/native/managers/CSSTransitionsManager.js +8 -1
  30. package/lib/module/css/native/managers/CSSTransitionsManager.js.map +1 -1
  31. package/lib/module/css/svg/native/processors/stroke.js +9 -5
  32. package/lib/module/css/svg/native/processors/stroke.js.map +1 -1
  33. package/lib/module/platform-specific/findHostInstance.js +8 -5
  34. package/lib/module/platform-specific/findHostInstance.js.map +1 -1
  35. package/lib/module/platform-specific/jsVersion.js +1 -1
  36. package/lib/module/updateProps/updateProps.js +3 -2
  37. package/lib/module/updateProps/updateProps.js.map +1 -1
  38. package/lib/module/valueSetter.js +1 -1
  39. package/lib/module/valueSetter.js.map +1 -1
  40. package/lib/typescript/common/constants/platform.d.ts.map +1 -1
  41. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +0 -1
  42. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
  43. package/lib/typescript/createAnimatedComponent/getViewInfo.d.ts.map +1 -1
  44. package/lib/typescript/css/component/AnimatedComponent.d.ts +0 -1
  45. package/lib/typescript/css/component/AnimatedComponent.d.ts.map +1 -1
  46. package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts +5 -1
  47. package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts.map +1 -1
  48. package/lib/typescript/css/svg/native/processors/stroke.d.ts.map +1 -1
  49. package/lib/typescript/platform-specific/findHostInstance.d.ts.map +1 -1
  50. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  51. package/lib/typescript/platform-specific/types.d.ts +1 -0
  52. package/lib/typescript/platform-specific/types.d.ts.map +1 -1
  53. package/lib/typescript/updateProps/updateProps.d.ts.map +1 -1
  54. package/lib/typescript/valueSetter.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/src/common/constants/platform.ts +6 -5
  57. package/src/createAnimatedComponent/commonTypes.ts +0 -1
  58. package/src/createAnimatedComponent/getViewInfo.ts +3 -1
  59. package/src/css/component/AnimatedComponent.tsx +0 -2
  60. package/src/css/native/managers/CSSManager.ts +8 -8
  61. package/src/css/native/managers/CSSTransitionsManager.ts +9 -2
  62. package/src/css/svg/native/processors/stroke.ts +9 -6
  63. package/src/platform-specific/findHostInstance.ts +7 -7
  64. package/src/platform-specific/jsVersion.ts +1 -1
  65. package/src/platform-specific/types.ts +2 -0
  66. package/src/updateProps/updateProps.ts +3 -2
  67. package/src/valueSetter.ts +2 -1
@@ -635,38 +635,60 @@ void LayoutAnimationsProxy_Legacy::startEnteringAnimation(const int tag, ShadowV
635
635
 
636
636
  auto &viewProps = static_cast<const ViewProps &>(*mutation.newChildShadowView.props);
637
637
  auto opacity = viewProps.opacity;
638
+ #ifdef ANDROID
639
+ const auto handle = pendingStarts_[tag].handle;
640
+ pendingStarts_[tag].count++;
641
+ #endif
638
642
 
639
- scheduleOnUI(uiScheduler_, [weakThis = weak_from_this(), finalView, current, mutation, opacity, tag]() {
640
- auto strongThis = weakThis.lock();
641
- if (!strongThis) {
642
- return;
643
- }
643
+ scheduleOnUI(
644
+ uiScheduler_,
645
+ [weakThis = weak_from_this(),
646
+ finalView,
647
+ current,
648
+ mutation,
649
+ opacity,
650
+ tag
651
+ #ifdef ANDROID
652
+ ,
653
+ handle
654
+ #endif
655
+ ]() {
656
+ auto strongThis = weakThis.lock();
657
+ if (!strongThis) {
658
+ return;
659
+ }
644
660
 
645
- Rect window{};
646
- {
647
- auto &mutex = strongThis->mutex;
648
- auto lock = std::unique_lock<std::recursive_mutex>(mutex);
649
- strongThis->layoutAnimations_.insert_or_assign(
650
- tag,
651
- LayoutAnimation{
652
- .finalView = finalView, .currentView = current, .parentTag = mutation.parentTag, .opacity = opacity});
653
- window = strongThis->surfaceManager.getWindow(mutation.newChildShadowView.surfaceId);
654
- }
661
+ Rect window{};
662
+ {
663
+ auto &mutex = strongThis->mutex;
664
+ auto lock = std::unique_lock<std::recursive_mutex>(mutex);
665
+ #ifdef ANDROID
666
+ if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
667
+ // the view was removed before this start could run
668
+ return;
669
+ }
670
+ #endif
671
+ strongThis->layoutAnimations_.insert_or_assign(
672
+ tag,
673
+ LayoutAnimation{
674
+ .finalView = finalView, .currentView = current, .parentTag = mutation.parentTag, .opacity = opacity});
675
+ window = strongThis->surfaceManager.getWindow(mutation.newChildShadowView.surfaceId);
676
+ }
655
677
 
656
- Snapshot values(mutation.newChildShadowView, window);
657
- auto &uiRuntime = strongThis->uiRuntime_;
658
- jsi::Object yogaValues(uiRuntime);
659
- yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
660
- yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
661
- yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
662
- yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
663
- yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
664
- yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
665
- yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
666
- yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
667
- strongThis->layoutAnimationsManager_->startLayoutAnimation(
668
- uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
669
- });
678
+ Snapshot values(mutation.newChildShadowView, window);
679
+ auto &uiRuntime = strongThis->uiRuntime_;
680
+ jsi::Object yogaValues(uiRuntime);
681
+ yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
682
+ yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
683
+ yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
684
+ yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
685
+ yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
686
+ yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
687
+ yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
688
+ yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
689
+ strongThis->layoutAnimationsManager_->startLayoutAnimation(
690
+ uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
691
+ });
670
692
  }
671
693
 
672
694
  void LayoutAnimationsProxy_Legacy::startExitingAnimation(const int tag, ShadowViewMutation &mutation) const {
@@ -674,38 +696,62 @@ void LayoutAnimationsProxy_Legacy::startExitingAnimation(const int tag, ShadowVi
674
696
  LOG(INFO) << "start exiting animation for tag " << tag << std::endl;
675
697
  #endif
676
698
  auto surfaceId = mutation.oldChildShadowView.surfaceId;
699
+ #ifdef ANDROID
700
+ const auto handle = pendingStarts_[tag].handle;
701
+ pendingStarts_[tag].count++;
702
+ #endif
677
703
 
678
- scheduleOnUI(uiScheduler_, [weakThis = weak_from_this(), tag, mutation, surfaceId]() {
679
- auto strongThis = weakThis.lock();
680
- if (!strongThis) {
681
- return;
682
- }
683
-
684
- auto oldView = mutation.oldChildShadowView;
685
- Rect window{};
686
- {
687
- auto &mutex = strongThis->mutex;
688
- auto lock = std::unique_lock<std::recursive_mutex>(mutex);
689
- strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
690
- window = strongThis->surfaceManager.getWindow(surfaceId);
691
- }
704
+ scheduleOnUI(
705
+ uiScheduler_,
706
+ [weakThis = weak_from_this(),
707
+ tag,
708
+ mutation,
709
+ surfaceId
710
+ #ifdef ANDROID
711
+ ,
712
+ handle
713
+ #endif
714
+ ]() {
715
+ auto strongThis = weakThis.lock();
716
+ if (!strongThis) {
717
+ return;
718
+ }
692
719
 
693
- Snapshot values(oldView, window);
720
+ auto oldView = mutation.oldChildShadowView;
721
+ Rect window{};
722
+ {
723
+ auto &mutex = strongThis->mutex;
724
+ auto lock = std::unique_lock<std::recursive_mutex>(mutex);
725
+ #ifdef ANDROID
726
+ if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
727
+ // the view was removed (e.g. its subtree was force-ended by a screen
728
+ // pop) before this start could run — its Remove+Delete are already on
729
+ // their way to the mounting layer, so starting the animation now
730
+ // would emit updates for a view that's about to be deleted
731
+ strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
732
+ return;
733
+ }
734
+ #endif
735
+ strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
736
+ window = strongThis->surfaceManager.getWindow(surfaceId);
737
+ }
694
738
 
695
- auto &uiRuntime = strongThis->uiRuntime_;
696
- jsi::Object yogaValues(uiRuntime);
697
- yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
698
- yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
699
- yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
700
- yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
701
- yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
702
- yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
703
- yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
704
- yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
705
- strongThis->layoutAnimationsManager_->startLayoutAnimation(
706
- uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
707
- strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
708
- });
739
+ Snapshot values(oldView, window);
740
+
741
+ auto &uiRuntime = strongThis->uiRuntime_;
742
+ jsi::Object yogaValues(uiRuntime);
743
+ yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
744
+ yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
745
+ yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
746
+ yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
747
+ yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
748
+ yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
749
+ yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
750
+ yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
751
+ strongThis->layoutAnimationsManager_->startLayoutAnimation(
752
+ uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
753
+ strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
754
+ });
709
755
  }
710
756
 
711
757
  void LayoutAnimationsProxy_Legacy::startLayoutAnimation(const int tag, const ShadowViewMutation &mutation) const {
@@ -713,43 +759,64 @@ void LayoutAnimationsProxy_Legacy::startLayoutAnimation(const int tag, const Sha
713
759
  LOG(INFO) << "start layout animation for tag " << tag << std::endl;
714
760
  #endif
715
761
  auto surfaceId = mutation.oldChildShadowView.surfaceId;
762
+ #ifdef ANDROID
763
+ const auto handle = pendingStarts_[tag].handle;
764
+ pendingStarts_[tag].count++;
765
+ #endif
716
766
 
717
- scheduleOnUI(uiScheduler_, [weakThis = weak_from_this(), mutation, surfaceId, tag]() {
718
- auto strongThis = weakThis.lock();
719
- if (!strongThis) {
720
- return;
721
- }
722
-
723
- auto oldView = mutation.oldChildShadowView;
724
- Rect window{};
725
- {
726
- auto &mutex = strongThis->mutex;
727
- auto lock = std::unique_lock<std::recursive_mutex>(mutex);
728
- strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
729
- window = strongThis->surfaceManager.getWindow(surfaceId);
730
- }
767
+ scheduleOnUI(
768
+ uiScheduler_,
769
+ [weakThis = weak_from_this(),
770
+ mutation,
771
+ surfaceId,
772
+ tag
773
+ #ifdef ANDROID
774
+ ,
775
+ handle
776
+ #endif
777
+ ]() {
778
+ auto strongThis = weakThis.lock();
779
+ if (!strongThis) {
780
+ return;
781
+ }
731
782
 
732
- Snapshot currentValues(oldView, window);
733
- Snapshot targetValues(mutation.newChildShadowView, window);
783
+ auto oldView = mutation.oldChildShadowView;
784
+ Rect window{};
785
+ {
786
+ auto &mutex = strongThis->mutex;
787
+ auto lock = std::unique_lock<std::recursive_mutex>(mutex);
788
+ #ifdef ANDROID
789
+ if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
790
+ // the view was removed before this start could run
791
+ return;
792
+ }
793
+ #endif
794
+ strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
795
+ window = strongThis->surfaceManager.getWindow(surfaceId);
796
+ }
734
797
 
735
- auto &uiRuntime = strongThis->uiRuntime_;
736
- jsi::Object yogaValues(uiRuntime);
737
- yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
738
- yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
739
- yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
740
- yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
741
- yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
742
- yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
743
- yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
744
- yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
745
- yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
746
- yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
747
- yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
748
- yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
749
- yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
750
- yogaValues.setProperty(uiRuntime, "windowHeight", targetValues.windowHeight);
751
- strongThis->layoutAnimationsManager_->startLayoutAnimation(uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
752
- });
798
+ Snapshot currentValues(oldView, window);
799
+ Snapshot targetValues(mutation.newChildShadowView, window);
800
+
801
+ auto &uiRuntime = strongThis->uiRuntime_;
802
+ jsi::Object yogaValues(uiRuntime);
803
+ yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
804
+ yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
805
+ yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
806
+ yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
807
+ yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
808
+ yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
809
+ yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
810
+ yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
811
+ yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
812
+ yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
813
+ yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
814
+ yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
815
+ yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
816
+ yogaValues.setProperty(uiRuntime, "windowHeight", targetValues.windowHeight);
817
+ strongThis->layoutAnimationsManager_->startLayoutAnimation(
818
+ uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
819
+ });
753
820
  }
754
821
 
755
822
  void LayoutAnimationsProxy_Legacy::updateOngoingAnimationTarget(const int tag, const ShadowViewMutation &mutation)
@@ -759,6 +826,12 @@ void LayoutAnimationsProxy_Legacy::updateOngoingAnimationTarget(const int tag, c
759
826
  }
760
827
 
761
828
  void LayoutAnimationsProxy_Legacy::maybeCancelAnimation(const int tag) const {
829
+ #ifdef ANDROID
830
+ // invalidate animation starts that are scheduled but haven't run yet
831
+ if (const auto it = pendingStarts_.find(tag); it != pendingStarts_.end()) {
832
+ it->second.handle++;
833
+ }
834
+ #endif
762
835
  if (!layoutAnimations_.contains(tag)) {
763
836
  return;
764
837
  }
@@ -717,11 +717,6 @@ void ReanimatedModuleProxy::performOperations() {
717
717
  }
718
718
 
719
719
  commitUpdates(uiRuntime, updatesBatch);
720
-
721
- // Clear the entire cache after the commit
722
- // (we don't know if the view is updated from outside of Reanimated
723
- // so we have to clear the entire cache)
724
- viewStylesRepository_->clearNodesCache();
725
720
  }
726
721
 
727
722
  void ReanimatedModuleProxy::performNonLayoutOperations() {
@@ -1292,7 +1287,8 @@ void ReanimatedModuleProxy::initializeFabric(const std::shared_ptr<UIManager> &u
1292
1287
 
1293
1288
  strongThis->requestFlushRegistry();
1294
1289
  };
1295
- mountHook_ = std::make_shared<ReanimatedMountHook>(uiManager_, updatesRegistryManager_, request);
1290
+ mountHook_ =
1291
+ std::make_shared<ReanimatedMountHook>(uiManager_, updatesRegistryManager_, viewStylesRepository_, request);
1296
1292
  commitHook_ = std::make_shared<ReanimatedCommitHook>(uiManager_, updatesRegistryManager_, layoutAnimationsProxy_);
1297
1293
  }
1298
1294
 
@@ -1,5 +1,5 @@
1
1
  project(Reanimated)
2
- cmake_minimum_required(VERSION 3.8)
2
+ cmake_minimum_required(VERSION 3.16)
3
3
 
4
4
  set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
5
5
 
@@ -50,6 +50,9 @@ find_package(react-native-worklets REQUIRED CONFIG)
50
50
  add_library(reanimated SHARED ${REANIMATED_COMMON_CPP_SOURCES}
51
51
  ${REANIMATED_ANDROID_CPP_SOURCES})
52
52
 
53
+ target_precompile_headers(reanimated PRIVATE
54
+ "${ANDROID_CPP_DIR}/ReanimatedPCH.h")
55
+
53
56
  if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 80)
54
57
  include(
55
58
  "${REACT_NATIVE_DIR}/ReactCommon/cmake-utils/react-native-flags.cmake")
@@ -130,6 +130,8 @@ if (project == rootProject) {
130
130
  apply plugin: "com.android.library"
131
131
  apply plugin: "maven-publish"
132
132
 
133
+ apply from: "./generate-stub-pch.gradle.kts"
134
+
133
135
  android {
134
136
  compileSdkVersion safeExtGet("compileSdkVersion", 36)
135
137
 
@@ -0,0 +1,84 @@
1
+ import groovy.json.JsonSlurper
2
+
3
+ // Workaround for Android Studio's C++ analyzer surfacing errors during Gradle
4
+ // Sync when CMake's precompiled header binary (`cmake_pch.hxx.pch`, generated
5
+ // from `ReanimatedPCH.h`) hasn't been built yet. The project compiles fine,
6
+ // but on a clean sync the IDE can't index sources without the PCH binary. See
7
+ // the underlying issue: https://issuetracker.google.com/issues/187448826
8
+
9
+ // Generates minimal stub `.pch` files from an empty header so the IDE's C++
10
+ // engine doesn't fail during sync. The actual build regenerates the real PCH
11
+ // files via ninja because we set each stub PCH's mtime older than its source
12
+ // (`cmake_pch.hxx.cxx`).
13
+
14
+ // Adapted from Expo's PR: https://github.com/expo/expo/pull/45921
15
+
16
+ val cxxDir = project.file(".cxx")
17
+
18
+ val generateStubPCHTask = tasks.register("generateStubPCH") {
19
+ dependsOn("configureCMakeDebug")
20
+ doLast {
21
+ if (!cxxDir.exists()) {
22
+ return@doLast
23
+ }
24
+ cxxDir.walkTopDown().forEach { file ->
25
+ if (file.name != "compile_commands.json") {
26
+ return@forEach
27
+ }
28
+ @Suppress("UNCHECKED_CAST")
29
+ val entries = JsonSlurper().parseText(file.readText()) as List<Map<String, Any>>
30
+ entries.forEach entry@{ entry ->
31
+ val entryFile = entry["file"] as String
32
+ if (!entryFile.endsWith("cmake_pch.hxx.cxx")) {
33
+ return@entry
34
+ }
35
+ val pchFile = File(entryFile.substring(0, entryFile.length - ".cxx".length) + ".pch")
36
+ if (!pchFile.exists() || pchFile.length() == 0L) {
37
+ pchFile.parentFile.mkdirs()
38
+
39
+ val command = entry["command"] as String
40
+ val compiler = command.split(" ").first()
41
+ val target = Regex("""--target=\S+""").find(command)!!.value
42
+ val sysroot = Regex("""--sysroot=\S+""").find(command)!!.value
43
+
44
+ val stubHeader = File(pchFile.parentFile, "stub_pch.hxx")
45
+ stubHeader.writeText("")
46
+
47
+ val process = ProcessBuilder(
48
+ compiler,
49
+ target,
50
+ sysroot,
51
+ "-x", "c++-header",
52
+ "-o", pchFile.absolutePath,
53
+ stubHeader.absolutePath,
54
+ )
55
+ .directory(File(entry["directory"] as String))
56
+ .redirectErrorStream(true)
57
+ .start()
58
+ process.outputStream.close()
59
+ if (process.waitFor() != 0) {
60
+ throw GradleException(
61
+ "Stub PCH generation failed: ${process.inputStream.bufferedReader().readText()}",
62
+ )
63
+ }
64
+ }
65
+ // Ensure PCH is older than source so ninja rebuilds the real one during build
66
+ pchFile.setLastModified(File(entryFile).lastModified() - 1)
67
+ }
68
+ }
69
+ }
70
+ }
71
+
72
+ // Register `prepareKotlinBuildScriptModel` if absent (Android Studio sync needs it
73
+ // to exist so the stub PCH generation runs) or configure it if some other plugin
74
+ // already registered it (e.g. on CI, where re-registering throws `Cannot add task
75
+ // 'prepareKotlinBuildScriptModel' as a task with that name already exists.`).
76
+ if (tasks.findByName("prepareKotlinBuildScriptModel") == null) {
77
+ tasks.register("prepareKotlinBuildScriptModel") {
78
+ dependsOn(generateStubPCHTask)
79
+ }
80
+ } else {
81
+ tasks.named("prepareKotlinBuildScriptModel") {
82
+ dependsOn(generateStubPCHTask)
83
+ }
84
+ }
@@ -0,0 +1,46 @@
1
+ #pragma once
2
+
3
+ // IWYU pragma: begin_keep
4
+
5
+ // C++ standard library
6
+ #include <algorithm>
7
+ #include <atomic>
8
+ #include <functional>
9
+ #include <map>
10
+ #include <memory>
11
+ #include <mutex>
12
+ #include <optional>
13
+ #include <ostream>
14
+ #include <string>
15
+ #include <string_view>
16
+ #include <type_traits>
17
+ #include <unordered_map>
18
+ #include <unordered_set>
19
+ #include <utility>
20
+ #include <vector>
21
+
22
+ // fbjni
23
+ #include <fbjni/fbjni.h>
24
+
25
+ // folly
26
+ #include <folly/Conv.h>
27
+ #include <folly/Expected.h>
28
+ #include <folly/Format.h>
29
+ #include <folly/dynamic.h>
30
+ #include <folly/json/dynamic.h>
31
+
32
+ // jsi
33
+ #include <jsi/JSIDynamic.h>
34
+ #include <jsi/jsi.h>
35
+
36
+ // react-native renderer (Fabric)
37
+ #include <react/renderer/components/root/RootProps.h>
38
+ #include <react/renderer/components/root/RootShadowNode.h>
39
+ #include <react/renderer/components/view/BaseViewProps.h>
40
+ #include <react/renderer/components/view/ViewProps.h>
41
+ #include <react/renderer/core/EventDispatcher.h>
42
+ #include <react/renderer/core/ShadowNode.h>
43
+ #include <react/renderer/mounting/ShadowTree.h>
44
+ #include <react/renderer/uimanager/UIManager.h>
45
+
46
+ // IWYU pragma: end_keep
@@ -15,6 +15,7 @@ import com.facebook.react.bridge.UiThreadUtil;
15
15
  import com.facebook.react.common.annotations.FrameworkAPI;
16
16
  import com.facebook.react.fabric.FabricUIManager;
17
17
  import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
18
+ import com.facebook.react.uimanager.IllegalViewOperationException;
18
19
  import com.facebook.react.uimanager.UIManagerHelper;
19
20
  import com.facebook.react.uimanager.common.UIManagerType;
20
21
  import com.facebook.soloader.SoLoader;
@@ -305,7 +306,19 @@ public class NativeProxy {
305
306
  }
306
307
 
307
308
  for (int i = 0; i < tags.length; i++) {
308
- if (mFabricUIManager.resolveView(tags[i]) == null) {
309
+ try {
310
+ if (mFabricUIManager.resolveView(tags[i]) == null) {
311
+ tags[i] = -1;
312
+ }
313
+ } catch (IllegalViewOperationException e) {
314
+ // `resolveView` is expected to return `null` for a tag without a
315
+ // mounted view, but it instead throws when the tag's `ViewState` is
316
+ // already registered while the Android view hasn't been created yet.
317
+ // This happens when a view is mid-preallocation and a third-party view
318
+ // manager (e.g. lottie-react-native) dispatches an event synchronously
319
+ // from within `createView`, re-entering this code path. Treat it the
320
+ // same as a missing view.
321
+ // See https://github.com/software-mansion/react-native-reanimated/issues/9636.
309
322
  tags[i] = -1;
310
323
  }
311
324
  }
@@ -10,6 +10,7 @@ public class KeyboardAnimationCallback extends WindowInsetsAnimationCompat.Callb
10
10
  private final NotifyAboutKeyboardChangeFunction mNotifyAboutKeyboardChange;
11
11
  private static final int CONTENT_TYPE_MASK = WindowInsetsCompat.Type.ime();
12
12
  private final boolean mIsNavigationBarTranslucent;
13
+ private boolean mPendingStartDispatch = false;
13
14
 
14
15
  public KeyboardAnimationCallback(
15
16
  Keyboard keyboard,
@@ -30,7 +31,9 @@ public class KeyboardAnimationCallback extends WindowInsetsAnimationCompat.Callb
30
31
  return bounds;
31
32
  }
32
33
  mKeyboard.onAnimationStart();
33
- mNotifyAboutKeyboardChange.call();
34
+ // Dispatching synchronously here can cancel the still-pending insets
35
+ // animation, so the dispatch is deferred to onProgress or onEnd.
36
+ mPendingStartDispatch = true;
34
37
  return super.onStart(animation, bounds);
35
38
  }
36
39
 
@@ -47,6 +50,7 @@ public class KeyboardAnimationCallback extends WindowInsetsAnimationCompat.Callb
47
50
  }
48
51
  }
49
52
  if (isAnyKeyboardAnimationRunning) {
53
+ mPendingStartDispatch = false;
50
54
  mKeyboard.updateHeight(insets, mIsNavigationBarTranslucent);
51
55
  mNotifyAboutKeyboardChange.call();
52
56
  }
@@ -56,6 +60,10 @@ public class KeyboardAnimationCallback extends WindowInsetsAnimationCompat.Callb
56
60
  @Override
57
61
  public void onEnd(@NonNull WindowInsetsAnimationCompat animation) {
58
62
  if (isKeyboardAnimation(animation)) {
63
+ if (mPendingStartDispatch) {
64
+ mNotifyAboutKeyboardChange.call();
65
+ }
66
+ mPendingStartDispatch = false;
59
67
  mKeyboard.onAnimationEnd();
60
68
  mNotifyAboutKeyboardChange.call();
61
69
  }
@@ -130,7 +130,18 @@ RCT_EXPORT_MODULE(ReanimatedModule);
130
130
  - (BOOL)hasReactNativeFailedReload
131
131
  {
132
132
  id workletsModule = [_moduleRegistry moduleForName:"WorkletsModule"];
133
- return ![_moduleRegistry moduleIsInitialized:[workletsModule class]];
133
+ if (![_moduleRegistry moduleIsInitialized:[workletsModule class]]) {
134
+ return YES;
135
+ }
136
+
137
+ // On a double reload React Native can momentarily leave the surface presenter without
138
+ // a scheduler. This is another manifestation of the same non-fatal reload race, so we
139
+ // bail on it here instead of asserting on a nil scheduler later in installTurboModule.
140
+ if ([_surfacePresenter scheduler] == nil) {
141
+ return YES;
142
+ }
143
+
144
+ return NO;
134
145
  }
135
146
 
136
147
  - (void)checkBridgeless
@@ -8,12 +8,12 @@ function isWindowAvailable() {
8
8
  // @ts-ignore Fallback if `window` is undefined.
9
9
  return typeof window !== 'undefined';
10
10
  }
11
- export const IS_ANDROID = /* @__PURE__ */(() => Platform.OS === 'android')();
12
- export const IS_IOS = /* @__PURE__ */(() => Platform.OS === 'ios')();
13
- export const IS_WEB = Platform.OS === 'web';
14
- export const IS_JEST = !!process.env.JEST_WORKER_ID;
11
+ export const IS_ANDROID = /* @__PURE__ */(() => Platform?.OS === 'android')();
12
+ export const IS_IOS = /* @__PURE__ */(() => Platform?.OS === 'ios')();
13
+ export const IS_WEB = Platform?.OS === 'web';
14
+ export const IS_JEST = typeof globalThis.jest !== 'undefined' || process.env.NODE_ENV === 'test';
15
15
  /** @knipIgnore */
16
- export const IS_WINDOWS = Platform.OS === 'windows';
16
+ export const IS_WINDOWS = Platform?.OS === 'windows';
17
17
  export const IS_WINDOW_AVAILABLE = isWindowAvailable();
18
18
  export const SHOULD_BE_USE_WEB = IS_JEST || IS_WEB || IS_WINDOWS;
19
19
  //# sourceMappingURL=platform.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Platform","isWindowAvailable","window","IS_ANDROID","OS","IS_IOS","IS_WEB","IS_JEST","process","env","JEST_WORKER_ID","IS_WINDOWS","IS_WINDOW_AVAILABLE","SHOULD_BE_USE_WEB"],"sourceRoot":"../../../../src","sources":["common/constants/platform.ts"],"mappings":"AAAA,YAAY;;AACZ,SAASA,QAAQ,QAAQ,cAAc;AAEvC,SAASC,iBAAiBA,CAAA,EAAG;EAC3B;EACA;EACA;EACA;EACA,OAAO,OAAOC,MAAM,KAAK,WAAW;AACtC;AAEA,OAAO,MAAMC,UAAmB,GAAG,eAAgB,CAAC,MAClDH,QAAQ,CAACI,EAAE,KAAK,SAAS,EAAE,CAAC;AAC9B,OAAO,MAAMC,MAAe,GAAG,eAAgB,CAAC,MAAML,QAAQ,CAACI,EAAE,KAAK,KAAK,EAAE,CAAC;AAC9E,OAAO,MAAME,MAAe,GAAGN,QAAQ,CAACI,EAAE,KAAK,KAAK;AACpD,OAAO,MAAMG,OAAgB,GAAG,CAAC,CAACC,OAAO,CAACC,GAAG,CAACC,cAAc;AAC5D;AACA,OAAO,MAAMC,UAAmB,GAAGX,QAAQ,CAACI,EAAE,KAAK,SAAS;AAE5D,OAAO,MAAMQ,mBAA4B,GAAGX,iBAAiB,CAAC,CAAC;AAE/D,OAAO,MAAMY,iBAAiB,GAAGN,OAAO,IAAID,MAAM,IAAIK,UAAU","ignoreList":[]}
1
+ {"version":3,"names":["Platform","isWindowAvailable","window","IS_ANDROID","OS","IS_IOS","IS_WEB","IS_JEST","globalThis","jest","process","env","NODE_ENV","IS_WINDOWS","IS_WINDOW_AVAILABLE","SHOULD_BE_USE_WEB"],"sourceRoot":"../../../../src","sources":["common/constants/platform.ts"],"mappings":"AAAA,YAAY;;AACZ,SAASA,QAAQ,QAAQ,cAAc;AAEvC,SAASC,iBAAiBA,CAAA,EAAG;EAC3B;EACA;EACA;EACA;EACA,OAAO,OAAOC,MAAM,KAAK,WAAW;AACtC;AAEA,OAAO,MAAMC,UAAmB,GAAG,eAAgB,CAAC,MAClDH,QAAQ,EAAEI,EAAE,KAAK,SAAS,EAAE,CAAC;AAC/B,OAAO,MAAMC,MAAe,GAAG,eAAgB,CAAC,MAAML,QAAQ,EAAEI,EAAE,KAAK,KAAK,EAAE,CAAC;AAC/E,OAAO,MAAME,MAAe,GAAGN,QAAQ,EAAEI,EAAE,KAAK,KAAK;AACrD,OAAO,MAAMG,OAAgB,GAC3B,OAAOC,UAAU,CAACC,IAAI,KAAK,WAAW,IAAIC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,MAAM;AAC3E;AACA,OAAO,MAAMC,UAAmB,GAAGb,QAAQ,EAAEI,EAAE,KAAK,SAAS;AAE7D,OAAO,MAAMU,mBAA4B,GAAGb,iBAAiB,CAAC,CAAC;AAE/D,OAAO,MAAMc,iBAAiB,GAAGR,OAAO,IAAID,MAAM,IAAIO,UAAU","ignoreList":[]}
@@ -15,7 +15,9 @@
15
15
  // reactViewName via componentNameByReactViewName().
16
16
  export function getViewInfo(element) {
17
17
  return {
18
- reactViewName: element?._viewConfig?.uiViewClassName ?? element?.__internalInstanceHandle?.type ?? element?.__internalInstanceHandle?.elementType,
18
+ reactViewName: element?.__viewConfig?.uiViewClassName ??
19
+ // ReactFabricHostComponent (e.g. react-native-macos) exposes `_viewConfig`.
20
+ element?._viewConfig?.uiViewClassName ?? element?.__internalInstanceHandle?.type ?? element?.__internalInstanceHandle?.elementType,
19
21
  viewTag: element?.__nativeTag
20
22
  };
21
23
  }
@@ -1 +1 @@
1
- {"version":3,"names":["getViewInfo","element","reactViewName","_viewConfig","uiViewClassName","__internalInstanceHandle","type","elementType","viewTag","__nativeTag"],"sourceRoot":"../../../src","sources":["createAnimatedComponent/getViewInfo.ts"],"mappings":"AAAA,YAAY;;AAIZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,WAAWA,CAACC,OAAqB,EAG/C;EACA,OAAO;IACLC,aAAa,EAAGD,OAAO,EAAEE,WAAW,EAAEC,eAAe,IACnDH,OAAO,EAAEI,wBAAwB,EAAEC,IAAI,IACvCL,OAAO,EAAEI,wBAAwB,EAAEE,WAAsB;IAC3DC,OAAO,EAAEP,OAAO,EAAEQ;EACpB,CAAC;AACH","ignoreList":[]}
1
+ {"version":3,"names":["getViewInfo","element","reactViewName","__viewConfig","uiViewClassName","_viewConfig","__internalInstanceHandle","type","elementType","viewTag","__nativeTag"],"sourceRoot":"../../../src","sources":["createAnimatedComponent/getViewInfo.ts"],"mappings":"AAAA,YAAY;;AAIZ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,WAAWA,CAACC,OAAqB,EAG/C;EACA,OAAO;IACLC,aAAa,EAAGD,OAAO,EAAEE,YAAY,EAAEC,eAAe;IACpD;IACAH,OAAO,EAAEI,WAAW,EAAED,eAAe,IACrCH,OAAO,EAAEK,wBAAwB,EAAEC,IAAI,IACvCN,OAAO,EAAEK,wBAAwB,EAAEE,WAAsB;IAC3DC,OAAO,EAAER,OAAO,EAAES;EACpB,CAAC;AACH","ignoreList":[]}
@@ -16,7 +16,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
16
16
  export default class AnimatedComponent extends Component {
17
17
  _cssStyle = {}; // RN style object with Reanimated CSS properties
18
18
  _componentRef = null;
19
- _hasAnimatedRef = false;
20
19
  // Used only on web
21
20
  _componentDOMRef = null;
22
21
  _willUnmount = false;
@@ -95,7 +94,6 @@ export default class AnimatedComponent extends Component {
95
94
  // Component can specify ref which should be animated when animated version of the component is created.
96
95
  // Otherwise, we animate the component itself.
97
96
  if (componentRef && componentRef.getAnimatableRef) {
98
- this._hasAnimatedRef = true;
99
97
  return componentRef.getAnimatableRef();
100
98
  }
101
99
  // Case for SVG components on Web