Skip to content

Commit f651990

Browse files
committed
Revert "Android: Enable views to be nested within <Text> (facebook#23195)"
1 parent d9711e2 commit f651990

19 files changed

+135
-672
lines changed

Libraries/Components/View/View.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
'use strict';
1212

1313
const React = require('React');
14+
const TextAncestor = require('TextAncestor');
1415
const ViewNativeComponent = require('ViewNativeComponent');
1516

17+
const invariant = require('invariant');
18+
1619
import type {ViewProps} from 'ViewPropTypes';
1720

1821
export type Props = ViewProps;
@@ -32,7 +35,17 @@ if (__DEV__) {
3235
props: Props,
3336
forwardedRef: React.Ref<typeof ViewNativeComponent>,
3437
) => {
35-
return <ViewNativeComponent {...props} ref={forwardedRef} />;
38+
return (
39+
<TextAncestor.Consumer>
40+
{hasTextAncestor => {
41+
invariant(
42+
!hasTextAncestor,
43+
'Nesting of <View> within <Text> is not currently supported.',
44+
);
45+
return <ViewNativeComponent {...props} ref={forwardedRef} />;
46+
}}
47+
</TextAncestor.Consumer>
48+
);
3649
};
3750
ViewToExport = React.forwardRef(View);
3851
ViewToExport.displayName = 'View';

Libraries/Text/Text.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,12 @@ const viewConfig = {
6666
minimumFontScale: true,
6767
textBreakStrategy: true,
6868
onTextLayout: true,
69-
onInlineViewLayout: true,
7069
dataDetectorType: true,
7170
},
7271
directEventTypes: {
7372
topTextLayout: {
7473
registrationName: 'onTextLayout',
7574
},
76-
topInlineViewLayout: {
77-
registrationName: 'onInlineViewLayout',
78-
},
7975
},
8076
uiViewClassName: 'RCTText',
8177
};

ReactAndroid/src/main/java/com/facebook/react/uimanager/IViewManagerWithChildren.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeKind.java

