Skip to content

Commit

Permalink
Fix crash when SVG is unloaded by XAML (#2195)
Browse files Browse the repository at this point in the history
XAML may unload the root SVG panel, which will trigger a recursive unload. For GroupView, this unload will clear the child collection. However, active operations on the SVG from the React Native UIManager may still be in flight, in which case we may attempt to remove a child that has already been cleared by the root unload.
  • Loading branch information
rozele committed Jan 3, 2024
1 parent d1b0215 commit 07b9ca5
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 6 deletions.
10 changes: 6 additions & 4 deletions windows/RNSVG/GroupViewManager.cpp
Expand Up @@ -71,11 +71,13 @@ void GroupViewManager::RemoveAllChildren(FrameworkElement const &parent) {

void GroupViewManager::RemoveChildAt(FrameworkElement const &parent, int64_t index) {
if (auto const &groupView{parent.try_as<RNSVG::GroupView>()}) {
auto const &child{groupView.Children().GetAt(static_cast<uint32_t>(index))};
child.Unload();
child.SvgParent(nullptr);
if (!groupView.IsUnloaded()) {
auto const &child{groupView.Children().GetAt(static_cast<uint32_t>(index))};
child.Unload();
child.SvgParent(nullptr);

groupView.Children().RemoveAt(static_cast<uint32_t>(index));
groupView.Children().RemoveAt(static_cast<uint32_t>(index));
}

if (auto const &root{groupView.SvgRoot()}) {
root.Invalidate();
Expand Down
3 changes: 2 additions & 1 deletion windows/RNSVG/RenderableView.cpp
Expand Up @@ -358,6 +358,7 @@ void RenderableView::Unload() {
m_propList.clear();
m_propSetMap.clear();
m_strokeDashArray.Clear();
m_isUnloaded = true;
}

RNSVG::IRenderable RenderableView::HitTest(Point const &point) {
Expand All @@ -370,7 +371,7 @@ RNSVG::IRenderable RenderableView::HitTest(Point const &point) {
if (auto const &svgRoot{SvgRoot()}) {
float canvasDiagonal{Utils::GetCanvasDiagonal(svgRoot.ActualSize())};
float strokeWidth{Utils::GetAbsoluteLength(StrokeWidth(), canvasDiagonal)};

check_hresult(geometry->StrokeContainsPoint(pointD2D, strokeWidth, nullptr, nullptr, &strokeContainsPoint));
}

Expand Down
5 changes: 4 additions & 1 deletion windows/RNSVG/RenderableView.h
Expand Up @@ -25,6 +25,8 @@ struct RenderableView : RenderableViewT<RenderableView> {
bool IsResponsible() { return m_isResponsible; }
void IsResponsible(bool isResponsible) { m_isResponsible = isResponsible; }

bool IsUnloaded() { return m_isUnloaded; }

hstring FillBrushId() { return m_fillBrushId; }
Windows::UI::Color Fill() { return m_fill; }
float FillOpacity() { return m_fillOpacity; }
Expand Down Expand Up @@ -73,7 +75,8 @@ struct RenderableView : RenderableViewT<RenderableView> {
RNSVG::D2DGeometry m_geometry{nullptr};
bool m_recreateResources{true};
bool m_isResponsible{false};

bool m_isUnloaded{false};

hstring m_id{L""};
hstring m_clipPathId{L""};
Numerics::float3x2 m_transformMatrix{Numerics::make_float3x2_rotation(0)};
Expand Down
1 change: 1 addition & 0 deletions windows/RNSVG/Views.idl
Expand Up @@ -38,6 +38,7 @@ namespace RNSVG
{
RenderableView(Microsoft.ReactNative.IReactContext context);
SvgView SvgRoot{ get; };
Boolean IsUnloaded { get; };

String Id{ get; };
Windows.Foundation.Numerics.Matrix3x2 SvgTransform{ get; };
Expand Down

0 comments on commit 07b9ca5

Please sign in to comment.