react-native-windows 0.81.12 → 0.81.15

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 (29) hide show
  1. package/Common/Common.vcxproj +1 -1
  2. package/Folly/Folly.vcxproj +1 -1
  3. package/Libraries/Modal/Modal.windows.js +1 -7
  4. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.cpp +53 -66
  5. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +58 -21
  6. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +197 -54
  7. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +12 -3
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +14 -9
  9. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +4 -6
  10. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +101 -44
  11. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -2
  12. package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +3 -3
  13. package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.h +3 -1
  14. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +0 -1
  15. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
  16. package/Microsoft.ReactNative/Modules/Animated/AnimatedNode.cpp +3 -3
  17. package/Microsoft.ReactNative/Modules/Animated/AnimatedNode.h +3 -2
  18. package/Microsoft.ReactNative/Modules/Timing.h +2 -1
  19. package/Microsoft.ReactNative.Cxx/ModuleRegistration.h +10 -10
  20. package/PropertySheets/External/Microsoft.ReactNative.Composition.CppApp.targets +2 -2
  21. package/PropertySheets/External/Microsoft.ReactNative.Composition.CppLib.targets +2 -2
  22. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  23. package/ReactCommon/ReactCommon.vcxproj +1 -1
  24. package/Scripts/OfficeReact.Win32.nuspec +44 -44
  25. package/Scripts/Tfs/Layout-Desktop-Headers.ps1 +1 -15
  26. package/Shared/Shared.vcxitems.filters +0 -2
  27. package/package.json +1 -1
  28. package/Scripts/OpenSSL.nuspec +0 -39
  29. package/Scripts/OpenSSL.targets +0 -36
@@ -94,7 +94,7 @@
94
94
  </ItemGroup>
95
95
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
96
96
  <ItemGroup>
97
- <PackageReference Include="boost" Version="1.83.0.0" />
97
+ <PackageReference Include="boost" Version="1.84.0.0" />
98
98
  <PackageReference Include="Microsoft.Windows.CppWinRT" Version="$(CppWinRTVersion)" PrivateAssets="all" />
99
99
  </ItemGroup>
100
100
  <ImportGroup Label="ExtensionTargets">
@@ -364,7 +364,7 @@
364
364
  <TemporaryFollyPatchFiles Include="$(MSBuildThisFileDirectory)\TEMP_UntilFollyUpdate\**\*.*" />
365
365
  </ItemGroup>
366
366
  <ItemGroup>
367
- <PackageReference Include="boost" Version="1.83.0.0" />
367
+ <PackageReference Include="boost" Version="1.84.0.0" />
368
368
  </ItemGroup>
369
369
  <Target Name="Deploy" />
370
370
  <!-- Reenable this task if we need to temporarily replace any folly files for fixes, while we wait for PRs to land in folly -->
@@ -41,13 +41,7 @@ export type PublicModalInstance = HostInstance;
41
41
  const ModalEventEmitter =
42
42
  (Platform.OS === 'ios' || Platform.OS === 'windows') && // [Windows]
43
43
  NativeModalManager != null
44
- ? new NativeEventEmitter<ModalEventDefinitions>(
45
- // 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
46
- // If you want to use the native module on other platforms, please remove this condition and test its behavior
47
- Platform.OS !== 'ios' && Platform.OS !== 'windows' // [Windows]
48
- ? null
49
- : NativeModalManager,
50
- )
44
+ ? new NativeEventEmitter<ModalEventDefinitions>(NativeModalManager)
51
45
  : null;
52
46
 
