mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix a crash in Fabric View Culling when wrapping view is unflattened (#49845)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49845 changelog: [internal] Fixes a crash that occurs when culled view's ancestor is flattened/unflattened. Reviewed By: lenaic Differential Revision: D70620103 fbshipit-source-id: 20b7f9acd59c5e74e768d31ff1f96bdd06747389
This commit is contained in:
committed by
Facebook GitHub Bot
parent
cc761e42c8
commit
f5682d64eb
Vendored
+109
@@ -840,3 +840,112 @@ test('culling when ScrollView parent has transform', () => {
|
||||
'Insert {type: "View", parentNativeID: (root), index: 0, nativeID: (N/A)}',
|
||||
]);
|
||||
});
|
||||
|
||||
test('view flattening with culling', () => {
|
||||
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
|
||||
let maybeNode;
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{height: 100, width: 100}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
marginTop: 150,
|
||||
}}>
|
||||
<View
|
||||
nativeID={'child'}
|
||||
style={{height: 10, width: 10, backgroundColor: 'red'}}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
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)}',
|
||||
]);
|
||||
|
||||
const element = ensureInstance(maybeNode, ReactNativeElement);
|
||||
|
||||
Fantom.runOnUIThread(() => {
|
||||
Fantom.scrollTo(element, {
|
||||
x: 0,
|
||||
y: 60,
|
||||
});
|
||||
});
|
||||
|
||||
Fantom.runWorkLoop();
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "ScrollView", nativeID: (N/A)}',
|
||||
'Create {type: "View", nativeID: "child"}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
|
||||
]);
|
||||
|
||||
// force view to be unflattened.
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{height: 100, width: 100}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
marginTop: 150,
|
||||
opacity: 0, // force view to be unflattened
|
||||
}}>
|
||||
<View
|
||||
nativeID={'child'}
|
||||
style={{height: 10, width: 10, backgroundColor: 'red'}}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "View", nativeID: "child"}',
|
||||
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
|
||||
'Create {type: "View", nativeID: (N/A)}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
|
||||
]);
|
||||
|
||||
// force view to be flattened.
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{height: 100, width: 100}}
|
||||
ref={node => {
|
||||
maybeNode = node;
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
marginTop: 150,
|
||||
}}>
|
||||
<View
|
||||
nativeID={'child'}
|
||||
style={{height: 10, width: 10, backgroundColor: 'red'}}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "View", nativeID: "child"}',
|
||||
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
|
||||
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
|
||||
'Delete {type: "View", nativeID: (N/A)}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -201,6 +201,11 @@ static void updateMatchedPairSubtrees(
|
||||
<< newPair << " with parent [" << parentTag << "]";
|
||||
});
|
||||
|
||||
auto oldCullingContextCopy =
|
||||
oldCullingContext.adjustCullingContextIfNeeded(oldPair);
|
||||
auto newCullingContextCopy =
|
||||
newCullingContext.adjustCullingContextIfNeeded(newPair);
|
||||
|
||||
// Flattening
|
||||
if (!oldPair.flattened) {
|
||||
// Flatten old tree into new list
|
||||
@@ -217,8 +222,8 @@ static void updateMatchedPairSubtrees(
|
||||
oldPair.shadowView.tag,
|
||||
nullptr,
|
||||
nullptr,
|
||||
oldCullingContext,
|
||||
newCullingContext);
|
||||
oldCullingContextCopy,
|
||||
newCullingContextCopy);
|
||||
}
|
||||
// Unflattening
|
||||
else {
|
||||
@@ -230,7 +235,7 @@ static void updateMatchedPairSubtrees(
|
||||
// + zIndex: the children could be listed before the parent,
|
||||
// interwoven with children from other nodes, etc.
|
||||
auto oldFlattenedNodes = sliceChildShadowNodeViewPairsFromViewNodePair(
|
||||
oldPair, scope, true, oldCullingContext);
|
||||
oldPair, scope, true, oldCullingContextCopy);
|
||||
for (size_t i = 0, j = 0;
|
||||
i < oldChildPairs.size() && j < oldFlattenedNodes.size();
|
||||
i++) {
|
||||
@@ -252,8 +257,8 @@ static void updateMatchedPairSubtrees(
|
||||
parentTag,
|
||||
nullptr,
|
||||
nullptr,
|
||||
oldCullingContext,
|
||||
newCullingContext);
|
||||
oldCullingContextCopy,
|
||||
newCullingContextCopy);
|
||||
|
||||
// If old nodes were not visited, we know that we can delete
|
||||
// them now. They will be removed from the hierarchy by the
|
||||
|
||||
Reference in New Issue
Block a user