Lines changed: 0 additions & 25 deletions
This file was deleted.

ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,16 @@ public synchronized void updateLayout(
195195
// Check if the parent of the view has to layout the view, or the child has to lay itself out.
196196
if (!mRootTags.get(parentTag)) {
197197
ViewManager parentViewManager = mTagsToViewManagers.get(parentTag);
198-
IViewManagerWithChildren parentViewManagerWithChildren;
199-
if (parentViewManager instanceof IViewManagerWithChildren) {
200-
parentViewManagerWithChildren = (IViewManagerWithChildren) parentViewManager;
198+
ViewGroupManager parentViewGroupManager;
199+
if (parentViewManager instanceof ViewGroupManager) {
200+
parentViewGroupManager = (ViewGroupManager) parentViewManager;
201201
} else {
202202
throw new IllegalViewOperationException(
203203
"Trying to use view with tag " + parentTag +
204-
" as a parent, but its Manager doesn't implement IViewManagerWithChildren");
204+
" as a parent, but its Manager doesn't extends ViewGroupManager");
205205
}
206-
if (parentViewManagerWithChildren != null
207-
&& !parentViewManagerWithChildren.needsCustomLayoutForChildren()) {
206+
if (parentViewGroupManager != null
207+
&& !parentViewGroupManager.needsCustomLayoutForChildren()) {
208208
updateLayout(viewToUpdate, x, y, width, height);
209209
}
210210
} else {

ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyOptimizer.java

Lines changed: 37 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,6 @@ private static class NodeIndexPair {
6464
private final ShadowNodeRegistry mShadowNodeRegistry;
6565
private final SparseBooleanArray mTagsWithLayoutVisited = new SparseBooleanArray();
6666

67-
public static void assertNodeSupportedWithoutOptimizer(ReactShadowNode node) {
68-
// NativeKind.LEAF nodes require the optimizer. They are not ViewGroups so they cannot host
69-
// their native children themselves. Their native children need to be hoisted by the optimizer
70-
// to an ancestor which is a ViewGroup.
71-
Assertions.assertCondition(
72-
node.getNativeKind() != NativeKind.LEAF,
73-
"Nodes with NativeKind.LEAF are not supported when the optimizer is disabled");
74-
}
75-
7667
public NativeViewHierarchyOptimizer(
7768
UIViewOperationQueue uiViewOperationQueue,
7869
ShadowNodeRegistry shadowNodeRegistry) {
@@ -88,7 +79,6 @@ public void handleCreateView(
8879
ThemedReactContext themedContext,
8980
@Nullable ReactStylesDiffMap initialProps) {
9081
if (!ENABLED) {
91-
assertNodeSupportedWithoutOptimizer(node);
9282
int tag = node.getReactTag();
9383
mUIViewOperationQueue.enqueueCreateView(
9484
themedContext,
@@ -102,7 +92,7 @@ public void handleCreateView(
10292
isLayoutOnlyAndCollapsable(initialProps);
10393
node.setIsLayoutOnly(isLayoutOnly);
10494

105-
if (node.getNativeKind() != NativeKind.NONE) {
95+
if (!isLayoutOnly) {
10696
mUIViewOperationQueue.enqueueCreateView(
10797
themedContext,
10898
node.getReactTag(),
@@ -128,7 +118,6 @@ public void handleUpdateView(
128118
String className,
129119
ReactStylesDiffMap props) {
130120
if (!ENABLED) {
131-
assertNodeSupportedWithoutOptimizer(node);
132121
mUIViewOperationQueue.enqueueUpdateProperties(node.getReactTag(), className, props);
133122
return;
134123
}
@@ -159,7 +148,6 @@ public void handleManageChildren(
159148
int[] tagsToDelete,
160149
int[] indicesToDelete) {
161150
if (!ENABLED) {
162-
assertNodeSupportedWithoutOptimizer(nodeToManage);
163151
mUIViewOperationQueue.enqueueManageChildren(
164152
nodeToManage.getReactTag(),
165153
indicesToRemove,
@@ -201,7 +189,6 @@ public void handleSetChildren(
201189
ReadableArray childrenTags
202190
) {
203191
if (!ENABLED) {
204-
assertNodeSupportedWithoutOptimizer(nodeToManage);
205192
mUIViewOperationQueue.enqueueSetChildren(
206193
nodeToManage.getReactTag(),
207194
childrenTags);
@@ -221,9 +208,8 @@ public void handleSetChildren(
221208
*/
222209
public void handleUpdateLayout(ReactShadowNode node) {
223210
if (!ENABLED) {
224-
assertNodeSupportedWithoutOptimizer(node);
225211
mUIViewOperationQueue.enqueueUpdateLayout(
226-
Assertions.assertNotNull(node.getLayoutParent()).getReactTag(),
212+
Assertions.assertNotNull(node.getParent()).getReactTag(),
227213
node.getReactTag(),
228214
node.getScreenX(),
229215
node.getScreenY(),
@@ -235,12 +221,6 @@ public void handleUpdateLayout(ReactShadowNode node) {
235221
applyLayoutBase(node);
236222
}
237223

238-
public void handleForceViewToBeNonLayoutOnly(ReactShadowNode node) {
239-
if (node.isLayoutOnly()) {
240-
transitionLayoutOnlyViewToNativeView(node, null);
241-
}
242-
}
243-
244224
/**
245225
* Processes the shadow hierarchy to dispatch all necessary updateLayout calls to the native
246226
* hierarchy. Should be called after all updateLayout calls for a batch have been handled.
@@ -249,18 +229,16 @@ public void onBatchComplete() {
249229
mTagsWithLayoutVisited.clear();
250230
}
251231

252-
private NodeIndexPair walkUpUntilNativeKindIsParent(
232+
private NodeIndexPair walkUpUntilNonLayoutOnly(
253233
ReactShadowNode node,
254234
int indexInNativeChildren) {
255-
while (node.getNativeKind() != NativeKind.PARENT) {
235+
while (node.isLayoutOnly()) {
256236
ReactShadowNode parent = node.getParent();
257237
if (parent == null) {
258238
return null;
259239
}
260240

261-
indexInNativeChildren = indexInNativeChildren +
262-
(node.getNativeKind() == NativeKind.LEAF ? 1 : 0) +
263-
parent.getNativeOffsetForChild(node);
241+
indexInNativeChildren = indexInNativeChildren + parent.getNativeOffsetForChild(node);
264242
node = parent;
265243
}
266244

@@ -269,8 +247,8 @@ private NodeIndexPair walkUpUntilNativeKindIsParent(
269247

270248
private void addNodeToNode(ReactShadowNode parent, ReactShadowNode child, int index) {
271249
int indexInNativeChildren = parent.getNativeOffsetForChild(parent.getChildAt(index));
272-
if (parent.getNativeKind() != NativeKind.PARENT) {
273-
NodeIndexPair result = walkUpUntilNativeKindIsParent(parent, indexInNativeChildren);
250+
if (parent.isLayoutOnly()) {
251+
NodeIndexPair result = walkUpUntilNonLayoutOnly(parent, indexInNativeChildren);
274252
if (result == null) {
275253
// If the parent hasn't been attached to its native parent yet, don't issue commands to the
276254
// native hierarchy. We'll do that when the parent node actually gets attached somewhere.
@@ -280,26 +258,20 @@ private void addNodeToNode(ReactShadowNode parent, ReactShadowNode child, int in
280258
indexInNativeChildren = result.index;
281259
}
282260

283-
if (child.getNativeKind() != NativeKind.NONE) {
284-
addNativeChild(parent, child, indexInNativeChildren);
261+
if (!child.isLayoutOnly()) {
262+
addNonLayoutNode(parent, child, indexInNativeChildren);
285263
} else {
286-
addNonNativeChild(parent, child, indexInNativeChildren);
264+
addLayoutOnlyNode(parent, child, indexInNativeChildren);
287265
}
288266
}
289267

290268
/**
291-
* For handling node removal from manageChildren. In the case of removing a node which isn't
292-
* hosting its own children (e.g. layout-only or NativeKind.LEAF), we need to recursively remove
293-
* all its children from their native parents.
269+
* For handling node removal from manageChildren. In the case of removing a layout-only node, we
270+
* need to instead recursively remove all its children from their native parents.
294271
*/
295272
private void removeNodeFromParent(ReactShadowNode nodeToRemove, boolean shouldDelete) {
296-
if (nodeToRemove.getNativeKind() != NativeKind.PARENT) {
297-
for (int i = nodeToRemove.getChildCount() - 1; i >= 0; i--) {
298-
removeNodeFromParent(nodeToRemove.getChildAt(i), shouldDelete);
299-
}
300-
}
301-
302273
ReactShadowNode nativeNodeToRemoveFrom = nodeToRemove.getNativeParent();
274+
303275
if (nativeNodeToRemoveFrom != null) {
304276
int index = nativeNodeToRemoveFrom.indexOfNativeChild(nodeToRemove);
305277
nativeNodeToRemoveFrom.removeNativeChildAt(index);
@@ -310,17 +282,21 @@ private void removeNodeFromParent(ReactShadowNode nodeToRemove, boolean shouldDe
310282
null,
311283
shouldDelete ? new int[] {nodeToRemove.getReactTag()} : null,
312284
shouldDelete ? new int[] {index} : null);
285+
} else {
286+
for (int i = nodeToRemove.getChildCount() - 1; i >= 0; i--) {
287+
removeNodeFromParent(nodeToRemove.getChildAt(i), shouldDelete);
288+
}
313289
}
314290
}
315291

316-
private void addNonNativeChild(
317-
ReactShadowNode nativeParent,
318-
ReactShadowNode nonNativeChild,
292+
private void addLayoutOnlyNode(
293+
ReactShadowNode nonLayoutOnlyNode,
294+
ReactShadowNode layoutOnlyNode,
319295
int index) {
320-
addGrandchildren(nativeParent, nonNativeChild, index);
296+
addGrandchildren(nonLayoutOnlyNode, layoutOnlyNode, index);
321297
}
322298

323-
private void addNativeChild(
299+
private void addNonLayoutNode(
324300
ReactShadowNode parent,
325301
ReactShadowNode child,
326302
int index) {
@@ -331,33 +307,30 @@ private void addNativeChild(
331307
new ViewAtIndex[] {new ViewAtIndex(child.getReactTag(), index)},
332308
null,
333309
null);
334-
335-
if (child.getNativeKind() != NativeKind.PARENT) {
336-
addGrandchildren(parent, child, index + 1);
337-
}
338310
}
339311

340312
private void addGrandchildren(
341313
ReactShadowNode nativeParent,
342314
ReactShadowNode child,
343315
int index) {
344-
Assertions.assertCondition(child.getNativeKind() != NativeKind.PARENT);
316+
Assertions.assertCondition(!nativeParent.isLayoutOnly());
345317

346318
// `child` can't hold native children. Add all of `child`'s children to `parent`.
347319
int currentIndex = index;
348320
for (int i = 0; i < child.getChildCount(); i++) {
349321
ReactShadowNode grandchild = child.getChildAt(i);
350322
Assertions.assertCondition(grandchild.getNativeParent() == null);
351323

352-
// Adding this child could result in adding multiple native views
353-
int grandchildCountBefore = nativeParent.getNativeChildCount();
354-
if (grandchild.getNativeKind() == NativeKind.NONE) {
355-
addNonNativeChild(nativeParent, grandchild, currentIndex);
324+
if (grandchild.isLayoutOnly()) {
325+
// Adding this child could result in adding multiple native views
326+
int grandchildCountBefore = nativeParent.getNativeChildCount();
327+
addLayoutOnlyNode(nativeParent, grandchild, currentIndex);
328+
int grandchildCountAfter = nativeParent.getNativeChildCount();
329+
currentIndex += grandchildCountAfter - grandchildCountBefore;
356330
} else {
357-
addNativeChild(nativeParent, grandchild, currentIndex);
331+
addNonLayoutNode(nativeParent, grandchild, currentIndex);
332+
currentIndex++;
358333
}
359-
int grandchildCountAfter = nativeParent.getNativeChildCount();
360-
currentIndex += grandchildCountAfter - grandchildCountBefore;
361334
}
362335
}
363336

@@ -376,16 +349,10 @@ private void applyLayoutBase(ReactShadowNode node) {
376349
int x = node.getScreenX();
377350
int y = node.getScreenY();
378351

379-
while (parent != null && parent.getNativeKind() != NativeKind.PARENT) {
380-
if (!parent.isVirtual()) {
381-
// Skip these additions for virtual nodes. This has the same effect as `getLayout*`
382-
// returning `0`. Virtual nodes aren't in the Yoga tree so we can't call `getLayout*` on
383-
// them.
384-
385-
// TODO(7854667): handle and test proper clipping
386-
x += Math.round(parent.getLayoutX());
387-
y += Math.round(parent.getLayoutY());
388-
}
352+
while (parent != null && parent.isLayoutOnly()) {
353+
// TODO(7854667): handle and test proper clipping
354+
x += Math.round(parent.getLayoutX());
355+
y += Math.round(parent.getLayoutY());
389356

390357
parent = parent.getParent();
391358
}
@@ -394,10 +361,10 @@ private void applyLayoutBase(ReactShadowNode node) {
394361
}
395362

396363
private void applyLayoutRecursive(ReactShadowNode toUpdate, int x, int y) {
397-
if (toUpdate.getNativeKind() != NativeKind.NONE && toUpdate.getNativeParent() != null) {
364+
if (!toUpdate.isLayoutOnly() && toUpdate.getNativeParent() != null) {
398365
int tag = toUpdate.getReactTag();
399366
mUIViewOperationQueue.enqueueUpdateLayout(
400-
toUpdate.getLayoutParent().getReactTag(),
367+
toUpdate.getNativeParent().getReactTag(),
401368
tag,
402369
x,
403370
y,

0 commit comments

Comments
 (0)