53
47
  /**
@@ -26,16 +26,18 @@ bool isColorMeaningful(
26
26
  void pixelRoundBorderRadii(facebook::react::BorderRadii &borderRadii, float scaleFactor) noexcept {
27
27
  // Always round radii down to avoid spikey circles
28
28
  borderRadii.topLeft = {
29
- std::floor(borderRadii.topLeft.horizontal * scaleFactor), std::floor(borderRadii.topLeft.vertical * scaleFactor)};
29
+ .vertical = std::floor(borderRadii.topLeft.vertical * scaleFactor),
30
+ .horizontal = std::floor(borderRadii.topLeft.horizontal * scaleFactor)};
30
31
  borderRadii.topRight = {
31
- std::floor(borderRadii.topRight.horizontal * scaleFactor),
32
- std::floor(borderRadii.topRight.vertical * scaleFactor)};
32
+ .vertical = std::floor(borderRadii.topRight.vertical * scaleFactor),
33
+ .horizontal = std::floor(borderRadii.topRight.horizontal * scaleFactor)};
33
34
  borderRadii.bottomLeft = {
34
- std::floor(borderRadii.bottomLeft.horizontal * scaleFactor),
35
- std::floor(borderRadii.bottomLeft.vertical * scaleFactor)};
35
+ .vertical = std::floor(borderRadii.bottomLeft.vertical * scaleFactor),
36
+ .horizontal = std::floor(borderRadii.bottomLeft.horizontal * scaleFactor)};
36
37
  borderRadii.bottomRight = {
37
- std::floor(borderRadii.bottomRight.horizontal * scaleFactor),
38
- std::floor(borderRadii.bottomRight.vertical * scaleFactor)};
38
+ .vertical = std::floor(borderRadii.bottomRight.vertical * scaleFactor),
39
+ .horizontal = std::floor(borderRadii.bottomRight.horizontal * scaleFactor),
40
+ };
39
41
  }
40
42
 
41
43
  void scaleAndPixelRoundBorderWidths(
@@ -268,30 +270,14 @@ RoundedPathParameters GenerateRoundedPathParameters(
268
270
  return result;
269
271
  }
270
272
 
271
- float totalTopRadius = baseRadius.topLeft.horizontal + baseRadius.topRight.horizontal;
272
- float totalRightRadius = baseRadius.topRight.vertical + baseRadius.bottomRight.vertical;
273
- float totalBottomRadius = baseRadius.bottomRight.horizontal + baseRadius.bottomLeft.horizontal;
274
- float totalLeftRadius = baseRadius.bottomLeft.vertical + baseRadius.topLeft.vertical;
275
-
276
- float maxHorizontalRadius = std::max(totalTopRadius, totalBottomRadius);
277
- float maxVerticalRadius = std::max(totalLeftRadius, totalRightRadius);
278
-
279
- double totalWidth = inset.left + inset.right + pathSize.width;
280
- double totalHeight = inset.top + inset.bottom + pathSize.height;
281
-
282
- float scaleHoriz = static_cast<float>(maxHorizontalRadius / totalWidth);
283
- float scaleVert = static_cast<float>(maxVerticalRadius / totalHeight);
284
-
285
- float maxScale = std::max(1.0f, std::max(scaleHoriz, scaleVert));
286
-
287
- result.topLeftRadiusX = std::max(0.0f, baseRadius.topLeft.horizontal / maxScale - inset.left);
288
- result.topLeftRadiusY = std::max(0.0f, baseRadius.topLeft.vertical / maxScale - inset.top);
289
- result.topRightRadiusX = std::max(0.0f, baseRadius.topRight.horizontal / maxScale - inset.right);
290
- result.topRightRadiusY = std::max(0.0f, baseRadius.topRight.vertical / maxScale - inset.top);
291
- result.bottomRightRadiusX = std::max(0.0f, baseRadius.bottomRight.horizontal / maxScale - inset.right);
292
- result.bottomRightRadiusY = std::max(0.0f, baseRadius.bottomRight.vertical / maxScale - inset.bottom);
293
- result.bottomLeftRadiusX = std::max(0.0f, baseRadius.bottomLeft.horizontal / maxScale - inset.left);
294
- result.bottomLeftRadiusY = std::max(0.0f, baseRadius.bottomLeft.vertical / maxScale - inset.bottom);
273
+ result.topLeftRadiusX = std::max(0.0f, baseRadius.topLeft.horizontal - inset.left);
274
+ result.topLeftRadiusY = std::max(0.0f, baseRadius.topLeft.vertical - inset.top);
275
+ result.topRightRadiusX = std::max(0.0f, baseRadius.topRight.horizontal - inset.right);
276
+ result.topRightRadiusY = std::max(0.0f, baseRadius.topRight.vertical - inset.top);
277
+ result.bottomRightRadiusX = std::max(0.0f, baseRadius.bottomRight.horizontal - inset.right);
278
+ result.bottomRightRadiusY = std::max(0.0f, baseRadius.bottomRight.vertical - inset.bottom);
279
+ result.bottomLeftRadiusX = std::max(0.0f, baseRadius.bottomLeft.horizontal - inset.left);
280
+ result.bottomLeftRadiusY = std::max(0.0f, baseRadius.bottomLeft.vertical - inset.bottom);
295
281
 
296
282
  return result;
297
283
  }
@@ -473,8 +459,8 @@ void SetBorderLayerProperties(
473
459
  /*
474
460
  else
475
461
  {
476
- SetBorderLayerPropertiesCommon(theme, comContext, layer, shape, borderTexture, textureRect,
477
- anchorPoint, anchorOffset, strokeWidth, borderColor, borderStyle);
462
+ SetBorderLayerPropertiesCommon(theme, compContext, layer, shape, borderTexture, textureRect,
463
+ anchorPoint, anchorOffset, size, relativeSizeAdjustment, strokeWidth, borderColor, borderStyle);
478
464
  }
479
465
  */
