@samitouri / QOS-React / commits / c802d29bd1

Use HostContext to warn about invalid View/Text nesting (#12766)

Brian Vaughn committed May 14, 2018 at 15:34 UTC c802d29bd16753aef15863db8fb3f338c0067c75
8 files changed +352 -141
packages/react-native-renderer/src/ReactFabricRenderer.js
+37 -8
@@ -22,7 +22,7 @@ import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
22 import ReactFiberReconciler from 'react-reconciler';
23
24 import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev';
25 -import emptyObject from 'fbjs/lib/emptyObject';
25 +import invariant from 'fbjs/lib/invariant';
26
27 // Modules provided by RN:
28 import TextInputState from 'TextInputState';
@@ -35,6 +35,10 @@ import UIManager from 'UIManager';
35 // This means that they never overlap.
36 let nextReactTag = 2;
37
38 +type HostContext = $ReadOnly<{|
39 + isInAParentText: boolean,
40 +|}>;
41 +
42 /**
43 * This is used for refs on host components.
44 */
@@ -135,7 +139,7 @@ const ReactFabricRenderer = ReactFiberReconciler({
139 type: string,
140 props: Props,
141 rootContainerInstance: Container,
138 - hostContext: {},
142 + hostContext: HostContext,
143 internalInstanceHandle: Object,
144 ): Instance {
145 const tag = nextReactTag;
@@ -151,6 +155,11 @@ const ReactFabricRenderer = ReactFiberReconciler({
155 }
156 }
157
158 + invariant(
159 + type !== 'RCTView' || !hostContext.isInAParentText,
160 + 'Nesting of <View> within <Text> is not currently supported.',
161 + );
162 +
163 const updatePayload = ReactNativeAttributePayload.create(
164 props,
165 viewConfig.validAttributes,
@@ -175,9 +184,14 @@ const ReactFabricRenderer = ReactFiberReconciler({
184 createTextInstance(
185 text: string,
186 rootContainerInstance: Container,
178 - hostContext: {},
187 + hostContext: HostContext,
188 internalInstanceHandle: Object,
189 ): TextInstance {
190 + invariant(
191 + hostContext.isInAParentText,
192 + 'Text strings must be rendered within a <Text> component.',
193 + );
194 +
195 const tag = nextReactTag;
196 nextReactTag += 2;
197
@@ -203,12 +217,27 @@ const ReactFabricRenderer = ReactFiberReconciler({
217 return false;
218 },
219
206 - getRootHostContext(): {} {
207 - return emptyObject;
220 + getRootHostContext(rootContainerInstance: Container): HostContext {
221 + return {isInAParentText: false};
222 },
223
210 - getChildHostContext(): {} {
211 - return emptyObject;
224 + getChildHostContext(
225 + parentHostContext: HostContext,
226 + type: string,
227 + ): HostContext {
228 + const prevIsInAParentText = parentHostContext.isInAParentText;
229 + const isInAParentText =
230 + type === 'AndroidTextInput' || // Android
231 + type === 'RCTMultilineTextInputView' || // iOS
232 + type === 'RCTSinglelineTextInputView' || // iOS
233 + type === 'RCTText' ||
234 + type === 'RCTVirtualText';
235 +
236 + if (prevIsInAParentText !== isInAParentText) {
237 + return {isInAParentText};
238 + } else {
239 + return parentHostContext;
240 + }
241 },
242
243 getPublicInstance(instance) {
@@ -230,7 +259,7 @@ const ReactFabricRenderer = ReactFiberReconciler({
259 oldProps: Props,
260 newProps: Props,
261 rootContainerInstance: Container,
233 - hostContext: {},
262 + hostContext: HostContext,
263 ): null | Object {
264 const viewConfig = instance.canonical.viewConfig;
265 const updatePayload = ReactNativeAttributePayload.diff(
packages/react-native-renderer/src/ReactNativeFiberRenderer.js
+37 -7
@@ -12,6 +12,7 @@ import type {ReactNativeBaseComponentViewConfig} from './ReactNativeTypes';
12 import ReactFiberReconciler from 'react-reconciler';
13 import emptyObject from 'fbjs/lib/emptyObject';
14 import invariant from 'fbjs/lib/invariant';
15 +
16 // Modules provided by RN:
17 import UIManager from 'UIManager';
18 import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev';
@@ -35,6 +36,10 @@ export type Instance = {
36 type Props = Object;
37 type TextInstance = number;
38
39 +type HostContext = $ReadOnly<{|
40 + isInAParentText: boolean,
41 +|}>;
42 +
43 // Counter for uniquely identifying views.
44 // % 10 === 1 means it is a rootTag.
45 // % 2 === 0 means it is a Fabric tag.
@@ -71,7 +76,7 @@ const NativeRenderer = ReactFiberReconciler({
76 type: string,
77 props: Props,
78 rootContainerInstance: Container,
74 - hostContext: {},
79 + hostContext: HostContext,
80 internalInstanceHandle: Object,
81 ): Instance {
82 const tag = allocateTag();
@@ -85,6 +90,11 @@ const NativeRenderer = ReactFiberReconciler({
90 }
91 }
92
93 + invariant(
94 + type !== 'RCTView' || !hostContext.isInAParentText,
95 + 'Nesting of <View> within <Text> is not currently supported.',
96 + );
97 +
98 const updatePayload = ReactNativeAttributePayload.create(
99 props,
100 viewConfig.validAttributes,
@@ -110,9 +120,14 @@ const NativeRenderer = ReactFiberReconciler({
120 createTextInstance(
121 text: string,
122 rootContainerInstance: Container,
113 - hostContext: {},
123 + hostContext: HostContext,
124 internalInstanceHandle: Object,
125 ): TextInstance {
126 + invariant(
127 + hostContext.isInAParentText,
128 + 'Text strings must be rendered within a <Text> component.',
129 + );
130 +
131 const tag = allocateTag();
132
133 UIManager.createView(
@@ -155,12 +170,27 @@ const NativeRenderer = ReactFiberReconciler({
170 return false;
171 },
172
158 - getRootHostContext(): {} {
159 - return emptyObject;
173 + getRootHostContext(rootContainerInstance: Container): HostContext {
174 + return {isInAParentText: false};
175 },
176
162 - getChildHostContext(): {} {
163 - return emptyObject;
177 + getChildHostContext(
178 + parentHostContext: HostContext,
179 + type: string,
180 + ): HostContext {
181 + const prevIsInAParentText = parentHostContext.isInAParentText;
182 + const isInAParentText =
183 + type === 'AndroidTextInput' || // Android
184 + type === 'RCTMultilineTextInputView' || // iOS
185 + type === 'RCTSinglelineTextInputView' || // iOS
186 + type === 'RCTText' ||
187 + type === 'RCTVirtualText';
188 +
189 + if (prevIsInAParentText !== isInAParentText) {
190 + return {isInAParentText};
191 + } else {
192 + return parentHostContext;
193 + }
194 },
195
196 getPublicInstance(instance) {
@@ -181,7 +211,7 @@ const NativeRenderer = ReactFiberReconciler({
211 oldProps: Props,
212 newProps: Props,
213 rootContainerInstance: Container,
184 - hostContext: {},
214 + hostContext: HostContext,
215 ): null | Object {
216 return emptyObject;
217 },
packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
+98 -22
@@ -33,9 +33,9 @@ describe('ReactFabric', () => {
33 });
34
35 it('should be able to create and render a native component', () => {
36 - const View = createReactNativeComponentClass('View', () => ({
36 + const View = createReactNativeComponentClass('RCTView', () => ({
37 validAttributes: {foo: true},
38 - uiViewClassName: 'View',
38 + uiViewClassName: 'RCTView',
39 }));
40
41 ReactFabric.render(<View foo="test" />, 1);
@@ -45,9 +45,9 @@ describe('ReactFabric', () => {
45 });
46
47 it('should be able to create and update a native component', () => {
48 - const View = createReactNativeComponentClass('View', () => ({
48 + const View = createReactNativeComponentClass('RCTView', () => ({
49 validAttributes: {foo: true},
50 - uiViewClassName: 'View',
50 + uiViewClassName: 'RCTView',
51 }));
52
53 const firstNode = {};
@@ -67,9 +67,9 @@ describe('ReactFabric', () => {
67 });
68
69 it('should not call FabricUIManager.cloneNode after render for properties that have not changed', () => {
70 - const Text = createReactNativeComponentClass('Text', () => ({
70 + const Text = createReactNativeComponentClass('RCTText', () => ({
71 validAttributes: {foo: true},
72 - uiViewClassName: 'Text',
72 + uiViewClassName: 'RCTText',
73 }));
74
75 ReactFabric.render(<Text foo="a">1</Text>, 11);
@@ -110,15 +110,15 @@ describe('ReactFabric', () => {
110 });
111
112 it('should only pass props diffs to FabricUIManager.cloneNode', () => {
113 - const View = createReactNativeComponentClass('View', () => ({
113 + const Text = createReactNativeComponentClass('RCTText', () => ({
114 validAttributes: {foo: true, bar: true},
115 - uiViewClassName: 'View',
115 + uiViewClassName: 'RCTText',
116 }));
117
118 ReactFabric.render(
119 - <View foo="a" bar="a">
119 + <Text foo="a" bar="a">
120 1
121 - </View>,
121 + </Text>,
122 11,
123 );
124 expect(FabricUIManager.cloneNode).not.toBeCalled();
@@ -127,9 +127,9 @@ describe('ReactFabric', () => {
127 expect(FabricUIManager.cloneNodeWithNewChildrenAndProps).not.toBeCalled();
128
129 ReactFabric.render(
130 - <View foo="a" bar="b">
130 + <Text foo="a" bar="b">
131 1
132 - </View>,
132 + </Text>,
133 11,
134 );
135 expect(FabricUIManager.cloneNodeWithNewProps.mock.calls[0][1]).toEqual({
@@ -138,9 +138,9 @@ describe('ReactFabric', () => {
138 expect(FabricUIManager.__dumpHierarchyForJestTestsOnly()).toMatchSnapshot();
139
140 ReactFabric.render(
141 - <View foo="b" bar="b">
141 + <Text foo="b" bar="b">
142 2
143 - </View>,
143 + </Text>,
144 11,
145 );
146 expect(
@@ -152,9 +152,9 @@ describe('ReactFabric', () => {
152 });
153
154 it('should not call UIManager.updateView from setNativeProps for properties that have not changed', () => {
155 - const View = createReactNativeComponentClass('View', () => ({
155 + const View = createReactNativeComponentClass('RCTView', () => ({
156 validAttributes: {foo: true},
157 - uiViewClassName: 'View',
157 + uiViewClassName: 'RCTView',
158 }));
159
160 class Subclass extends ReactFabric.NativeComponent {
@@ -187,9 +187,9 @@ describe('ReactFabric', () => {
187 });
188
189 it('returns the correct instance and calls it in the callback', () => {
190 - const View = createReactNativeComponentClass('View', () => ({
190 + const View = createReactNativeComponentClass('RCTView', () => ({
191 validAttributes: {foo: true},
192 - uiViewClassName: 'View',
192 + uiViewClassName: 'RCTView',
193 }));
194
195 let a;
@@ -208,9 +208,9 @@ describe('ReactFabric', () => {
208 });
209
210 it('renders and reorders children', () => {
211 - const View = createReactNativeComponentClass('View', () => ({
211 + const View = createReactNativeComponentClass('RCTView', () => ({
212 validAttributes: {title: true},
213 - uiViewClassName: 'View',
213 + uiViewClassName: 'RCTView',
214 }));
215
216 class Component extends React.Component {
@@ -249,9 +249,9 @@ describe('ReactFabric', () => {
249 });
250
251 it('should call complete after inserting children', () => {
252 - const View = createReactNativeComponentClass('View', () => ({
252 + const View = createReactNativeComponentClass('RCTView', () => ({
253 validAttributes: {foo: true},
254 - uiViewClassName: 'View',
254 + uiViewClassName: 'RCTView',
255 }));
256
257 const snapshots = [];
@@ -272,4 +272,80 @@ describe('ReactFabric', () => {
272 );
273 expect(snapshots).toMatchSnapshot();
274 });
275 +
276 + it('should throw when <View> is used inside of a <Text> ancestor', () => {
277 + const Image = createReactNativeComponentClass('RCTImage', () => ({
278 + validAttributes: {},
279 + uiViewClassName: 'RCTImage',
280 + }));
281 + const Text = createReactNativeComponentClass('RCTText', () => ({
282 + validAttributes: {},
283 + uiViewClassName: 'RCTText',
284 + }));
285 + const View = createReactNativeComponentClass('RCTView', () => ({
286 + validAttributes: {},
287 + uiViewClassName: 'RCTView',
288 + }));
289 +
290 + expect(() =>
291 + ReactFabric.render(
292 + <Text>
293 + <View />
294 + </Text>,
295 + 11,
296 + ),
297 + ).toThrow('Nesting of <View> within <Text> is not currently supported.');
298 +
299 + // Non-View things (e.g. Image) are fine
300 + ReactFabric.render(
301 + <Text>
302 + <Image />
303 + </Text>,
304 + 11,
305 + );
306 + });
307 +
308 + it('should throw for text not inside of a <Text> ancestor', () => {
309 + const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({
310 + validAttributes: {},
311 + uiViewClassName: 'RCTScrollView',
312 + }));
313 + const Text = createReactNativeComponentClass('RCTText', () => ({
314 + validAttributes: {},
315 + uiViewClassName: 'RCTText',
316 + }));
317 + const View = createReactNativeComponentClass('RCTView', () => ({
318 + validAttributes: {},
319 + uiViewClassName: 'RCTView',
320 + }));
321 +
322 + expect(() => ReactFabric.render(<View>this should warn</View>, 11)).toThrow(
323 + 'Text strings must be rendered within a <Text> component.',
324 + );
325 +
326 + expect(() =>
327 + ReactFabric.render(
328 + <Text>
329 + <ScrollView>hi hello hi</ScrollView>
330 + </Text>,
331 + 11,
332 + ),
333 + ).toThrow('Text strings must be rendered within a <Text> component.');
334 + });
335 +
336 + it('should not throw for text inside of an indirect <Text> ancestor', () => {
337 + const Text = createReactNativeComponentClass('RCTText', () => ({
338 + validAttributes: {},
339 + uiViewClassName: 'RCTText',
340 + }));
341 +
342 + const Indirection = () => 'Hi';
343 +
344 + ReactFabric.render(
345 + <Text>
346 + <Indirection />
347 + </Text>,
348 + 11,
349 + );
350 + });
351 });
packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js
+2 -2
@@ -31,9 +31,9 @@ describe('ReactFabric', () => {
31 });
32
33 it('find Fabric nodes with the RN renderer', () => {
34 - const View = createReactNativeComponentClass('View', () => ({
34 + const View = createReactNativeComponentClass('RCTView', () => ({
35 validAttributes: {title: true},
36 - uiViewClassName: 'View',
36 + uiViewClassName: 'RCTView',
37 }));
38
39 let ref = React.createRef();
packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js
+1 -1
@@ -153,7 +153,7 @@ it('handles events', () => {
153 it('handles events on text nodes', () => {
154 expect(RCTEventEmitter.register.mock.calls.length).toBe(1);
155 const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
156 - const Text = fakeRequireNativeComponent('Text', {});
156 + const Text = fakeRequireNativeComponent('RCTText', {});
157
158 class ContextHack extends React.Component {
159 static childContextTypes = {isInAParentText: PropTypes.bool};
packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js
+89 -13
@@ -27,9 +27,9 @@ describe('ReactNative', () => {
27 });
28
29 it('should be able to create and render a native component', () => {
30 - const View = createReactNativeComponentClass('View', () => ({
30 + const View = createReactNativeComponentClass('RCTView', () => ({
31 validAttributes: {foo: true},
32 - uiViewClassName: 'View',
32 + uiViewClassName: 'RCTView',
33 }));
34
35 ReactNative.render(<View foo="test" />, 1);
@@ -40,9 +40,9 @@ describe('ReactNative', () => {
40 });
41
42 it('should be able to create and update a native component', () => {
43 - const View = createReactNativeComponentClass('View', () => ({
43 + const View = createReactNativeComponentClass('RCTView', () => ({
44 validAttributes: {foo: true},
45 - uiViewClassName: 'View',
45 + uiViewClassName: 'RCTView',
46 }));
47
48 ReactNative.render(<View foo="foo" />, 11);
@@ -57,13 +57,13 @@ describe('ReactNative', () => {
57 expect(UIManager.createView.mock.calls.length).toBe(1);
58 expect(UIManager.setChildren.mock.calls.length).toBe(1);
59 expect(UIManager.manageChildren).not.toBeCalled();
60 - expect(UIManager.updateView).toBeCalledWith(3, 'View', {foo: 'bar'});
60 + expect(UIManager.updateView).toBeCalledWith(3, 'RCTView', {foo: 'bar'});
61 });
62
63 it('should not call UIManager.updateView after render for properties that have not changed', () => {
64 - const Text = createReactNativeComponentClass('Text', () => ({
64 + const Text = createReactNativeComponentClass('RCTText', () => ({
65 validAttributes: {foo: true},
66 - uiViewClassName: 'Text',
66 + uiViewClassName: 'RCTText',
67 }));
68
69 ReactNative.render(<Text foo="a">1</Text>, 11);
@@ -87,9 +87,9 @@ describe('ReactNative', () => {
87 });
88
89 it('should not call UIManager.updateView from setNativeProps for properties that have not changed', () => {
90 - const View = createReactNativeComponentClass('View', () => ({
90 + const View = createReactNativeComponentClass('RCTView', () => ({
91 validAttributes: {foo: true},
92 - uiViewClassName: 'View',
92 + uiViewClassName: 'RCTView',
93 }));
94
95 class Subclass extends ReactNative.NativeComponent {
@@ -122,9 +122,9 @@ describe('ReactNative', () => {
122 });
123
124 it('returns the correct instance and calls it in the callback', () => {
125 - const View = createReactNativeComponentClass('View', () => ({
125 + const View = createReactNativeComponentClass('RCTView', () => ({
126 validAttributes: {foo: true},
127 - uiViewClassName: 'View',
127 + uiViewClassName: 'RCTView',
128 }));
129
130 let a;
@@ -143,9 +143,9 @@ describe('ReactNative', () => {
143 });
144
145 it('renders and reorders children', () => {
146 - const View = createReactNativeComponentClass('View', () => ({
146 + const View = createReactNativeComponentClass('RCTView', () => ({
147 validAttributes: {title: true},
148 - uiViewClassName: 'View',
148 + uiViewClassName: 'RCTView',
149 }));
150
151 class Component extends React.Component {
@@ -182,4 +182,80 @@ describe('ReactNative', () => {
182 ReactNative.render(<Component />, 11);
183 expect(mockArgs.length).toEqual(0);
184 });
185 +
186 + it('should throw when <View> is used inside of a <Text> ancestor', () => {
187 + const Image = createReactNativeComponentClass('RCTImage', () => ({
188 + validAttributes: {},
189 + uiViewClassName: 'RCTImage',
190 + }));
191 + const Text = createReactNativeComponentClass('RCTText', () => ({
192 + validAttributes: {},
193 + uiViewClassName: 'RCTText',
194 + }));
195 + const View = createReactNativeComponentClass('RCTView', () => ({
196 + validAttributes: {},
197 + uiViewClassName: 'RCTView',
198 + }));
199 +
200 + expect(() =>
201 + ReactNative.render(
202 + <Text>
203 + <View />
204 + </Text>,
205 + 11,
206 + ),
207 + ).toThrow('Nesting of <View> within <Text> is not currently supported.');
208 +
209 + // Non-View things (e.g. Image) are fine
210 + ReactNative.render(
211 + <Text>
212 + <Image />
213 + </Text>,
214 + 11,
215 + );
216 + });
217 +
218 + it('should throw for text not inside of a <Text> ancestor', () => {
219 + const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({
220 + validAttributes: {},
221 + uiViewClassName: 'RCTScrollView',
222 + }));
223 + const Text = createReactNativeComponentClass('RCTText', () => ({
224 + validAttributes: {},
225 + uiViewClassName: 'RCTText',
226 + }));
227 + const View = createReactNativeComponentClass('RCTView', () => ({
228 + validAttributes: {},
229 + uiViewClassName: 'RCTView',
230 + }));
231 +
232 + expect(() => ReactNative.render(<View>this should warn</View>, 11)).toThrow(
233 + 'Text strings must be rendered within a <Text> component.',
234 + );
235 +
236 + expect(() =>
237 + ReactNative.render(
238 + <Text>
239 + <ScrollView>hi hello hi</ScrollView>
240 + </Text>,
241 + 11,
242 + ),
243 + ).toThrow('Text strings must be rendered within a <Text> component.');
244 + });
245 +
246 + it('should not throw for text inside of an indirect <Text> ancestor', () => {
247 + const Text = createReactNativeComponentClass('RCTText', () => ({
248 + validAttributes: {},
249 + uiViewClassName: 'RCTText',
250 + }));
251 +
252 + const Indirection = () => 'Hi';
253 +
254 + ReactNative.render(
255 + <Text>
256 + <Indirection />
257 + </Text>,
258 + 11,
259 + );
260 + });
261 });
packages/react-native-renderer/src/__tests__/__snapshots__/ReactFabric-test.internal.js.snap
+46 -46
@@ -2,69 +2,69 @@
2
3 exports[`ReactFabric renders and reorders children 1`] = `
4 "11
5 - View null
6 - View {\\"title\\":\\"a\\"}
7 - View {\\"title\\":\\"b\\"}
8 - View {\\"title\\":\\"c\\"}
9 - View {\\"title\\":\\"d\\"}
10 - View {\\"title\\":\\"e\\"}
11 - View {\\"title\\":\\"f\\"}
12 - View {\\"title\\":\\"g\\"}
13 - View {\\"title\\":\\"h\\"}
14 - View {\\"title\\":\\"i\\"}
15 - View {\\"title\\":\\"j\\"}
16 - View {\\"title\\":\\"k\\"}
17 - View {\\"title\\":\\"l\\"}
18 - View {\\"title\\":\\"m\\"}
19 - View {\\"title\\":\\"n\\"}
20 - View {\\"title\\":\\"o\\"}
21 - View {\\"title\\":\\"p\\"}
22 - View {\\"title\\":\\"q\\"}
23 - View {\\"title\\":\\"r\\"}
24 - View {\\"title\\":\\"s\\"}
25 - View {\\"title\\":\\"t\\"}"
5 + RCTView null
6 + RCTView {\\"title\\":\\"a\\"}
7 + RCTView {\\"title\\":\\"b\\"}
8 + RCTView {\\"title\\":\\"c\\"}
9 + RCTView {\\"title\\":\\"d\\"}
10 + RCTView {\\"title\\":\\"e\\"}
11 + RCTView {\\"title\\":\\"f\\"}
12 + RCTView {\\"title\\":\\"g\\"}
13 + RCTView {\\"title\\":\\"h\\"}
14 + RCTView {\\"title\\":\\"i\\"}
15 + RCTView {\\"title\\":\\"j\\"}
16 + RCTView {\\"title\\":\\"k\\"}
17 + RCTView {\\"title\\":\\"l\\"}
18 + RCTView {\\"title\\":\\"m\\"}
19 + RCTView {\\"title\\":\\"n\\"}
20 + RCTView {\\"title\\":\\"o\\"}
21 + RCTView {\\"title\\":\\"p\\"}
22 + RCTView {\\"title\\":\\"q\\"}
23 + RCTView {\\"title\\":\\"r\\"}
24 + RCTView {\\"title\\":\\"s\\"}
25 + RCTView {\\"title\\":\\"t\\"}"
26 `;
27
28 exports[`ReactFabric renders and reorders children 2`] = `
29 "11
30 - View null
31 - View {\\"title\\":\\"m\\"}
32 - View {\\"title\\":\\"x\\"}
33 - View {\\"title\\":\\"h\\"}
34 - View {\\"title\\":\\"p\\"}
35 - View {\\"title\\":\\"g\\"}
36 - View {\\"title\\":\\"w\\"}
37 - View {\\"title\\":\\"f\\"}
38 - View {\\"title\\":\\"r\\"}
39 - View {\\"title\\":\\"a\\"}
40 - View {\\"title\\":\\"l\\"}
41 - View {\\"title\\":\\"k\\"}
42 - View {\\"title\\":\\"e\\"}
43 - View {\\"title\\":\\"o\\"}
44 - View {\\"title\\":\\"i\\"}
45 - View {\\"title\\":\\"v\\"}
46 - View {\\"title\\":\\"c\\"}
47 - View {\\"title\\":\\"s\\"}
48 - View {\\"title\\":\\"t\\"}
49 - View {\\"title\\":\\"z\\"}
50 - View {\\"title\\":\\"y\\"}"
30 + RCTView null
31 + RCTView {\\"title\\":\\"m\\"}
32 + RCTView {\\"title\\":\\"x\\"}
33 + RCTView {\\"title\\":\\"h\\"}
34 + RCTView {\\"title\\":\\"p\\"}
35 + RCTView {\\"title\\":\\"g\\"}
36 + RCTView {\\"title\\":\\"w\\"}
37 + RCTView {\\"title\\":\\"f\\"}
38 + RCTView {\\"title\\":\\"r\\"}
39 + RCTView {\\"title\\":\\"a\\"}
40 + RCTView {\\"title\\":\\"l\\"}
41 + RCTView {\\"title\\":\\"k\\"}
42 + RCTView {\\"title\\":\\"e\\"}
43 + RCTView {\\"title\\":\\"o\\"}
44 + RCTView {\\"title\\":\\"i\\"}
45 + RCTView {\\"title\\":\\"v\\"}
46 + RCTView {\\"title\\":\\"c\\"}
47 + RCTView {\\"title\\":\\"s\\"}
48 + RCTView {\\"title\\":\\"t\\"}
49 + RCTView {\\"title\\":\\"z\\"}
50 + RCTView {\\"title\\":\\"y\\"}"
51 `;
52
53 exports[`ReactFabric should call complete after inserting children 1`] = `
54 Array [
55 - "View {\\"foo\\":\\"a\\"}
56 - View {\\"foo\\":\\"b\\"}",
55 + "RCTView {\\"foo\\":\\"a\\"}
56 + RCTView {\\"foo\\":\\"b\\"}",
57 ]
58 `;
59
60 exports[`ReactFabric should only pass props diffs to FabricUIManager.cloneNode 1`] = `
61 "11
62 - View {\\"foo\\":\\"a\\",\\"bar\\":\\"b\\"}
62 + RCTText {\\"foo\\":\\"a\\",\\"bar\\":\\"b\\"}
63 RCTRawText {\\"text\\":\\"1\\"}"
64 `;
65
66 exports[`ReactFabric should only pass props diffs to FabricUIManager.cloneNode 2`] = `
67 "11
68 - View {\\"foo\\":\\"b\\",\\"bar\\":\\"b\\"}
68 + RCTText {\\"foo\\":\\"b\\",\\"bar\\":\\"b\\"}
69 RCTRawText {\\"text\\":\\"2\\"}"
70 `;
packages/react-native-renderer/src/__tests__/__snapshots__/ReactNativeMount-test.internal.js.snap
+42 -42
@@ -2,50 +2,50 @@
2
3 exports[`ReactNative renders and reorders children 1`] = `
4 "<native root> {}
5 - View null
6 - View {\\"title\\":\\"a\\"}
7 - View {\\"title\\":\\"b\\"}
8 - View {\\"title\\":\\"c\\"}
9 - View {\\"title\\":\\"d\\"}
10 - View {\\"title\\":\\"e\\"}
11 - View {\\"title\\":\\"f\\"}
12 - View {\\"title\\":\\"g\\"}
13 - View {\\"title\\":\\"h\\"}
14 - View {\\"title\\":\\"i\\"}
15 - View {\\"title\\":\\"j\\"}
16 - View {\\"title\\":\\"k\\"}
17 - View {\\"title\\":\\"l\\"}
18 - View {\\"title\\":\\"m\\"}
19 - View {\\"title\\":\\"n\\"}
20 - View {\\"title\\":\\"o\\"}
21 - View {\\"title\\":\\"p\\"}
22 - View {\\"title\\":\\"q\\"}
23 - View {\\"title\\":\\"r\\"}
24 - View {\\"title\\":\\"s\\"}
25 - View {\\"title\\":\\"t\\"}"
5 + RCTView null
6 + RCTView {\\"title\\":\\"a\\"}
7 + RCTView {\\"title\\":\\"b\\"}
8 + RCTView {\\"title\\":\\"c\\"}
9 + RCTView {\\"title\\":\\"d\\"}
10 + RCTView {\\"title\\":\\"e\\"}
11 + RCTView {\\"title\\":\\"f\\"}
12 + RCTView {\\"title\\":\\"g\\"}
13 + RCTView {\\"title\\":\\"h\\"}
14 + RCTView {\\"title\\":\\"i\\"}
15 + RCTView {\\"title\\":\\"j\\"}
16 + RCTView {\\"title\\":\\"k\\"}
17 + RCTView {\\"title\\":\\"l\\"}
18 + RCTView {\\"title\\":\\"m\\"}
19 + RCTView {\\"title\\":\\"n\\"}
20 + RCTView {\\"title\\":\\"o\\"}
21 + RCTView {\\"title\\":\\"p\\"}
22 + RCTView {\\"title\\":\\"q\\"}
23 + RCTView {\\"title\\":\\"r\\"}
24 + RCTView {\\"title\\":\\"s\\"}
25 + RCTView {\\"title\\":\\"t\\"}"
26 `;
27
28 exports[`ReactNative renders and reorders children 2`] = `
29 "<native root> {}
30 - View null
31 - View {\\"title\\":\\"m\\"}
32 - View {\\"title\\":\\"x\\"}
33 - View {\\"title\\":\\"h\\"}
34 - View {\\"title\\":\\"p\\"}
35 - View {\\"title\\":\\"g\\"}
36 - View {\\"title\\":\\"w\\"}
37 - View {\\"title\\":\\"f\\"}
38 - View {\\"title\\":\\"r\\"}
39 - View {\\"title\\":\\"a\\"}
40 - View {\\"title\\":\\"l\\"}
41 - View {\\"title\\":\\"k\\"}
42 - View {\\"title\\":\\"e\\"}
43 - View {\\"title\\":\\"o\\"}
44 - View {\\"title\\":\\"i\\"}
45 - View {\\"title\\":\\"v\\"}
46 - View {\\"title\\":\\"c\\"}
47 - View {\\"title\\":\\"s\\"}
48 - View {\\"title\\":\\"t\\"}
49 - View {\\"title\\":\\"z\\"}
50 - View {\\"title\\":\\"y\\"}"
30 + RCTView null
31 + RCTView {\\"title\\":\\"m\\"}
32 + RCTView {\\"title\\":\\"x\\"}
33 + RCTView {\\"title\\":\\"h\\"}
34 + RCTView {\\"title\\":\\"p\\"}
35 + RCTView {\\"title\\":\\"g\\"}
36 + RCTView {\\"title\\":\\"w\\"}
37 + RCTView {\\"title\\":\\"f\\"}
38 + RCTView {\\"title\\":\\"r\\"}
39 + RCTView {\\"title\\":\\"a\\"}
40 + RCTView {\\"title\\":\\"l\\"}
41 + RCTView {\\"title\\":\\"k\\"}
42 + RCTView {\\"title\\":\\"e\\"}
43 + RCTView {\\"title\\":\\"o\\"}
44 + RCTView {\\"title\\":\\"i\\"}
45 + RCTView {\\"title\\":\\"v\\"}
46 + RCTView {\\"title\\":\\"c\\"}
47 + RCTView {\\"title\\":\\"s\\"}
48 + RCTView {\\"title\\":\\"t\\"}
49 + RCTView {\\"title\\":\\"z\\"}
50 + RCTView {\\"title\\":\\"y\\"}"
51 `;