From c9c1ca60f550e0178550f01009f95ee6d454e1d2 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 09:22:12 -0700 Subject: [PATCH 01/15] Use HostContext to warn about invalid view/text nesting --- .../src/ReactNativeFiberRenderer.js | 36 +++++++++++++++---- scripts/rollup/modules.js | 1 + 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 7de768b3b2981..a62f238699cb3 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -12,8 +12,10 @@ import type {ReactNativeBaseComponentViewConfig} from './ReactNativeTypes'; import ReactFiberReconciler from 'react-reconciler'; import emptyObject from 'fbjs/lib/emptyObject'; import invariant from 'fbjs/lib/invariant'; +import warning from 'fbjs/lib/warning'; // Modules provided by RN: import UIManager from 'UIManager'; +import Platform from 'Platform'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry'; @@ -35,6 +37,10 @@ export type Instance = { type Props = Object; type TextInstance = number; +type HostContext = { + type: string, +}; + // Counter for uniquely identifying views. // % 10 === 1 means it is a rootTag. // % 2 === 0 means it is a Fabric tag. @@ -71,7 +77,7 @@ const NativeRenderer = ReactFiberReconciler({ type: string, props: Props, rootContainerInstance: Container, - hostContext: {}, + hostContext: HostContext, internalInstanceHandle: Object, ): Instance { const tag = allocateTag(); @@ -83,6 +89,13 @@ const NativeRenderer = ReactFiberReconciler({ deepFreezeAndThrowOnMutationInDev(props[key]); } } + + const ancestorType = hostContext.type; + warning( + (ancestorType !== 'RCTText' && ancestorType !== 'RCTVirtualText') || + Platform.OS !== 'android', + 'Nesting of within is not supported on Android.', + ); } const updatePayload = ReactNativeAttributePayload.create( @@ -110,11 +123,19 @@ const NativeRenderer = ReactFiberReconciler({ createTextInstance( text: string, rootContainerInstance: Container, - hostContext: {}, + hostContext: HostContext, internalInstanceHandle: Object, ): TextInstance { const tag = allocateTag(); + if (__DEV__) { + const ancestorType = hostContext.type; + warning( + ancestorType === 'RCTText' || ancestorType === 'RCTVirtualText', + 'Text strings must have a ancestor.', + ); + } + UIManager.createView( tag, // reactTag 'RCTRawText', // viewName @@ -155,12 +176,15 @@ const NativeRenderer = ReactFiberReconciler({ return false; }, - getRootHostContext(): {} { - return emptyObject; + getRootHostContext(rootContainerInstance: Container): HostContext { + return {type: 'root'}; }, - getChildHostContext(): {} { - return emptyObject; + getChildHostContext( + parentHostContext: HostContext, + type: string, + ): HostContext { + return {type}; }, getPublicInstance(instance) { diff --git a/scripts/rollup/modules.js b/scripts/rollup/modules.js index 5daeaed9c13b4..33472cc12f012 100644 --- a/scripts/rollup/modules.js +++ b/scripts/rollup/modules.js @@ -18,6 +18,7 @@ const importSideEffects = Object.freeze({ 'fbjs/lib/camelizeStyleName': HAS_NO_SIDE_EFFECTS_ON_IMPORT, 'fbjs/lib/hyphenateStyleName': HAS_NO_SIDE_EFFECTS_ON_IMPORT, deepFreezeAndThrowOnMutationInDev: HAS_NO_SIDE_EFFECTS_ON_IMPORT, + Platform: HAS_NO_SIDE_EFFECTS_ON_IMPORT, }); // Bundles exporting globals that other modules rely on. From fcf2f7af0f07bb6e00f2589eef1aa00fcd704a45 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 09:40:16 -0700 Subject: [PATCH 02/15] Added tests for HostContext warning behavior --- .../ReactNativeMount-test.internal.js | 89 ++++++++++++++++--- .../ReactNativeMount-test.internal.js.snap | 84 ++++++++--------- 2 files changed, 118 insertions(+), 55 deletions(-) diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js index f93a369d87251..41a9f27dbdad8 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js @@ -27,9 +27,9 @@ describe('ReactNative', () => { }); it('should be able to create and render a native component', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); ReactNative.render(, 1); @@ -40,9 +40,9 @@ describe('ReactNative', () => { }); it('should be able to create and update a native component', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); ReactNative.render(, 11); @@ -57,13 +57,13 @@ describe('ReactNative', () => { expect(UIManager.createView.mock.calls.length).toBe(1); expect(UIManager.setChildren.mock.calls.length).toBe(1); expect(UIManager.manageChildren).not.toBeCalled(); - expect(UIManager.updateView).toBeCalledWith(3, 'View', {foo: 'bar'}); + expect(UIManager.updateView).toBeCalledWith(3, 'RCTView', {foo: 'bar'}); }); it('should not call UIManager.updateView after render for properties that have not changed', () => { - const Text = createReactNativeComponentClass('Text', () => ({ + const Text = createReactNativeComponentClass('RCTText', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'Text', + uiViewClassName: 'RCTText', })); ReactNative.render(1, 11); @@ -87,9 +87,9 @@ describe('ReactNative', () => { }); it('should not call UIManager.updateView from setNativeProps for properties that have not changed', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); class Subclass extends ReactNative.NativeComponent { @@ -122,9 +122,9 @@ describe('ReactNative', () => { }); it('returns the correct instance and calls it in the callback', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); let a; @@ -143,9 +143,9 @@ describe('ReactNative', () => { }); it('renders and reorders children', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {title: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); class Component extends React.Component { @@ -182,4 +182,67 @@ describe('ReactNative', () => { ReactNative.render(, 11); expect(mockArgs.length).toEqual(0); }); + + ['ios', 'android'].forEach(platform => { + it('should warn about inside of a ancestor for Android', () => { + const Platform = require('Platform'); + Platform.OS = platform; + + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); + const View = createReactNativeComponentClass('RCTView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTView', + })); + + if (platform === 'android') { + expect(() => + ReactNative.render( + + + , + 11, + ), + ).toWarnDev( + 'Nesting of within is not supported on Android.', + ); + } else { + ReactNative.render( + + + , + 11, + ); + } + }); + }); + + it('should warn about text not inside of a ancestor', () => { + const View = createReactNativeComponentClass('RCTView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTView', + })); + + expect(() => + ReactNative.render(this should warn, 11), + ).toWarnDev('Text strings must have a ancestor.'); + }); + + it('should not warn warn about text inside of an indirect ancestor', () => { + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); + + const Indirection = () => 'Hi'; + + ReactNative.render( + + + , + 11, + ); + }); }); diff --git a/packages/react-native-renderer/src/__tests__/__snapshots__/ReactNativeMount-test.internal.js.snap b/packages/react-native-renderer/src/__tests__/__snapshots__/ReactNativeMount-test.internal.js.snap index 5225479968090..9cf7df921746b 100644 --- a/packages/react-native-renderer/src/__tests__/__snapshots__/ReactNativeMount-test.internal.js.snap +++ b/packages/react-native-renderer/src/__tests__/__snapshots__/ReactNativeMount-test.internal.js.snap @@ -2,50 +2,50 @@ exports[`ReactNative renders and reorders children 1`] = ` " {} - View null - View {\\"title\\":\\"a\\"} - View {\\"title\\":\\"b\\"} - View {\\"title\\":\\"c\\"} - View {\\"title\\":\\"d\\"} - View {\\"title\\":\\"e\\"} - View {\\"title\\":\\"f\\"} - View {\\"title\\":\\"g\\"} - View {\\"title\\":\\"h\\"} - View {\\"title\\":\\"i\\"} - View {\\"title\\":\\"j\\"} - View {\\"title\\":\\"k\\"} - View {\\"title\\":\\"l\\"} - View {\\"title\\":\\"m\\"} - View {\\"title\\":\\"n\\"} - View {\\"title\\":\\"o\\"} - View {\\"title\\":\\"p\\"} - View {\\"title\\":\\"q\\"} - View {\\"title\\":\\"r\\"} - View {\\"title\\":\\"s\\"} - View {\\"title\\":\\"t\\"}" + RCTView null + RCTView {\\"title\\":\\"a\\"} + RCTView {\\"title\\":\\"b\\"} + RCTView {\\"title\\":\\"c\\"} + RCTView {\\"title\\":\\"d\\"} + RCTView {\\"title\\":\\"e\\"} + RCTView {\\"title\\":\\"f\\"} + RCTView {\\"title\\":\\"g\\"} + RCTView {\\"title\\":\\"h\\"} + RCTView {\\"title\\":\\"i\\"} + RCTView {\\"title\\":\\"j\\"} + RCTView {\\"title\\":\\"k\\"} + RCTView {\\"title\\":\\"l\\"} + RCTView {\\"title\\":\\"m\\"} + RCTView {\\"title\\":\\"n\\"} + RCTView {\\"title\\":\\"o\\"} + RCTView {\\"title\\":\\"p\\"} + RCTView {\\"title\\":\\"q\\"} + RCTView {\\"title\\":\\"r\\"} + RCTView {\\"title\\":\\"s\\"} + RCTView {\\"title\\":\\"t\\"}" `; exports[`ReactNative renders and reorders children 2`] = ` " {} - View null - View {\\"title\\":\\"m\\"} - View {\\"title\\":\\"x\\"} - View {\\"title\\":\\"h\\"} - View {\\"title\\":\\"p\\"} - View {\\"title\\":\\"g\\"} - View {\\"title\\":\\"w\\"} - View {\\"title\\":\\"f\\"} - View {\\"title\\":\\"r\\"} - View {\\"title\\":\\"a\\"} - View {\\"title\\":\\"l\\"} - View {\\"title\\":\\"k\\"} - View {\\"title\\":\\"e\\"} - View {\\"title\\":\\"o\\"} - View {\\"title\\":\\"i\\"} - View {\\"title\\":\\"v\\"} - View {\\"title\\":\\"c\\"} - View {\\"title\\":\\"s\\"} - View {\\"title\\":\\"t\\"} - View {\\"title\\":\\"z\\"} - View {\\"title\\":\\"y\\"}" + RCTView null + RCTView {\\"title\\":\\"m\\"} + RCTView {\\"title\\":\\"x\\"} + RCTView {\\"title\\":\\"h\\"} + RCTView {\\"title\\":\\"p\\"} + RCTView {\\"title\\":\\"g\\"} + RCTView {\\"title\\":\\"w\\"} + RCTView {\\"title\\":\\"f\\"} + RCTView {\\"title\\":\\"r\\"} + RCTView {\\"title\\":\\"a\\"} + RCTView {\\"title\\":\\"l\\"} + RCTView {\\"title\\":\\"k\\"} + RCTView {\\"title\\":\\"e\\"} + RCTView {\\"title\\":\\"o\\"} + RCTView {\\"title\\":\\"i\\"} + RCTView {\\"title\\":\\"v\\"} + RCTView {\\"title\\":\\"c\\"} + RCTView {\\"title\\":\\"s\\"} + RCTView {\\"title\\":\\"t\\"} + RCTView {\\"title\\":\\"z\\"} + RCTView {\\"title\\":\\"y\\"}" `; From 97709b55b2238dd1847f622f4c26d9b4b7b74002 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 09:47:00 -0700 Subject: [PATCH 03/15] Return host context in DEV only --- .../react-native-renderer/src/ReactNativeFiberRenderer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index a62f238699cb3..8fa1450e667d5 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -177,14 +177,14 @@ const NativeRenderer = ReactFiberReconciler({ }, getRootHostContext(rootContainerInstance: Container): HostContext { - return {type: 'root'}; + return __DEV__ ? {type: 'root'} : emptyObject; }, getChildHostContext( parentHostContext: HostContext, type: string, ): HostContext { - return {type}; + return __DEV__ ? {type} : emptyObject; }, getPublicInstance(instance) { From e0bd2836c84cbe7ec8ea2cb7addcf9e04d510479 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 09:47:36 -0700 Subject: [PATCH 04/15] Fixed ReactNativeEvents --- .../src/__tests__/ReactNativeEvents-test.internal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js index 07fbe1692aa6a..13fce4d77d1bb 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js @@ -153,7 +153,7 @@ it('handles events', () => { it('handles events on text nodes', () => { expect(RCTEventEmitter.register.mock.calls.length).toBe(1); const EventEmitter = RCTEventEmitter.register.mock.calls[0][0]; - const Text = fakeRequireNativeComponent('Text', {}); + const Text = fakeRequireNativeComponent('RCTText', {}); class ContextHack extends React.Component { static childContextTypes = {isInAParentText: PropTypes.bool}; From 3b214bca2612a3395a82c5db4be200d8185782b0 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 09:54:37 -0700 Subject: [PATCH 05/15] Simplified HostContext; dont recreate unless value has changed --- .../src/ReactNativeFiberRenderer.js | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 8fa1450e667d5..eae0265cdf77d 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -38,7 +38,7 @@ type Props = Object; type TextInstance = number; type HostContext = { - type: string, + isInAParentText: boolean, }; // Counter for uniquely identifying views. @@ -90,10 +90,8 @@ const NativeRenderer = ReactFiberReconciler({ } } - const ancestorType = hostContext.type; warning( - (ancestorType !== 'RCTText' && ancestorType !== 'RCTVirtualText') || - Platform.OS !== 'android', + !hostContext.isInAParentText || Platform.OS !== 'android', 'Nesting of within is not supported on Android.', ); } @@ -129,9 +127,8 @@ const NativeRenderer = ReactFiberReconciler({ const tag = allocateTag(); if (__DEV__) { - const ancestorType = hostContext.type; warning( - ancestorType === 'RCTText' || ancestorType === 'RCTVirtualText', + hostContext.isInAParentText, 'Text strings must have a ancestor.', ); } @@ -177,14 +174,28 @@ const NativeRenderer = ReactFiberReconciler({ }, getRootHostContext(rootContainerInstance: Container): HostContext { - return __DEV__ ? {type: 'root'} : emptyObject; + return __DEV__ ? {isInAParentText: false} : emptyObject; }, getChildHostContext( parentHostContext: HostContext, type: string, ): HostContext { - return __DEV__ ? {type} : emptyObject; + if (__DEV__) { + const oldIsInAParentText = parentHostContext.isInAParentText; + const newIsInAParentText = + type === 'RCTText' || type === 'RCTVirtualText'; + + if (oldIsInAParentText !== newIsInAParentText) { + return { + isInAParentText: newIsInAParentText, + }; + } else { + return parentHostContext; + } + } + + return emptyObject; }, getPublicInstance(instance) { From 61d1067a8928c3d3cd239af3d66d0a31c6c8718f Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 09:59:14 -0700 Subject: [PATCH 06/15] Added same HostContext changes to fabric renderer --- .../src/ReactFabricRenderer.js | 45 +++++++- .../src/ReactNativeFiberRenderer.js | 4 +- .../__tests__/ReactFabric-test.internal.js | 107 ++++++++++++++---- .../ReactFabricAndNative-test.internal.js | 4 +- .../ReactFabric-test.internal.js.snap | 92 +++++++-------- 5 files changed, 175 insertions(+), 77 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 0ec040bddf05b..61264ec05d0cd 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -23,11 +23,13 @@ import ReactFiberReconciler from 'react-reconciler'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; import emptyObject from 'fbjs/lib/emptyObject'; +import warning from 'fbjs/lib/warning'; // Modules provided by RN: import TextInputState from 'TextInputState'; import FabricUIManager from 'FabricUIManager'; import UIManager from 'UIManager'; +import Platform from 'Platform'; // Counter for uniquely identifying views. // % 10 === 1 means it is a rootTag. @@ -35,6 +37,10 @@ import UIManager from 'UIManager'; // This means that they never overlap. let nextReactTag = 2; +type HostContext = { + isInAParentText: boolean, +}; + /** * This is used for refs on host components. */ @@ -135,7 +141,7 @@ const ReactFabricRenderer = ReactFiberReconciler({ type: string, props: Props, rootContainerInstance: Container, - hostContext: {}, + hostContext: HostContext, internalInstanceHandle: Object, ): Instance { const tag = nextReactTag; @@ -149,6 +155,11 @@ const ReactFabricRenderer = ReactFiberReconciler({ deepFreezeAndThrowOnMutationInDev(props[key]); } } + + warning( + !hostContext.isInAParentText || Platform.OS !== 'android', + 'Nesting of within is not supported on Android.', + ); } const updatePayload = ReactNativeAttributePayload.create( @@ -175,9 +186,16 @@ const ReactFabricRenderer = ReactFiberReconciler({ createTextInstance( text: string, rootContainerInstance: Container, - hostContext: {}, + hostContext: HostContext, internalInstanceHandle: Object, ): TextInstance { + if (__DEV__) { + warning( + hostContext.isInAParentText, + 'Text strings must have a ancestor.', + ); + } + const tag = nextReactTag; nextReactTag += 2; @@ -203,11 +221,28 @@ const ReactFabricRenderer = ReactFiberReconciler({ return false; }, - getRootHostContext(): {} { - return emptyObject; + getRootHostContext(rootContainerInstance: Container): HostContext { + return __DEV__ ? {isInAParentText: false} : emptyObject; }, - getChildHostContext(): {} { + getChildHostContext( + parentHostContext: HostContext, + type: string, + ): HostContext { + if (__DEV__) { + const oldIsInAParentText = parentHostContext.isInAParentText; + const newIsInAParentText = + type === 'RCTText' || type === 'RCTVirtualText'; + + if (oldIsInAParentText !== newIsInAParentText) { + return { + isInAParentText: newIsInAParentText, + }; + } else { + return parentHostContext; + } + } + return emptyObject; }, diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index eae0265cdf77d..1840e23b8575b 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -124,8 +124,6 @@ const NativeRenderer = ReactFiberReconciler({ hostContext: HostContext, internalInstanceHandle: Object, ): TextInstance { - const tag = allocateTag(); - if (__DEV__) { warning( hostContext.isInAParentText, @@ -133,6 +131,8 @@ const NativeRenderer = ReactFiberReconciler({ ); } + const tag = allocateTag(); + UIManager.createView( tag, // reactTag 'RCTRawText', // viewName diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index a1741f7dc4688..4ec268b831535 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -33,9 +33,9 @@ describe('ReactFabric', () => { }); it('should be able to create and render a native component', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); ReactFabric.render(, 1); @@ -45,9 +45,9 @@ describe('ReactFabric', () => { }); it('should be able to create and update a native component', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); const firstNode = {}; @@ -67,9 +67,9 @@ describe('ReactFabric', () => { }); it('should not call FabricUIManager.cloneNode after render for properties that have not changed', () => { - const Text = createReactNativeComponentClass('Text', () => ({ + const Text = createReactNativeComponentClass('RCTText', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'Text', + uiViewClassName: 'RCTText', })); ReactFabric.render(1, 11); @@ -110,15 +110,15 @@ describe('ReactFabric', () => { }); it('should only pass props diffs to FabricUIManager.cloneNode', () => { - const View = createReactNativeComponentClass('View', () => ({ + const Text = createReactNativeComponentClass('RCTText', () => ({ validAttributes: {foo: true, bar: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTText', })); ReactFabric.render( - + 1 - , + , 11, ); expect(FabricUIManager.cloneNode).not.toBeCalled(); @@ -127,9 +127,9 @@ describe('ReactFabric', () => { expect(FabricUIManager.cloneNodeWithNewChildrenAndProps).not.toBeCalled(); ReactFabric.render( - + 1 - , + , 11, ); expect(FabricUIManager.cloneNodeWithNewProps.mock.calls[0][1]).toEqual({ @@ -138,9 +138,9 @@ describe('ReactFabric', () => { expect(FabricUIManager.__dumpHierarchyForJestTestsOnly()).toMatchSnapshot(); ReactFabric.render( - + 2 - , + , 11, ); expect( @@ -152,9 +152,9 @@ describe('ReactFabric', () => { }); it('should not call UIManager.updateView from setNativeProps for properties that have not changed', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); class Subclass extends ReactFabric.NativeComponent { @@ -187,9 +187,9 @@ describe('ReactFabric', () => { }); it('returns the correct instance and calls it in the callback', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); let a; @@ -208,9 +208,9 @@ describe('ReactFabric', () => { }); it('renders and reorders children', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {title: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); class Component extends React.Component { @@ -249,9 +249,9 @@ describe('ReactFabric', () => { }); it('should call complete after inserting children', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {foo: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); const snapshots = []; @@ -272,4 +272,67 @@ describe('ReactFabric', () => { ); expect(snapshots).toMatchSnapshot(); }); + + ['ios', 'android'].forEach(platform => { + it('should warn about inside of a ancestor for Android', () => { + const Platform = require('Platform'); + Platform.OS = platform; + + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); + const View = createReactNativeComponentClass('RCTView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTView', + })); + + if (platform === 'android') { + expect(() => + ReactFabric.render( + + + , + 11, + ), + ).toWarnDev( + 'Nesting of within is not supported on Android.', + ); + } else { + ReactFabric.render( + + + , + 11, + ); + } + }); + }); + + it('should warn about text not inside of a ancestor', () => { + const View = createReactNativeComponentClass('RCTView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTView', + })); + + expect(() => + ReactFabric.render(this should warn, 11), + ).toWarnDev('Text strings must have a ancestor.'); + }); + + it('should not warn warn about text inside of an indirect ancestor', () => { + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); + + const Indirection = () => 'Hi'; + + ReactFabric.render( + + + , + 11, + ); + }); }); diff --git a/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js index a78dd5d228386..faaa82f3efea2 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js @@ -31,9 +31,9 @@ describe('ReactFabric', () => { }); it('find Fabric nodes with the RN renderer', () => { - const View = createReactNativeComponentClass('View', () => ({ + const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {title: true}, - uiViewClassName: 'View', + uiViewClassName: 'RCTView', })); let ref = React.createRef(); diff --git a/packages/react-native-renderer/src/__tests__/__snapshots__/ReactFabric-test.internal.js.snap b/packages/react-native-renderer/src/__tests__/__snapshots__/ReactFabric-test.internal.js.snap index 6e190e635d98c..4a0f4d8cf557a 100644 --- a/packages/react-native-renderer/src/__tests__/__snapshots__/ReactFabric-test.internal.js.snap +++ b/packages/react-native-renderer/src/__tests__/__snapshots__/ReactFabric-test.internal.js.snap @@ -2,69 +2,69 @@ exports[`ReactFabric renders and reorders children 1`] = ` "11 - View null - View {\\"title\\":\\"a\\"} - View {\\"title\\":\\"b\\"} - View {\\"title\\":\\"c\\"} - View {\\"title\\":\\"d\\"} - View {\\"title\\":\\"e\\"} - View {\\"title\\":\\"f\\"} - View {\\"title\\":\\"g\\"} - View {\\"title\\":\\"h\\"} - View {\\"title\\":\\"i\\"} - View {\\"title\\":\\"j\\"} - View {\\"title\\":\\"k\\"} - View {\\"title\\":\\"l\\"} - View {\\"title\\":\\"m\\"} - View {\\"title\\":\\"n\\"} - View {\\"title\\":\\"o\\"} - View {\\"title\\":\\"p\\"} - View {\\"title\\":\\"q\\"} - View {\\"title\\":\\"r\\"} - View {\\"title\\":\\"s\\"} - View {\\"title\\":\\"t\\"}" + RCTView null + RCTView {\\"title\\":\\"a\\"} + RCTView {\\"title\\":\\"b\\"} + RCTView {\\"title\\":\\"c\\"} + RCTView {\\"title\\":\\"d\\"} + RCTView {\\"title\\":\\"e\\"} + RCTView {\\"title\\":\\"f\\"} + RCTView {\\"title\\":\\"g\\"} + RCTView {\\"title\\":\\"h\\"} + RCTView {\\"title\\":\\"i\\"} + RCTView {\\"title\\":\\"j\\"} + RCTView {\\"title\\":\\"k\\"} + RCTView {\\"title\\":\\"l\\"} + RCTView {\\"title\\":\\"m\\"} + RCTView {\\"title\\":\\"n\\"} + RCTView {\\"title\\":\\"o\\"} + RCTView {\\"title\\":\\"p\\"} + RCTView {\\"title\\":\\"q\\"} + RCTView {\\"title\\":\\"r\\"} + RCTView {\\"title\\":\\"s\\"} + RCTView {\\"title\\":\\"t\\"}" `; exports[`ReactFabric renders and reorders children 2`] = ` "11 - View null - View {\\"title\\":\\"m\\"} - View {\\"title\\":\\"x\\"} - View {\\"title\\":\\"h\\"} - View {\\"title\\":\\"p\\"} - View {\\"title\\":\\"g\\"} - View {\\"title\\":\\"w\\"} - View {\\"title\\":\\"f\\"} - View {\\"title\\":\\"r\\"} - View {\\"title\\":\\"a\\"} - View {\\"title\\":\\"l\\"} - View {\\"title\\":\\"k\\"} - View {\\"title\\":\\"e\\"} - View {\\"title\\":\\"o\\"} - View {\\"title\\":\\"i\\"} - View {\\"title\\":\\"v\\"} - View {\\"title\\":\\"c\\"} - View {\\"title\\":\\"s\\"} - View {\\"title\\":\\"t\\"} - View {\\"title\\":\\"z\\"} - View {\\"title\\":\\"y\\"}" + RCTView null + RCTView {\\"title\\":\\"m\\"} + RCTView {\\"title\\":\\"x\\"} + RCTView {\\"title\\":\\"h\\"} + RCTView {\\"title\\":\\"p\\"} + RCTView {\\"title\\":\\"g\\"} + RCTView {\\"title\\":\\"w\\"} + RCTView {\\"title\\":\\"f\\"} + RCTView {\\"title\\":\\"r\\"} + RCTView {\\"title\\":\\"a\\"} + RCTView {\\"title\\":\\"l\\"} + RCTView {\\"title\\":\\"k\\"} + RCTView {\\"title\\":\\"e\\"} + RCTView {\\"title\\":\\"o\\"} + RCTView {\\"title\\":\\"i\\"} + RCTView {\\"title\\":\\"v\\"} + RCTView {\\"title\\":\\"c\\"} + RCTView {\\"title\\":\\"s\\"} + RCTView {\\"title\\":\\"t\\"} + RCTView {\\"title\\":\\"z\\"} + RCTView {\\"title\\":\\"y\\"}" `; exports[`ReactFabric should call complete after inserting children 1`] = ` Array [ - "View {\\"foo\\":\\"a\\"} - View {\\"foo\\":\\"b\\"}", + "RCTView {\\"foo\\":\\"a\\"} + RCTView {\\"foo\\":\\"b\\"}", ] `; exports[`ReactFabric should only pass props diffs to FabricUIManager.cloneNode 1`] = ` "11 - View {\\"foo\\":\\"a\\",\\"bar\\":\\"b\\"} + RCTText {\\"foo\\":\\"a\\",\\"bar\\":\\"b\\"} RCTRawText {\\"text\\":\\"1\\"}" `; exports[`ReactFabric should only pass props diffs to FabricUIManager.cloneNode 2`] = ` "11 - View {\\"foo\\":\\"b\\",\\"bar\\":\\"b\\"} + RCTText {\\"foo\\":\\"b\\",\\"bar\\":\\"b\\"} RCTRawText {\\"text\\":\\"2\\"}" `; From 9e8850fb335ac39c09d5ddbd8517c9f12989e7dc Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 10:29:12 -0700 Subject: [PATCH 07/15] Account for TextInput as well --- packages/react-native-renderer/src/ReactFabricRenderer.js | 6 +++++- .../react-native-renderer/src/ReactNativeFiberRenderer.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 61264ec05d0cd..35821ff017fe2 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -232,7 +232,11 @@ const ReactFabricRenderer = ReactFiberReconciler({ if (__DEV__) { const oldIsInAParentText = parentHostContext.isInAParentText; const newIsInAParentText = - type === 'RCTText' || type === 'RCTVirtualText'; + type === 'AndroidTextInput' || + type === 'RCTMultilineTextInputView' || + type === 'RCTText' || + type === 'RCTSinglelineTextInputView' || + type === 'RCTVirtualText'; if (oldIsInAParentText !== newIsInAParentText) { return { diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 1840e23b8575b..5fe229a0af946 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -184,7 +184,11 @@ const NativeRenderer = ReactFiberReconciler({ if (__DEV__) { const oldIsInAParentText = parentHostContext.isInAParentText; const newIsInAParentText = - type === 'RCTText' || type === 'RCTVirtualText'; + type === 'AndroidTextInput' || + type === 'RCTMultilineTextInputView' || + type === 'RCTText' || + type === 'RCTSinglelineTextInputView' || + type === 'RCTVirtualText'; if (oldIsInAParentText !== newIsInAParentText) { return { From f0f1db259265890298116b49b592bacc0a70d24b Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 10:41:18 -0700 Subject: [PATCH 08/15] Account for Images inside of Text. Remove Android-specific check in anticipation of Tim removing this change on RN --- .../src/ReactFabricRenderer.js | 5 +- .../src/ReactNativeFiberRenderer.js | 5 +- .../__tests__/ReactFabric-test.internal.js | 64 +++++++++---------- .../ReactNativeMount-test.internal.js | 64 +++++++++---------- scripts/rollup/modules.js | 1 - 5 files changed, 64 insertions(+), 75 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 35821ff017fe2..45c7bea049d29 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -29,7 +29,6 @@ import warning from 'fbjs/lib/warning'; import TextInputState from 'TextInputState'; import FabricUIManager from 'FabricUIManager'; import UIManager from 'UIManager'; -import Platform from 'Platform'; // Counter for uniquely identifying views. // % 10 === 1 means it is a rootTag. @@ -157,8 +156,8 @@ const ReactFabricRenderer = ReactFiberReconciler({ } warning( - !hostContext.isInAParentText || Platform.OS !== 'android', - 'Nesting of within is not supported on Android.', + type !== 'RCTView' || !hostContext.isInAParentText, + 'Nesting of within is not currently supported.', ); } diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 5fe229a0af946..667f5c931c11a 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -15,7 +15,6 @@ import invariant from 'fbjs/lib/invariant'; import warning from 'fbjs/lib/warning'; // Modules provided by RN: import UIManager from 'UIManager'; -import Platform from 'Platform'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry'; @@ -91,8 +90,8 @@ const NativeRenderer = ReactFiberReconciler({ } warning( - !hostContext.isInAParentText || Platform.OS !== 'android', - 'Nesting of within is not supported on Android.', + type !== 'RCTView' || !hostContext.isInAParentText, + 'Nesting of within is not currently supported.', ); } diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index 4ec268b831535..66c7d5ad2e6f8 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -273,40 +273,36 @@ describe('ReactFabric', () => { expect(snapshots).toMatchSnapshot(); }); - ['ios', 'android'].forEach(platform => { - it('should warn about inside of a ancestor for Android', () => { - const Platform = require('Platform'); - Platform.OS = platform; - - const Text = createReactNativeComponentClass('RCTText', () => ({ - validAttributes: {}, - uiViewClassName: 'RCTText', - })); - const View = createReactNativeComponentClass('RCTView', () => ({ - validAttributes: {}, - uiViewClassName: 'RCTView', - })); - - if (platform === 'android') { - expect(() => - ReactFabric.render( - - - , - 11, - ), - ).toWarnDev( - 'Nesting of within is not supported on Android.', - ); - } else { - ReactFabric.render( - - - , - 11, - ); - } - }); + it('should warn about inside of a ancestor', () => { + const Image = createReactNativeComponentClass('RCTImage', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTImage', + })); + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); + const View = createReactNativeComponentClass('RCTView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTView', + })); + + expect(() => + ReactFabric.render( + + + , + 11, + ), + ).toWarnDev('Nesting of within is not supported on Android.'); + + // Non-View things (e.g. Image) are fine + ReactFabric.render( + + + , + 11, + ); }); it('should warn about text not inside of a ancestor', () => { diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js index 41a9f27dbdad8..0ca64bc308b19 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js @@ -183,40 +183,36 @@ describe('ReactNative', () => { expect(mockArgs.length).toEqual(0); }); - ['ios', 'android'].forEach(platform => { - it('should warn about inside of a ancestor for Android', () => { - const Platform = require('Platform'); - Platform.OS = platform; - - const Text = createReactNativeComponentClass('RCTText', () => ({ - validAttributes: {}, - uiViewClassName: 'RCTText', - })); - const View = createReactNativeComponentClass('RCTView', () => ({ - validAttributes: {}, - uiViewClassName: 'RCTView', - })); - - if (platform === 'android') { - expect(() => - ReactNative.render( - - - , - 11, - ), - ).toWarnDev( - 'Nesting of within is not supported on Android.', - ); - } else { - ReactNative.render( - - - , - 11, - ); - } - }); + it('should warn about inside of a ancestor', () => { + const Image = createReactNativeComponentClass('RCTImage', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTImage', + })); + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); + const View = createReactNativeComponentClass('RCTView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTView', + })); + + expect(() => + ReactNative.render( + + + , + 11, + ), + ).toWarnDev('Nesting of within is not supported on Android.'); + + // Non-View things (e.g. Image) are fine + ReactNative.render( + + + , + 11, + ); }); it('should warn about text not inside of a ancestor', () => { diff --git a/scripts/rollup/modules.js b/scripts/rollup/modules.js index 33472cc12f012..5daeaed9c13b4 100644 --- a/scripts/rollup/modules.js +++ b/scripts/rollup/modules.js @@ -18,7 +18,6 @@ const importSideEffects = Object.freeze({ 'fbjs/lib/camelizeStyleName': HAS_NO_SIDE_EFFECTS_ON_IMPORT, 'fbjs/lib/hyphenateStyleName': HAS_NO_SIDE_EFFECTS_ON_IMPORT, deepFreezeAndThrowOnMutationInDev: HAS_NO_SIDE_EFFECTS_ON_IMPORT, - Platform: HAS_NO_SIDE_EFFECTS_ON_IMPORT, }); // Bundles exporting globals that other modules rely on. From c1c080536c0266f2db01bde72c721876c500a293 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 10:55:55 -0700 Subject: [PATCH 09/15] Updated warning in test --- .../src/__tests__/ReactFabric-test.internal.js | 2 +- .../src/__tests__/ReactNativeMount-test.internal.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index 66c7d5ad2e6f8..44501999af896 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -294,7 +294,7 @@ describe('ReactFabric', () => { , 11, ), - ).toWarnDev('Nesting of within is not supported on Android.'); + ).toWarnDev('Nesting of within is not currently supported.'); // Non-View things (e.g. Image) are fine ReactFabric.render( diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js index 0ca64bc308b19..e1ce7df10c856 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js @@ -204,7 +204,7 @@ describe('ReactNative', () => { , 11, ), - ).toWarnDev('Nesting of within is not supported on Android.'); + ).toWarnDev('Nesting of within is not currently supported.'); // Non-View things (e.g. Image) are fine ReactNative.render( From 4821bf861800b6e8b7558c6c6c15a3e6eb63a393 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 10:56:10 -0700 Subject: [PATCH 10/15] Bailout earlier when isInAParentText true --- .../src/ReactFabricRenderer.js | 14 ++++++-------- .../src/ReactNativeFiberRenderer.js | 14 ++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 45c7bea049d29..e7c9c662752ae 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -229,18 +229,16 @@ const ReactFabricRenderer = ReactFiberReconciler({ type: string, ): HostContext { if (__DEV__) { - const oldIsInAParentText = parentHostContext.isInAParentText; - const newIsInAParentText = + if (parentHostContext.isInAParentText) { + return parentHostContext; + } else if ( type === 'AndroidTextInput' || type === 'RCTMultilineTextInputView' || type === 'RCTText' || type === 'RCTSinglelineTextInputView' || - type === 'RCTVirtualText'; - - if (oldIsInAParentText !== newIsInAParentText) { - return { - isInAParentText: newIsInAParentText, - }; + type === 'RCTVirtualText' + ) { + return {isInAParentText: true}; } else { return parentHostContext; } diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 667f5c931c11a..426456d9f2742 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -181,18 +181,16 @@ const NativeRenderer = ReactFiberReconciler({ type: string, ): HostContext { if (__DEV__) { - const oldIsInAParentText = parentHostContext.isInAParentText; - const newIsInAParentText = + if (parentHostContext.isInAParentText) { + return parentHostContext; + } else if ( type === 'AndroidTextInput' || type === 'RCTMultilineTextInputView' || type === 'RCTText' || type === 'RCTSinglelineTextInputView' || - type === 'RCTVirtualText'; - - if (oldIsInAParentText !== newIsInAParentText) { - return { - isInAParentText: newIsInAParentText, - }; + type === 'RCTVirtualText' + ) { + return {isInAParentText: true}; } else { return parentHostContext; } From b8105014772f0a3ed85c944310cd8e0157ea853d Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 8 May 2018 11:42:12 -0700 Subject: [PATCH 11/15] Added a test for foo case --- .../src/ReactFabricRenderer.js | 14 +++++++------- .../src/ReactNativeFiberRenderer.js | 14 +++++++------- .../__tests__/ReactFabric-test.internal.js | 19 ++++++++++++++++++- .../ReactNativeMount-test.internal.js | 19 ++++++++++++++++++- 4 files changed, 50 insertions(+), 16 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index e7c9c662752ae..90ec83990a6ce 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -191,7 +191,7 @@ const ReactFabricRenderer = ReactFiberReconciler({ if (__DEV__) { warning( hostContext.isInAParentText, - 'Text strings must have a ancestor.', + 'Text strings must be rendered within a .', ); } @@ -229,16 +229,16 @@ const ReactFabricRenderer = ReactFiberReconciler({ type: string, ): HostContext { if (__DEV__) { - if (parentHostContext.isInAParentText) { - return parentHostContext; - } else if ( + const prevIsInAParentText = parentHostContext.isInAParentText; + const isInAParentText = type === 'AndroidTextInput' || type === 'RCTMultilineTextInputView' || type === 'RCTText' || type === 'RCTSinglelineTextInputView' || - type === 'RCTVirtualText' - ) { - return {isInAParentText: true}; + type === 'RCTVirtualText'; + + if (prevIsInAParentText !== isInAParentText) { + return {isInAParentText}; } else { return parentHostContext; } diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 426456d9f2742..6d0fa0323357e 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -126,7 +126,7 @@ const NativeRenderer = ReactFiberReconciler({ if (__DEV__) { warning( hostContext.isInAParentText, - 'Text strings must have a ancestor.', + 'Text strings must be rendered within a .', ); } @@ -181,16 +181,16 @@ const NativeRenderer = ReactFiberReconciler({ type: string, ): HostContext { if (__DEV__) { - if (parentHostContext.isInAParentText) { - return parentHostContext; - } else if ( + const prevIsInAParentText = parentHostContext.isInAParentText; + const isInAParentText = type === 'AndroidTextInput' || type === 'RCTMultilineTextInputView' || type === 'RCTText' || type === 'RCTSinglelineTextInputView' || - type === 'RCTVirtualText' - ) { - return {isInAParentText: true}; + type === 'RCTVirtualText'; + + if (prevIsInAParentText !== isInAParentText) { + return {isInAParentText}; } else { return parentHostContext; } diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index 44501999af896..2d1c3b0853300 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -306,6 +306,14 @@ describe('ReactFabric', () => { }); it('should warn about text not inside of a ancestor', () => { + const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTScrollView', + })); + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {}, uiViewClassName: 'RCTView', @@ -313,7 +321,16 @@ describe('ReactFabric', () => { expect(() => ReactFabric.render(this should warn, 11), - ).toWarnDev('Text strings must have a ancestor.'); + ).toWarnDev('Text strings must be rendered within a .'); + + expect(() => + ReactFabric.render( + + hi hello hi + , + 11, + ), + ).toWarnDev('Text strings must be rendered within a .'); }); it('should not warn warn about text inside of an indirect ancestor', () => { diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js index e1ce7df10c856..58a614a18de2c 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js @@ -216,6 +216,14 @@ describe('ReactNative', () => { }); it('should warn about text not inside of a ancestor', () => { + const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTScrollView', + })); + const Text = createReactNativeComponentClass('RCTText', () => ({ + validAttributes: {}, + uiViewClassName: 'RCTText', + })); const View = createReactNativeComponentClass('RCTView', () => ({ validAttributes: {}, uiViewClassName: 'RCTView', @@ -223,7 +231,16 @@ describe('ReactNative', () => { expect(() => ReactNative.render(this should warn, 11), - ).toWarnDev('Text strings must have a ancestor.'); + ).toWarnDev('Text strings must be rendered within a .'); + + expect(() => + ReactNative.render( + + hi hello hi + , + 11, + ), + ).toWarnDev('Text strings must be rendered within a .'); }); it('should not warn warn about text inside of an indirect ancestor', () => { From 079e4ea58819c46f9a26b24f32c66dba1b898f3f Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Thu, 10 May 2018 15:53:19 -0700 Subject: [PATCH 12/15] Replaced warning() with console.error() --- .../src/ReactFabricRenderer.js | 23 +++++++++++------- .../src/ReactNativeFiberRenderer.js | 24 ++++++++++++------- .../__tests__/ReactFabric-test.internal.js | 4 ++-- .../ReactNativeMount-test.internal.js | 4 ++-- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 90ec83990a6ce..5deca0985c719 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -23,7 +23,6 @@ import ReactFiberReconciler from 'react-reconciler'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; import emptyObject from 'fbjs/lib/emptyObject'; -import warning from 'fbjs/lib/warning'; // Modules provided by RN: import TextInputState from 'TextInputState'; @@ -155,10 +154,13 @@ const ReactFabricRenderer = ReactFiberReconciler({ } } - warning( - type !== 'RCTView' || !hostContext.isInAParentText, - 'Nesting of within is not currently supported.', - ); + if (type === 'RCTView' && hostContext.isInAParentText) { + // Intentional use of console.error() rather than fbjs warning(), + // So that React Native redbox is used (rather than yellow box). + console.error( + 'Nesting of within is not currently supported.', + ); + } } const updatePayload = ReactNativeAttributePayload.create( @@ -189,10 +191,13 @@ const ReactFabricRenderer = ReactFiberReconciler({ internalInstanceHandle: Object, ): TextInstance { if (__DEV__) { - warning( - hostContext.isInAParentText, - 'Text strings must be rendered within a .', - ); + if (!hostContext.isInAParentText) { + // Intentional use of console.error() rather than fbjs warning(), + // So that React Native redbox is used (rather than yellow box). + console.error( + 'Text strings must be rendered within a component.', + ); + } } const tag = nextReactTag; diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 6d0fa0323357e..d485de9d3d5ad 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -12,7 +12,7 @@ import type {ReactNativeBaseComponentViewConfig} from './ReactNativeTypes'; import ReactFiberReconciler from 'react-reconciler'; import emptyObject from 'fbjs/lib/emptyObject'; import invariant from 'fbjs/lib/invariant'; -import warning from 'fbjs/lib/warning'; + // Modules provided by RN: import UIManager from 'UIManager'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; @@ -89,10 +89,13 @@ const NativeRenderer = ReactFiberReconciler({ } } - warning( - type !== 'RCTView' || !hostContext.isInAParentText, - 'Nesting of within is not currently supported.', - ); + if (type === 'RCTView' && hostContext.isInAParentText) { + // Intentional use of console.error() rather than fbjs warning(), + // So that React Native redbox is used (rather than yellow box). + console.error( + 'Nesting of within is not currently supported.', + ); + } } const updatePayload = ReactNativeAttributePayload.create( @@ -124,10 +127,13 @@ const NativeRenderer = ReactFiberReconciler({ internalInstanceHandle: Object, ): TextInstance { if (__DEV__) { - warning( - hostContext.isInAParentText, - 'Text strings must be rendered within a .', - ); + if (!hostContext.isInAParentText) { + // Intentional use of console.error() rather than fbjs warning(), + // So that React Native redbox is used (rather than yellow box). + console.error( + 'Text strings must be rendered within a component.', + ); + } } const tag = allocateTag(); diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index 2d1c3b0853300..8d64be0920be3 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -321,7 +321,7 @@ describe('ReactFabric', () => { expect(() => ReactFabric.render(this should warn, 11), - ).toWarnDev('Text strings must be rendered within a .'); + ).toWarnDev('Text strings must be rendered within a component.'); expect(() => ReactFabric.render( @@ -330,7 +330,7 @@ describe('ReactFabric', () => { , 11, ), - ).toWarnDev('Text strings must be rendered within a .'); + ).toWarnDev('Text strings must be rendered within a component.'); }); it('should not warn warn about text inside of an indirect ancestor', () => { diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js index 58a614a18de2c..ef5f8c882b5cc 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js @@ -231,7 +231,7 @@ describe('ReactNative', () => { expect(() => ReactNative.render(this should warn, 11), - ).toWarnDev('Text strings must be rendered within a .'); + ).toWarnDev('Text strings must be rendered within a component.'); expect(() => ReactNative.render( @@ -240,7 +240,7 @@ describe('ReactNative', () => { , 11, ), - ).toWarnDev('Text strings must be rendered within a .'); + ).toWarnDev('Text strings must be rendered within a component.'); }); it('should not warn warn about text inside of an indirect ancestor', () => { From 2cab4bfca74b2427dd26cefc65996a825bc426bc Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 11 May 2018 09:03:43 -0700 Subject: [PATCH 13/15] Made native/fabric HostContext type more explicit --- packages/react-native-renderer/src/ReactFabricRenderer.js | 6 +++--- .../react-native-renderer/src/ReactNativeFiberRenderer.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 5deca0985c719..ac97c7fd82ebf 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -35,9 +35,9 @@ import UIManager from 'UIManager'; // This means that they never overlap. let nextReactTag = 2; -type HostContext = { +type HostContext = $ReadOnly<{| isInAParentText: boolean, -}; +|}>; /** * This is used for refs on host components. @@ -268,7 +268,7 @@ const ReactFabricRenderer = ReactFiberReconciler({ oldProps: Props, newProps: Props, rootContainerInstance: Container, - hostContext: {}, + hostContext: HostContext, ): null | Object { const viewConfig = instance.canonical.viewConfig; const updatePayload = ReactNativeAttributePayload.diff( diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index d485de9d3d5ad..b2f5dec5b47b2 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -36,9 +36,9 @@ export type Instance = { type Props = Object; type TextInstance = number; -type HostContext = { +type HostContext = $ReadOnly<{| isInAParentText: boolean, -}; +|}>; // Counter for uniquely identifying views. // % 10 === 1 means it is a rootTag. @@ -221,7 +221,7 @@ const NativeRenderer = ReactFiberReconciler({ oldProps: Props, newProps: Props, rootContainerInstance: Container, - hostContext: {}, + hostContext: HostContext, ): null | Object { return emptyObject; }, From a1c01b846c7b6dff40603b17766cd86f23b7967e Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 11 May 2018 09:11:08 -0700 Subject: [PATCH 14/15] Replace DEV Text/View nesting check with invariant --- .../src/ReactFabricRenderer.js | 58 ++++++++----------- .../src/ReactNativeFiberRenderer.js | 56 +++++++----------- .../__tests__/ReactFabric-test.internal.js | 16 ++--- .../ReactNativeMount-test.internal.js | 16 ++--- 4 files changed, 61 insertions(+), 85 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index ac97c7fd82ebf..38cbaee09c7f1 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -22,7 +22,7 @@ import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry'; import ReactFiberReconciler from 'react-reconciler'; import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev'; -import emptyObject from 'fbjs/lib/emptyObject'; +import invariant from 'fbjs/lib/invariant'; // Modules provided by RN: import TextInputState from 'TextInputState'; @@ -153,16 +153,13 @@ const ReactFabricRenderer = ReactFiberReconciler({ deepFreezeAndThrowOnMutationInDev(props[key]); } } - - if (type === 'RCTView' && hostContext.isInAParentText) { - // Intentional use of console.error() rather than fbjs warning(), - // So that React Native redbox is used (rather than yellow box). - console.error( - 'Nesting of within is not currently supported.', - ); - } } + invariant( + type !== 'RCTView' || !hostContext.isInAParentText, + 'Nesting of within is not currently supported.', + ); + const updatePayload = ReactNativeAttributePayload.create( props, viewConfig.validAttributes, @@ -190,15 +187,10 @@ const ReactFabricRenderer = ReactFiberReconciler({ hostContext: HostContext, internalInstanceHandle: Object, ): TextInstance { - if (__DEV__) { - if (!hostContext.isInAParentText) { - // Intentional use of console.error() rather than fbjs warning(), - // So that React Native redbox is used (rather than yellow box). - console.error( - 'Text strings must be rendered within a component.', - ); - } - } + invariant( + hostContext.isInAParentText, + 'Text strings must be rendered within a component.', + ); const tag = nextReactTag; nextReactTag += 2; @@ -226,30 +218,26 @@ const ReactFabricRenderer = ReactFiberReconciler({ }, getRootHostContext(rootContainerInstance: Container): HostContext { - return __DEV__ ? {isInAParentText: false} : emptyObject; + return {isInAParentText: false}; }, getChildHostContext( parentHostContext: HostContext, type: string, ): HostContext { - if (__DEV__) { - const prevIsInAParentText = parentHostContext.isInAParentText; - const isInAParentText = - type === 'AndroidTextInput' || - type === 'RCTMultilineTextInputView' || - type === 'RCTText' || - type === 'RCTSinglelineTextInputView' || - type === 'RCTVirtualText'; - - if (prevIsInAParentText !== isInAParentText) { - return {isInAParentText}; - } else { - return parentHostContext; - } + const prevIsInAParentText = parentHostContext.isInAParentText; + const isInAParentText = + type === 'AndroidTextInput' || + type === 'RCTMultilineTextInputView' || + type === 'RCTText' || + type === 'RCTSinglelineTextInputView' || + type === 'RCTVirtualText'; + + if (prevIsInAParentText !== isInAParentText) { + return {isInAParentText}; + } else { + return parentHostContext; } - - return emptyObject; }, getPublicInstance(instance) { diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index b2f5dec5b47b2..8bebdbc7d8ce2 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -88,16 +88,13 @@ const NativeRenderer = ReactFiberReconciler({ deepFreezeAndThrowOnMutationInDev(props[key]); } } - - if (type === 'RCTView' && hostContext.isInAParentText) { - // Intentional use of console.error() rather than fbjs warning(), - // So that React Native redbox is used (rather than yellow box). - console.error( - 'Nesting of within is not currently supported.', - ); - } } + invariant( + type !== 'RCTView' || !hostContext.isInAParentText, + 'Nesting of within is not currently supported.', + ); + const updatePayload = ReactNativeAttributePayload.create( props, viewConfig.validAttributes, @@ -126,15 +123,10 @@ const NativeRenderer = ReactFiberReconciler({ hostContext: HostContext, internalInstanceHandle: Object, ): TextInstance { - if (__DEV__) { - if (!hostContext.isInAParentText) { - // Intentional use of console.error() rather than fbjs warning(), - // So that React Native redbox is used (rather than yellow box). - console.error( - 'Text strings must be rendered within a component.', - ); - } - } + invariant( + hostContext.isInAParentText, + 'Text strings must be rendered within a component.', + ); const tag = allocateTag(); @@ -179,30 +171,26 @@ const NativeRenderer = ReactFiberReconciler({ }, getRootHostContext(rootContainerInstance: Container): HostContext { - return __DEV__ ? {isInAParentText: false} : emptyObject; + return {isInAParentText: false}; }, getChildHostContext( parentHostContext: HostContext, type: string, ): HostContext { - if (__DEV__) { - const prevIsInAParentText = parentHostContext.isInAParentText; - const isInAParentText = - type === 'AndroidTextInput' || - type === 'RCTMultilineTextInputView' || - type === 'RCTText' || - type === 'RCTSinglelineTextInputView' || - type === 'RCTVirtualText'; - - if (prevIsInAParentText !== isInAParentText) { - return {isInAParentText}; - } else { - return parentHostContext; - } + const prevIsInAParentText = parentHostContext.isInAParentText; + const isInAParentText = + type === 'AndroidTextInput' || + type === 'RCTMultilineTextInputView' || + type === 'RCTText' || + type === 'RCTSinglelineTextInputView' || + type === 'RCTVirtualText'; + + if (prevIsInAParentText !== isInAParentText) { + return {isInAParentText}; + } else { + return parentHostContext; } - - return emptyObject; }, getPublicInstance(instance) { diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index 8d64be0920be3..cc697f4ddbc21 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -273,7 +273,7 @@ describe('ReactFabric', () => { expect(snapshots).toMatchSnapshot(); }); - it('should warn about inside of a ancestor', () => { + it('should throw when is used inside of a ancestor', () => { const Image = createReactNativeComponentClass('RCTImage', () => ({ validAttributes: {}, uiViewClassName: 'RCTImage', @@ -294,7 +294,7 @@ describe('ReactFabric', () => { , 11, ), - ).toWarnDev('Nesting of within is not currently supported.'); + ).toThrow('Nesting of within is not currently supported.'); // Non-View things (e.g. Image) are fine ReactFabric.render( @@ -305,7 +305,7 @@ describe('ReactFabric', () => { ); }); - it('should warn about text not inside of a ancestor', () => { + it('should throw for text not inside of a ancestor', () => { const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({ validAttributes: {}, uiViewClassName: 'RCTScrollView', @@ -319,9 +319,9 @@ describe('ReactFabric', () => { uiViewClassName: 'RCTView', })); - expect(() => - ReactFabric.render(this should warn, 11), - ).toWarnDev('Text strings must be rendered within a component.'); + expect(() => ReactFabric.render(this should warn, 11)).toThrow( + 'Text strings must be rendered within a component.', + ); expect(() => ReactFabric.render( @@ -330,10 +330,10 @@ describe('ReactFabric', () => { , 11, ), - ).toWarnDev('Text strings must be rendered within a component.'); + ).toThrow('Text strings must be rendered within a component.'); }); - it('should not warn warn about text inside of an indirect ancestor', () => { + it('should not throw for text inside of an indirect ancestor', () => { const Text = createReactNativeComponentClass('RCTText', () => ({ validAttributes: {}, uiViewClassName: 'RCTText', diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js index ef5f8c882b5cc..60b5d79f5db5a 100644 --- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js @@ -183,7 +183,7 @@ describe('ReactNative', () => { expect(mockArgs.length).toEqual(0); }); - it('should warn about inside of a ancestor', () => { + it('should throw when is used inside of a ancestor', () => { const Image = createReactNativeComponentClass('RCTImage', () => ({ validAttributes: {}, uiViewClassName: 'RCTImage', @@ -204,7 +204,7 @@ describe('ReactNative', () => { , 11, ), - ).toWarnDev('Nesting of within is not currently supported.'); + ).toThrow('Nesting of within is not currently supported.'); // Non-View things (e.g. Image) are fine ReactNative.render( @@ -215,7 +215,7 @@ describe('ReactNative', () => { ); }); - it('should warn about text not inside of a ancestor', () => { + it('should throw for text not inside of a ancestor', () => { const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({ validAttributes: {}, uiViewClassName: 'RCTScrollView', @@ -229,9 +229,9 @@ describe('ReactNative', () => { uiViewClassName: 'RCTView', })); - expect(() => - ReactNative.render(this should warn, 11), - ).toWarnDev('Text strings must be rendered within a component.'); + expect(() => ReactNative.render(this should warn, 11)).toThrow( + 'Text strings must be rendered within a component.', + ); expect(() => ReactNative.render( @@ -240,10 +240,10 @@ describe('ReactNative', () => { , 11, ), - ).toWarnDev('Text strings must be rendered within a component.'); + ).toThrow('Text strings must be rendered within a component.'); }); - it('should not warn warn about text inside of an indirect ancestor', () => { + it('should not throw for text inside of an indirect ancestor', () => { const Text = createReactNativeComponentClass('RCTText', () => ({ validAttributes: {}, uiViewClassName: 'RCTText', From 2ca455562f76217a4e9ea1b3aa728f4850bd7558 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Fri, 11 May 2018 09:15:25 -0700 Subject: [PATCH 15/15] Added an inline comment --- packages/react-native-renderer/src/ReactFabricRenderer.js | 6 +++--- .../react-native-renderer/src/ReactNativeFiberRenderer.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-native-renderer/src/ReactFabricRenderer.js b/packages/react-native-renderer/src/ReactFabricRenderer.js index 38cbaee09c7f1..210ffc8041403 100644 --- a/packages/react-native-renderer/src/ReactFabricRenderer.js +++ b/packages/react-native-renderer/src/ReactFabricRenderer.js @@ -227,10 +227,10 @@ const ReactFabricRenderer = ReactFiberReconciler({ ): HostContext { const prevIsInAParentText = parentHostContext.isInAParentText; const isInAParentText = - type === 'AndroidTextInput' || - type === 'RCTMultilineTextInputView' || + type === 'AndroidTextInput' || // Android + type === 'RCTMultilineTextInputView' || // iOS + type === 'RCTSinglelineTextInputView' || // iOS type === 'RCTText' || - type === 'RCTSinglelineTextInputView' || type === 'RCTVirtualText'; if (prevIsInAParentText !== isInAParentText) { diff --git a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js index 8bebdbc7d8ce2..62ad7d7674620 100644 --- a/packages/react-native-renderer/src/ReactNativeFiberRenderer.js +++ b/packages/react-native-renderer/src/ReactNativeFiberRenderer.js @@ -180,10 +180,10 @@ const NativeRenderer = ReactFiberReconciler({ ): HostContext { const prevIsInAParentText = parentHostContext.isInAParentText; const isInAParentText = - type === 'AndroidTextInput' || - type === 'RCTMultilineTextInputView' || + type === 'AndroidTextInput' || // Android + type === 'RCTMultilineTextInputView' || // iOS + type === 'RCTSinglelineTextInputView' || // iOS type === 'RCTText' || - type === 'RCTSinglelineTextInputView' || type === 'RCTVirtualText'; if (prevIsInAParentText !== isInAParentText) {