480
466
  }
@@ -516,11 +502,11 @@ void DrawAllBorderLayers(
516
502
  spTextures[0], // Target Layer, Source Texture, Target Texture
517
503
  {0,
518
504
  0,
519
- borderRadii.topLeft.vertical + borderWidths.left,
520
- borderRadii.topLeft.horizontal + borderWidths.top}, // Texture Left, Top, Width, Height
505
+ borderRadii.topLeft.horizontal + borderWidths.left,
506
+ borderRadii.topLeft.vertical + borderWidths.top}, // Texture Left, Top, Width, Height
521
507
  {AnchorPosition::Left, AnchorPosition::Top}, // Layer Anchor Point
522
508
  {0, 0}, // Layer Anchor Offset
523
- {borderRadii.topLeft.vertical + borderWidths.left, borderRadii.topLeft.horizontal + borderWidths.top}, // size
509
+ {borderRadii.topLeft.horizontal + borderWidths.left, borderRadii.topLeft.vertical + borderWidths.top}, // size
524
510
  {0.0f, 0.0f}, // relativeSize
525
511
  std::max(borderWidths.left, borderWidths.top),
526
512
  borderColors.left ? borderColors.left : borderColors.top,
@@ -533,13 +519,13 @@ void DrawAllBorderLayers(
533
519
  spBorderLayers[1],
534
520
  shape,
535
521
  spTextures[1],
536
- {borderRadii.topLeft.vertical + borderWidths.left,
522
+ {borderRadii.topLeft.horizontal + borderWidths.left,
537
523
  0,
538
- textureWidth - (borderRadii.topRight.vertical + borderWidths.right),
524
+ textureWidth - (borderRadii.topRight.horizontal + borderWidths.right),
539
525
  borderWidths.top},
540
526
  {AnchorPosition::Left, AnchorPosition::Top},
541
- {borderRadii.topLeft.vertical + borderWidths.left, 0},
542
- {-(borderRadii.topLeft.vertical + borderWidths.left + borderRadii.topRight.vertical + borderWidths.right),
527
+ {borderRadii.topLeft.horizontal + borderWidths.left, 0},
528
+ {-(borderRadii.topLeft.horizontal + borderWidths.left + borderRadii.topRight.horizontal + borderWidths.right),
543
529
  borderWidths.top}, // size
544
530
  {1.0f, 0.0f}, // relativeSize
545
531
  borderWidths.top,
@@ -553,13 +539,13 @@ void DrawAllBorderLayers(
553
539
  spBorderLayers[2],
554
540
  shape,
555
541
  spTextures[2],
556
- {textureWidth - (borderRadii.topRight.vertical + borderWidths.right),
542
+ {textureWidth - (borderRadii.topRight.horizontal + borderWidths.right),
557
543
  0,
558
544
  textureWidth,
559
- borderRadii.topRight.horizontal + borderWidths.top},
545
+ borderRadii.topRight.vertical + borderWidths.top},
560
546
  {AnchorPosition::Right, AnchorPosition::Top},
561
- {-(borderRadii.topRight.vertical + borderWidths.right), 0},
562
- {borderRadii.topRight.vertical + borderWidths.right, borderRadii.topRight.horizontal + borderWidths.top},
547
+ {-(borderRadii.topRight.horizontal + borderWidths.right), 0},
548
+ {borderRadii.topRight.horizontal + borderWidths.right, borderRadii.topRight.vertical + borderWidths.top},
563
549
  {0.0f, 0.0f},
564
550
  std::max(borderWidths.right, borderWidths.top),
565
551
  borderColors.right ? borderColors.right : borderColors.top,
@@ -573,14 +559,14 @@ void DrawAllBorderLayers(
573
559
  shape,
574
560
  spTextures[3],
575
561
  {textureWidth - borderWidths.right,
576
- borderWidths.top + borderRadii.topRight.horizontal,
562
+ borderWidths.top + borderRadii.topRight.vertical,
577
563
  textureWidth,
578
- textureHeight - (borderWidths.bottom + borderRadii.bottomRight.horizontal)},
564
+ textureHeight - (borderWidths.bottom + borderRadii.bottomRight.vertical)},
579
565
  {AnchorPosition::Right, AnchorPosition::Top},
580
- {-borderWidths.right, borderWidths.top + borderRadii.topRight.horizontal},
566
+ {-borderWidths.right, borderWidths.top + borderRadii.topRight.vertical},
581
567
  {borderWidths.right,
582
- -(borderWidths.top + borderRadii.topRight.horizontal + borderWidths.bottom +
583
- borderRadii.bottomRight.horizontal)}, // size
568
+ -(borderWidths.top + borderRadii.topRight.vertical + borderWidths.bottom +
569
+ borderRadii.bottomRight.vertical)}, // size
584
570
  {0.0f, 1.0f},
585
571
  borderWidths.right,
586
572
  borderColors.right,
@@ -593,14 +579,14 @@ void DrawAllBorderLayers(
593
579
  spBorderLayers[4],
594
580
  shape,
595
581
  spTextures[4],
596
- {textureWidth - (borderWidths.right + borderRadii.bottomRight.vertical),
597
- textureHeight - (borderWidths.bottom + borderRadii.bottomRight.horizontal),
582
+ {textureWidth - (borderWidths.right + borderRadii.bottomRight.horizontal),
583
+ textureHeight - (borderWidths.bottom + borderRadii.bottomRight.vertical),
598
584
  textureWidth,
599
585
  textureHeight},
600
586
  {AnchorPosition::Right, AnchorPosition::Bottom},
601
- {-(borderWidths.right + borderRadii.bottomRight.vertical),
602
- -(borderWidths.bottom + borderRadii.bottomRight.horizontal)},
603
- {borderWidths.right + borderRadii.bottomRight.vertical, borderWidths.bottom + borderRadii.bottomRight.horizontal},
587
+ {-(borderWidths.right + borderRadii.bottomRight.horizontal),
588
+ -(borderWidths.bottom + borderRadii.bottomRight.vertical)},
589
+ {borderWidths.right + borderRadii.bottomRight.horizontal, borderWidths.bottom + borderRadii.bottomRight.vertical},
604
590
  {0, 0},
605
591
  std::max(borderWidths.right, borderWidths.bottom),
606
592
  borderColors.right ? borderColors.right : borderColors.bottom,
@@ -613,13 +599,14 @@ void DrawAllBorderLayers(
613
599
  spBorderLayers[5],
614
600
  shape,
615
601
  spTextures[5],
616
- {borderWidths.left + borderRadii.bottomLeft.vertical,
602
+ {borderWidths.left + borderRadii.bottomLeft.horizontal,
617
603
  textureHeight - borderWidths.bottom,
618
- textureWidth - (borderWidths.right + borderRadii.bottomRight.vertical),
604
+ textureWidth - (borderWidths.right + borderRadii.bottomRight.horizontal),
619
605
  textureHeight},
620
606
  {AnchorPosition::Left, AnchorPosition::Bottom},
621
- {borderWidths.left + borderRadii.bottomLeft.vertical, -borderWidths.bottom},
622
- {-(borderWidths.right + borderRadii.bottomLeft.vertical + borderWidths.left + borderRadii.bottomRight.vertical),
607
+ {borderWidths.left + borderRadii.bottomLeft.horizontal, -borderWidths.bottom},
608
+ {-(borderWidths.right + borderRadii.bottomLeft.horizontal + borderWidths.left +
609
+ borderRadii.bottomRight.horizontal),
623
610
  borderWidths.bottom},
624
611
  {1.0f, 0.0f},
625
612
  borderWidths.bottom,
@@ -634,12 +621,12 @@ void DrawAllBorderLayers(
634
621
  shape,
635
622
  spTextures[6],
636
623
  {0,
637
- textureHeight - (borderWidths.bottom + borderRadii.bottomLeft.horizontal),
638
- borderWidths.left + borderRadii.bottomLeft.vertical,
624
+ textureHeight - (borderWidths.bottom + borderRadii.bottomLeft.vertical),
625
+ borderWidths.left + borderRadii.bottomLeft.horizontal,
639
626
  textureHeight},
640
627
  {AnchorPosition::Left, AnchorPosition::Bottom},
641
- {0, -(borderWidths.bottom + borderRadii.bottomLeft.horizontal)},
642
- {borderWidths.left + borderRadii.bottomLeft.vertical, borderWidths.bottom + borderRadii.bottomLeft.horizontal},
628
+ {0, -(borderWidths.bottom + borderRadii.bottomLeft.vertical)},
629
+ {borderWidths.left + borderRadii.bottomLeft.horizontal, borderWidths.bottom + borderRadii.bottomLeft.vertical},
643
630
  {0, 0},
644
631
  std::max(borderWidths.left, borderWidths.bottom),
645
632
  borderColors.left ? borderColors.left : borderColors.bottom,
@@ -653,13 +640,13 @@ void DrawAllBorderLayers(
653
640
  shape,
654
641
  spTextures[7],
655
642
  {0,
656
- borderWidths.top + borderRadii.topLeft.horizontal,
643
+ borderWidths.top + borderRadii.topLeft.vertical,
657
644
  borderWidths.left,
658
- textureHeight - (borderWidths.bottom + borderRadii.bottomLeft.horizontal)},
645
+ textureHeight - (borderWidths.bottom + borderRadii.bottomLeft.vertical)},
659
646
  {AnchorPosition::Left, AnchorPosition::Top},
660
- {0, borderWidths.top + borderRadii.topLeft.horizontal},
647
+ {0, borderWidths.top + borderRadii.topLeft.vertical},
661
648
  {borderWidths.left,
662
- -(borderWidths.top + borderRadii.topLeft.horizontal + borderWidths.bottom + borderRadii.bottomLeft.horizontal)},
649
+ -(borderWidths.top + borderRadii.topLeft.vertical + borderWidths.bottom + borderRadii.bottomLeft.vertical)},
663
650
  {0, 1},
664
651
  borderWidths.left,
665
652
  borderColors.left,
@@ -2,6 +2,9 @@
2
2
  #include "pch.h"
3
3
  #include "CompositionContextHelper.h"
4
4
  #include <algorithm>
5
+ #include <cassert>
6
+ #include <exception>
7
+ #include <vector>
5
8
  #if __has_include("Composition.Experimental.SystemCompositionContextHelper.g.cpp")
6
9
  #include "Composition.Experimental.SystemCompositionContextHelper.g.cpp"
7
10
  #endif
@@ -443,30 +446,43 @@ struct CompVisualImpl {
443
446
  void InsertAt(
444
447
  const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual,
445
448
  uint32_t index) noexcept {
449
+ if (index > m_childrenCache.size()) {
450
+ std::terminate();
451
+ }
446
452
  auto containerChildren = InnerVisual().as<typename TTypeRedirects::ContainerVisual>().Children();
447
453
  auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
448
454
  if (index == 0) {
449
455
  containerChildren.InsertAtBottom(compVisual);
450
- return;
456
+ } else {
457
+ auto insertAfter = containerChildren.First();
458
+ for (uint32_t i = 1; i < index; i++)
459
+ insertAfter.MoveNext();
460
+ containerChildren.InsertAbove(compVisual, insertAfter.Current());
461
+ }
462
+ if (index >= m_childrenCache.size()) {
463
+ m_childrenCache.push_back(visual);
464
+ } else {
465
+ m_childrenCache.insert(m_childrenCache.begin() + index, visual);
451
466
  }
452
- auto insertAfter = containerChildren.First();
453
- for (uint32_t i = 1; i < index; i++)
454
- insertAfter.MoveNext();
455
- containerChildren.InsertAbove(compVisual, insertAfter.Current());
456
467
  }
457
468
 
458
469
  void Remove(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept {
459
470
  auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
460
471
  auto containerChildren = InnerVisual().as<typename TTypeRedirects::ContainerVisual>().Children();
461
472
  containerChildren.Remove(compVisual);
473
+ auto it = std::find_if(
474
+ m_childrenCache.begin(), m_childrenCache.end(), [&visual](const auto &cached) { return cached == visual; });
475
+ if (it != m_childrenCache.end()) {
476
+ m_childrenCache.erase(it);
477
+ }
462
478
  }
463
479
 
464
480
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual GetAt(uint32_t index) noexcept {
465
- auto containerChildren = m_visual.as<typename TTypeRedirects::ContainerVisual>().Children();
466
- auto it = containerChildren.First();
467
- for (uint32_t i = 0; i < index; i++)
468
- it.MoveNext();
469
- return TTypeRedirects::CompositionContextHelper::CreateVisual(it.Current());
481
+ if (index < m_childrenCache.size()) {
482
+ return m_childrenCache[index];
483
+ }
484
+ assert(false && "GetAt called with out-of-range index");
485
+ return nullptr;
470
486
  }
471
487
 
472
488
  void SetClippingPath(ID2D1Geometry *clippingPath) noexcept {
@@ -546,6 +562,7 @@ struct CompVisualImpl {
546
562
 
547
563
  protected:
548
564
  TVisual m_visual;
565
+ std::vector<winrt::Microsoft::ReactNative::Composition::Experimental::IVisual> m_childrenCache;
549
566
  };
550
567
 
551
568
  template <typename TTypeRedirects>
@@ -866,30 +883,43 @@ struct CompScrollerVisual : winrt::implements<
866
883
  void InsertAt(
867
884
  const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual,
868
885
  uint32_t index) noexcept {
886
+ if (index > m_childrenCache.size()) {
887
+ std::terminate();
888
+ }
869
889
  auto containerChildren = m_contentVisual.Children();
870
890
  auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
871
891
  if (index == 0) {
872
892
  containerChildren.InsertAtBottom(compVisual);
873
- return;
893
+ } else {
894
+ auto insertAfter = containerChildren.First();
895
+ for (uint32_t i = 1; i < index; i++)
896
+ insertAfter.MoveNext();
897
+ containerChildren.InsertAbove(compVisual, insertAfter.Current());
898
+ }
899
+ if (index >= m_childrenCache.size()) {
900
+ m_childrenCache.push_back(visual);
901
+ } else {
902
+ m_childrenCache.insert(m_childrenCache.begin() + index, visual);
874
903
  }
875
- auto insertAfter = containerChildren.First();
876
- for (uint32_t i = 1; i < index; i++)
877
- insertAfter.MoveNext();
878
- containerChildren.InsertAbove(compVisual, insertAfter.Current());
879
904
  }
880
905
 
881
906
  void Remove(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept {
882
907
  auto compVisual = TTypeRedirects::CompositionContextHelper::InnerVisual(visual);
883
908
  auto containerChildren = m_contentVisual.Children();
884
909
  containerChildren.Remove(compVisual);
910
+ auto it = std::find_if(
911
+ m_childrenCache.begin(), m_childrenCache.end(), [&visual](const auto &cached) { return cached == visual; });
912
+ if (it != m_childrenCache.end()) {
913
+ m_childrenCache.erase(it);
914
+ }
885
915
  }
886
916
 
887
917
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual GetAt(uint32_t index) noexcept {
888
- auto containerChildren = m_visual.as<typename TTypeRedirects::ContainerVisual>().Children();
889
- auto it = containerChildren.First();
890
- for (uint32_t i = 0; i < index; i++)
891
- it.MoveNext();
892
- return TTypeRedirects::CompositionContextHelper::CreateVisual(it.Current());
918
+ if (index < m_childrenCache.size()) {
919
+ return m_childrenCache[index];
920
+ }
921
+ assert(false && "GetAt called with out-of-range index");
922
+ return nullptr;
893
923
  }
894
924
 
895
925
  void Brush(const winrt::Microsoft::ReactNative::Composition::Experimental::IBrush &brush) noexcept {
@@ -1273,6 +1303,12 @@ struct CompScrollerVisual : winrt::implements<
1273
1303
  std::sort(snapPositions.begin(), snapPositions.end());
1274
1304
  snapPositions.erase(std::unique(snapPositions.begin(), snapPositions.end()), snapPositions.end());
1275
1305
 
1306
+ // Skip reconfiguration if snap points haven't changed
1307
+ if (snapPositions == m_previousSnapPositions) {
1308
+ return;
1309
+ }
1310
+ m_previousSnapPositions = snapPositions;
1311
+
1276
1312
  std::vector<typename TTypeRedirects::InteractionTrackerInertiaRestingValue> restingValues;
1277
1313
 
1278
1314
  for (size_t i = 0; i < snapPositions.size(); ++i) {
@@ -1402,6 +1438,7 @@ struct CompScrollerVisual : winrt::implements<
1402
1438
  winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment m_snapToAlignment{
1403
1439
  winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment::Near};
1404
1440
  std::vector<float> m_snapToOffsets;
1441
+ std::vector<float> m_previousSnapPositions;
1405
1442
  bool m_inertia{false};
1406
1443
  bool m_custom{false};
1407
1444
  bool m_interacting{false};
@@ -1428,6 +1465,7 @@ struct CompScrollerVisual : winrt::implements<
1428
1465
  typename TTypeRedirects::SpriteVisual m_contentVisual{nullptr};
1429
1466
  typename TTypeRedirects::InteractionTracker m_interactionTracker{nullptr};
1430
1467
  typename TTypeRedirects::VisualInteractionSource m_visualInteractionSource{nullptr};
1468
+ std::vector<winrt::Microsoft::ReactNative::Composition::Experimental::IVisual> m_childrenCache;
1431
1469
  };
1432
1470
  using WindowsCompScrollerVisual = CompScrollerVisual<WindowsTypeRedirects>;
1433
1471
  #ifdef USE_WINUI3
@@ -2196,7 +2234,6 @@ struct CompContext : winrt::implements<
2196
2234
  winrt::com_ptr<ID3D11Device> m_d3dDevice;
2197
2235
  winrt::com_ptr<ID2D1Device> m_d2dDevice;
2198
2236
  typename TTypeRedirects::CompositionGraphicsDevice m_compositionGraphicsDevice{nullptr};
2199
- winrt::com_ptr<ID3D11DeviceContext> m_d3dDeviceContext;
2200
2237
  };
2201
2238
 
2202
2239
  winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual