From e0b1b63c3feb0d414cb299607c7262a7db57da90 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 23 Apr 2025 05:01:25 -0700 Subject: [PATCH] add view culling test when unflattening a subtree (#50852) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50852 changelog: [internal] Adding a test to verify view culling in scenario where a subtree is revealed and part of it is culled. Reviewed By: lenaic Differential Revision: D73454202 fbshipit-source-id: 6c4fb2ec4757b9ed1460bec8d3f02a661470266f --- .../__tests__/ScrollView-viewCulling-itest.js | 83 +++++++++++++++++++ .../renderer/mounting/Differentiator.cpp | 2 - 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js index fdfbc7b0bc7..a3291568068 100644 --- a/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js +++ b/packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js @@ -1315,3 +1315,86 @@ test('parent-child switching from unflattened-flattened to flattened-unflattened 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}', ]); }); + +test('unflattening and creating a subtree that is partially culled', () => { + const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100}); + + // First render with a flattened view container that is visible. + Fantom.runTask(() => { + root.render( + + + , + ); + }); + + expect(root.takeMountingManagerLogs()).toEqual([ + 'Update {type: "RootView", nativeID: (root)}', + 'Create {type: "ScrollView", nativeID: (N/A)}', + 'Create {type: "View", nativeID: (N/A)}', + 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}', + 'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}', + ]); + + let maybeNode = null; + + // Now update opacity to unflattned the container and add a child that has a culled descendant. + Fantom.runTask(() => { + root.render( + { + maybeNode = node; + }} + contentOffset={{x: 0, y: 111}}> + + + + + + , + ); + }); + + expect(root.takeMountingManagerLogs()).toEqual([ + 'Update {type: "ScrollView", nativeID: (N/A)}', + 'Update {type: "View", nativeID: (N/A)}', + 'Create {type: "View", nativeID: (N/A)}', + 'Create {type: "View", nativeID: "child"}', + 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}', + 'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}', + ]); + + const element = ensureInstance(maybeNode, ReactNativeElement); + + // Scroll down to see the grandchild. + Fantom.scrollTo(element, { + x: 0, + y: 115, + }); + + expect(root.takeMountingManagerLogs()).toEqual([ + 'Update {type: "ScrollView", nativeID: (N/A)}', + 'Create {type: "View", nativeID: "grandchild"}', + 'Insert {type: "View", parentNativeID: "child", index: 0, nativeID: "grandchild"}', + ]); +}); diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp index a7c6307c2cc..53c12b55af4 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp @@ -872,8 +872,6 @@ static void calculateShadowViewMutationsFlattener( if (!treeChildPair.flattened) { ViewNodePairScope innerScope{}; - // TODO(T217775046): Find a test case for this branch of view - // flattening + culling. calculateShadowViewMutations( innerScope, mutationContainer.downwardMutations,