From d421c2530b96f10fe70986b2a1bd0bd4564a295c Mon Sep 17 00:00:00 2001 From: Ondrej Zaruba Date: Wed, 22 Dec 2021 14:51:07 +0100 Subject: [PATCH 1/5] Enable multiple roots with separate contexts --- .../ActivityIndicator/__tests__/index-test.js | 42 +- .../src/exports/AppRegistry/AppContainer.js | 13 +- .../exports/AppRegistry/renderApplication.js | 12 +- .../src/exports/AppRegistry/rootContext.js | 14 + .../exports/Button/__tests__/index-test.js | 16 +- .../exports/CheckBox/__tests__/index-test.js | 38 +- .../src/exports/CheckBox/index.js | 23 +- .../src/exports/Image/__tests__/index-test.js | 66 ++- .../src/exports/Image/index.js | 20 +- .../ImageBackground/__tests__/index.js | 8 +- .../src/exports/Modal/ModalAnimation.js | 16 +- .../src/exports/Modal/ModalFocusTrap.js | 16 +- .../src/exports/Modal/__tests__/index.js | 73 +-- .../src/exports/Picker/PickerItem.js | 6 +- .../exports/Picker/__tests__/index-test.js | 14 +- .../src/exports/Picker/index.js | 78 +-- .../exports/Pressable/__tests__/index-test.js | 40 +- .../ProgressBar/__tests__/index-test.js | 6 +- .../ScrollView/__tests__/index-test.js | 18 +- ...reateStyleResolver.js => StyleResolver.js} | 150 +++--- .../__tests__/createStyleResolver-test.js | 4 +- .../exports/StyleSheet/createCSSStyleSheet.js | 9 +- .../StyleSheet/createOrderedCSSStyleSheet.js | 10 +- .../src/exports/StyleSheet/css.js | 4 +- .../src/exports/StyleSheet/styleResolver.js | 12 - .../exports/Switch/__tests__/index-test.js | 18 +- .../src/exports/Switch/index.js | 30 +- .../src/exports/Text/__tests__/index-test.js | 78 +-- .../src/exports/Text/index.js | 4 +- .../exports/TextInput/__tests__/index-test.js | 116 ++-- .../src/exports/TextInput/index.js | 508 +++++++++--------- .../__tests__/index-test.js | 6 +- .../src/exports/View/__tests__/index-test.js | 68 ++- .../src/exports/View/index.js | 4 +- .../createElement/__tests__/index-test.js | 393 +++++++++----- .../src/exports/createElement/index.js | 4 +- .../createDOMProps/__tests__/index-test.js | 65 ++- .../src/modules/createDOMProps/index.js | 3 +- .../src/modules/usePlatformMethods/index.js | 34 +- .../src/vendor/renderRootContext.js | 35 ++ 40 files changed, 1202 insertions(+), 872 deletions(-) create mode 100644 packages/react-native-web/src/exports/AppRegistry/rootContext.js rename packages/react-native-web/src/exports/StyleSheet/{createStyleResolver.js => StyleResolver.js} (65%) delete mode 100644 packages/react-native-web/src/exports/StyleSheet/styleResolver.js create mode 100644 packages/react-native-web/src/vendor/renderRootContext.js diff --git a/packages/react-native-web/src/exports/ActivityIndicator/__tests__/index-test.js b/packages/react-native-web/src/exports/ActivityIndicator/__tests__/index-test.js index f5ae61b588..0509c173c7 100644 --- a/packages/react-native-web/src/exports/ActivityIndicator/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/ActivityIndicator/__tests__/index-test.js @@ -4,56 +4,64 @@ import ActivityIndicator from '..'; import React from 'react'; import { act } from 'react-dom/test-utils'; import { createEventTarget } from 'dom-event-testing-library'; -import { render } from '@testing-library/react'; +import renderRootContext from '../../../vendor/renderRootContext'; describe('components/ActivityIndicator', () => { describe('prop "accessibilityLabel"', () => { test('value is set', () => { - const { container } = render(); + const { container } = renderRootContext( + + ); expect(container.firstChild).toMatchSnapshot(); }); }); describe('prop "accessibilityLiveRegion"', () => { test('value is set', () => { - const { container } = render(); + const { container } = renderRootContext( + + ); expect(container.firstChild).toMatchSnapshot(); }); }); describe('prop "animating"', () => { test('is "true"', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); test('is "false"', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); }); test('prop "color"', () => { - const { container } = render(); + const { container } = renderRootContext(); const svg = container.firstChild.querySelector('svg'); expect(svg).toMatchSnapshot(); }); describe('prop "dataSet"', () => { test('value is set', () => { - const { container } = render(); + const { container } = renderRootContext( + + ); expect(container.firstChild).toMatchSnapshot(); }); }); describe('prop "hidesWhenStopped"', () => { test('is "true"', () => { - const { container } = render(); + const { container } = renderRootContext( + + ); expect(container.firstChild).toMatchSnapshot(); }); test('is "false"', () => { - const { container } = render( + const { container } = renderRootContext( ); expect(container.firstChild).toMatchSnapshot(); @@ -62,7 +70,7 @@ describe('components/ActivityIndicator', () => { describe('prop "nativeID"', () => { test('value is set', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); }); @@ -72,7 +80,7 @@ describe('components/ActivityIndicator', () => { const onBlur = jest.fn(); const ref = React.createRef(); act(() => { - render(); + renderRootContext(); }); const target = createEventTarget(ref.current); const body = createEventTarget(document.body); @@ -89,7 +97,7 @@ describe('components/ActivityIndicator', () => { const onFocus = jest.fn(); const ref = React.createRef(); act(() => { - render(); + renderRootContext(); }); const target = createEventTarget(ref.current); act(() => { @@ -102,33 +110,33 @@ describe('components/ActivityIndicator', () => { describe('prop "ref"', () => { test('value is set', () => { const ref = jest.fn(); - render(); + renderRootContext(); expect(ref).toBeCalled(); }); }); describe('prop "size"', () => { test('is "large"', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); test('is a number', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); }); describe('prop "style"', () => { test('value is set', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); }); describe('prop "testID"', () => { test('value is set', () => { - const { container } = render(); + const { container } = renderRootContext(); expect(container.firstChild).toMatchSnapshot(); }); }); diff --git a/packages/react-native-web/src/exports/AppRegistry/AppContainer.js b/packages/react-native-web/src/exports/AppRegistry/AppContainer.js index cc5283bfc6..952c14c808 100644 --- a/packages/react-native-web/src/exports/AppRegistry/AppContainer.js +++ b/packages/react-native-web/src/exports/AppRegistry/AppContainer.js @@ -9,6 +9,8 @@ */ import * as React from 'react'; +import RootContext from './rootContext'; +import StyleResolver from '../StyleSheet/StyleResolver'; import StyleSheet from '../StyleSheet'; import View from '../View'; @@ -16,11 +18,10 @@ type Props = { WrapperComponent?: ?React.ComponentType<*>, // $FlowFixMe children?: React.Children, - rootTag: any + rootTag: any, + styleResolver: typeof StyleResolver }; -const RootTagContext: React.Context = React.createContext(null); - export default function AppContainer(props: Props): React.Node { const { children, WrapperComponent } = props; @@ -31,13 +32,13 @@ export default function AppContainer(props: Props): React.Node { if (WrapperComponent) { innerView = {innerView}; } - + const rootContext = { rootTag: props.rootTag, styleResolver: props.styleResolver }; return ( - + {innerView} - + ); } diff --git a/packages/react-native-web/src/exports/AppRegistry/renderApplication.js b/packages/react-native-web/src/exports/AppRegistry/renderApplication.js index 4ea3c4270d..da6613faeb 100644 --- a/packages/react-native-web/src/exports/AppRegistry/renderApplication.js +++ b/packages/react-native-web/src/exports/AppRegistry/renderApplication.js @@ -13,7 +13,7 @@ import type { ComponentType, Node } from 'react'; import AppContainer from './AppContainer'; import invariant from 'fbjs/lib/invariant'; import render, { hydrate } from '../render'; -import styleResolver from '../StyleSheet/styleResolver'; +import StyleResolver from '../StyleSheet/StyleResolver'; import React from 'react'; export default function renderApplication( @@ -29,10 +29,15 @@ export default function renderApplication( const { hydrate: shouldHydrate, initialProps, rootTag } = options; const renderFn = shouldHydrate ? hydrate : render; + const styleResolver = new StyleResolver(options.rootTag); invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag); renderFn( - + , rootTag, @@ -45,8 +50,9 @@ export function getApplication( initialProps: Object, WrapperComponent?: ?ComponentType<*> ): {| element: Node, getStyleElement: (Object) => Node |} { + const styleResolver = new StyleResolver(); const element = ( - + ); diff --git a/packages/react-native-web/src/exports/AppRegistry/rootContext.js b/packages/react-native-web/src/exports/AppRegistry/rootContext.js new file mode 100644 index 0000000000..d217b7e76b --- /dev/null +++ b/packages/react-native-web/src/exports/AppRegistry/rootContext.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Ondrej Zaruba. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import * as React from 'react'; +import StyleResolver from '../../exports/StyleSheet/StyleResolver'; + +const RootContext: { styleResoler: StyleResolver, rootTag: Node } = React.createContext(null); +export default RootContext; diff --git a/packages/react-native-web/src/exports/Button/__tests__/index-test.js b/packages/react-native-web/src/exports/Button/__tests__/index-test.js index e901ab00ef..7e538d66eb 100644 --- a/packages/react-native-web/src/exports/Button/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/Button/__tests__/index-test.js @@ -2,22 +2,24 @@ import Button from '..'; import React from 'react'; import { act } from 'react-dom/test-utils'; import { createEventTarget } from 'dom-event-testing-library'; -import { render } from '@testing-library/react'; +import renderRootContext from '../../../vendor/renderRootContext'; describe('components/Button', () => { test('prop "accessibilityLabel"', () => { - const { container } = render(