Skip to content

Commit

Permalink
Update ART to concurrent, RN and Noop to error
Browse files Browse the repository at this point in the history
  • Loading branch information
sebmarkbage committed Mar 27, 2024
1 parent e27d5bb commit d13bb69
Show file tree
Hide file tree
Showing 21 changed files with 108 additions and 35 deletions.
17 changes: 12 additions & 5 deletions packages/react-art/src/ReactART.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

import * as React from 'react';
import ReactVersion from 'shared/ReactVersion';
import {LegacyRoot} from 'react-reconciler/src/ReactRootTags';
import {ConcurrentRoot} from 'react-reconciler/src/ReactRootTags';
import {
createContainer,
updateContainer,
injectIntoDevTools,
flushSync,
} from 'react-reconciler/src/ReactFiberReconciler';
import Transform from 'art/core/transform';
import Mode from 'art/modes/current';
Expand Down Expand Up @@ -68,13 +69,15 @@ class Surface extends React.Component {

this._mountNode = createContainer(
this._surface,
LegacyRoot,
ConcurrentRoot,
null,
false,
false,
'',
);
updateContainer(this.props.children, this._mountNode, this);
flushSync(() => {
updateContainer(this.props.children, this._mountNode, this);
});
}

componentDidUpdate(prevProps, prevState) {
Expand All @@ -84,15 +87,19 @@ class Surface extends React.Component {
this._surface.resize(+props.width, +props.height);
}

updateContainer(this.props.children, this._mountNode, this);
flushSync(() => {
updateContainer(this.props.children, this._mountNode, this);
});

if (this._surface.render) {
this._surface.render();
}
}

componentWillUnmount() {
updateContainer(null, this._mountNode, this);
flushSync(() => {
updateContainer(null, this._mountNode, this);
});
}

render() {
Expand Down
5 changes: 5 additions & 0 deletions packages/react-native-renderer/src/ReactFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {getPublicInstanceFromInternalInstanceHandle} from './ReactFiberConfigFab

// Module provided by RN:
import {ReactFiberErrorDialog} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
import {disableLegacyMode} from 'shared/ReactFeatureFlags';

if (typeof ReactFiberErrorDialog.showErrorDialog !== 'function') {
throw new Error(
Expand Down Expand Up @@ -106,6 +107,10 @@ function render(
callback: ?() => void,
concurrentRoot: ?boolean,
): ?ElementRef<ElementType> {
if (disableLegacyMode && !concurrentRoot) {
throw new Error('render: Unsupported Legacy Mode API.');
}

let root = roots.get(containerTag);

if (!root) {
Expand Down
6 changes: 6 additions & 0 deletions packages/react-native-renderer/src/ReactNativeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ import {
isChildPublicInstance,
} from './ReactNativePublicCompat';

import {disableLegacyMode} from 'shared/ReactFeatureFlags';

// Module provided by RN:
import {ReactFiberErrorDialog} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';

Expand Down Expand Up @@ -109,6 +111,10 @@ function render(
containerTag: number,
callback: ?() => void,
): ?ElementRef<ElementType> {
if (disableLegacyMode) {
throw new Error('render: Unsupported Legacy Mode API.');
}

let root = roots.get(containerTag);

if (!root) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ describe('ReactNativeError', () => {
);
});

// @gate !disableLegacyMode
it('should be able to extract a component stack from a native view', () => {
const View = createReactNativeComponentClass('View', () => ({
validAttributes: {foo: true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ beforeEach(() => {
.ReactNativeViewConfigRegistry.register;
});

// @gate !disableLegacyMode
it('fails to register the same event name with different types', async () => {
const InvalidEvents = createReactNativeComponentClass('InvalidEvents', () => {
if (!__DEV__) {
Expand Down Expand Up @@ -122,6 +123,7 @@ it('fails to register the same event name with different types', async () => {
).rejects.toThrow('Event cannot be both direct and bubbling: topChange');
});

// @gate !disableLegacyMode
it('fails if unknown/unsupported event types are dispatched', () => {
expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
Expand All @@ -143,6 +145,7 @@ it('fails if unknown/unsupported event types are dispatched', () => {
}).toThrow('Unsupported top level event type "unspecifiedEvent" dispatched');
});

// @gate !disableLegacyMode
it('handles events', () => {
expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
Expand Down Expand Up @@ -200,6 +203,7 @@ it('handles events', () => {
});

// @gate !disableLegacyContext || !__DEV__
// @gate !disableLegacyMode
it('handles events on text nodes', () => {
expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
Expand Down Expand Up @@ -283,6 +287,7 @@ it('handles events on text nodes', () => {
]);
});

// @gate !disableLegacyMode
it('handles when a responder is unmounted while a touch sequence is in progress', () => {
const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
const View = fakeRequireNativeComponent('View', {id: true});
Expand Down Expand Up @@ -372,6 +377,7 @@ it('handles when a responder is unmounted while a touch sequence is in progress'
expect(log).toEqual(['two responder start']);
});

// @gate !disableLegacyMode
it('handles events without target', () => {
const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];

Expand Down Expand Up @@ -462,6 +468,7 @@ it('handles events without target', () => {
]);
});

// @gate !disableLegacyMode
it('dispatches event with target as instance', () => {
const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ describe('ReactNative', () => {
require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').TextInputState;
});

// @gate !disableLegacyMode
it('should be able to create and render a native component', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand All @@ -58,6 +59,7 @@ describe('ReactNative', () => {
expect(UIManager.updateView).not.toBeCalled();
});

// @gate !disableLegacyMode
it('should be able to create and update a native component', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand All @@ -79,6 +81,7 @@ describe('ReactNative', () => {
expect(UIManager.updateView).toBeCalledWith(3, 'RCTView', {foo: 'bar'});
});

// @gate !disableLegacyMode
it('should not call UIManager.updateView after render for properties that have not changed', () => {
const Text = createReactNativeComponentClass('RCTText', () => ({
validAttributes: {foo: true},
Expand All @@ -105,6 +108,7 @@ describe('ReactNative', () => {
expect(UIManager.updateView).toHaveBeenCalledTimes(4);
});

// @gate !disableLegacyMode
it('should call dispatchCommand for native refs', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -133,6 +137,7 @@ describe('ReactNative', () => {
);
});

// @gate !disableLegacyMode
it('should warn and no-op if calling dispatchCommand on non native refs', () => {
class BasicClass extends React.Component {
render() {
Expand Down Expand Up @@ -162,6 +167,7 @@ describe('ReactNative', () => {
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
});

// @gate !disableLegacyMode
it('should call sendAccessibilityEvent for native refs', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -192,6 +198,7 @@ describe('ReactNative', () => {
).toHaveBeenCalledWith(expect.any(Number), 'focus');
});

// @gate !disableLegacyMode
it('should warn and no-op if calling sendAccessibilityEvent on non native refs', () => {
class BasicClass extends React.Component {
render() {
Expand Down Expand Up @@ -221,6 +228,7 @@ describe('ReactNative', () => {
expect(UIManager.sendAccessibilityEvent).not.toBeCalled();
});

// @gate !disableLegacyMode
it('should not call UIManager.updateView from ref.setNativeProps for properties that have not changed', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -254,6 +262,7 @@ describe('ReactNative', () => {
);
});

// @gate !disableLegacyMode
it('should call UIManager.measure on ref.measure', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand All @@ -280,6 +289,7 @@ describe('ReactNative', () => {
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);
});

// @gate !disableLegacyMode
it('should call UIManager.measureInWindow on ref.measureInWindow', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand All @@ -306,6 +316,7 @@ describe('ReactNative', () => {
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);
});

// @gate !disableLegacyMode
it('should support reactTag in ref.measureLayout', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -346,6 +357,7 @@ describe('ReactNative', () => {
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});

// @gate !disableLegacyMode
it('should support ref in ref.measureLayout of host components', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -382,6 +394,7 @@ describe('ReactNative', () => {
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});

// @gate !disableLegacyMode
it('returns the correct instance and calls it in the callback', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand All @@ -403,6 +416,7 @@ describe('ReactNative', () => {
expect(a).toBe(c);
});

// @gate !disableLegacyMode
it('renders and reorders children', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {title: true},
Expand Down Expand Up @@ -433,6 +447,7 @@ describe('ReactNative', () => {
expect(UIManager.__dumpHierarchyForJestTestsOnly()).toMatchSnapshot();
});

// @gate !disableLegacyMode
it('calls setState with no arguments', () => {
let mockArgs;
class Component extends React.Component {
Expand All @@ -448,6 +463,7 @@ describe('ReactNative', () => {
expect(mockArgs.length).toEqual(0);
});

// @gate !disableLegacyMode
it('should not throw when <View> is used inside of a <Text> ancestor', () => {
const Image = createReactNativeComponentClass('RCTImage', () => ({
validAttributes: {},
Expand Down Expand Up @@ -478,6 +494,7 @@ describe('ReactNative', () => {
);
});

// @gate !disableLegacyMode
it('should throw for text not inside of a <Text> ancestor', async () => {
const ScrollView = createReactNativeComponentClass('RCTScrollView', () => ({
validAttributes: {},
Expand Down Expand Up @@ -512,6 +529,7 @@ describe('ReactNative', () => {
);
});

// @gate !disableLegacyMode
it('should not throw for text inside of an indirect <Text> ancestor', () => {
const Text = createReactNativeComponentClass('RCTText', () => ({
validAttributes: {},
Expand All @@ -528,6 +546,7 @@ describe('ReactNative', () => {
);
});

// @gate !disableLegacyMode
it('findHostInstance_DEPRECATED should warn if used to find a host component inside StrictMode', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -564,6 +583,7 @@ describe('ReactNative', () => {
expect(match).toBe(child);
});

// @gate !disableLegacyMode
it('findHostInstance_DEPRECATED should warn if passed a component that is inside StrictMode', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -601,6 +621,7 @@ describe('ReactNative', () => {
expect(match).toBe(child);
});

// @gate !disableLegacyMode
it('findNodeHandle should warn if used to find a host component inside StrictMode', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -635,6 +656,7 @@ describe('ReactNative', () => {
expect(match).toBe(child._nativeTag);
});

// @gate !disableLegacyMode
it('findNodeHandle should warn if passed a component that is inside StrictMode', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down Expand Up @@ -670,6 +692,7 @@ describe('ReactNative', () => {
expect(match).toBe(child._nativeTag);
});

// @gate !disableLegacyMode
it('blur on host component calls TextInputState', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand All @@ -687,6 +710,7 @@ describe('ReactNative', () => {
expect(TextInputState.blurTextInput).toHaveBeenCalledWith(viewRef.current);
});

// @gate !disableLegacyMode
it('focus on host component calls TextInputState', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('createReactNativeComponentClass', () => {
ReactNative = require('react-native-renderer');
});

// @gate !disableLegacyMode
it('should register viewConfigs', () => {
const textViewConfig = {
validAttributes: {},
Expand Down
9 changes: 8 additions & 1 deletion packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
ConcurrentRoot,
LegacyRoot,
} from 'react-reconciler/constants';
import {enableRefAsProp} from 'shared/ReactFeatureFlags';
import {enableRefAsProp, disableLegacyMode} from 'shared/ReactFeatureFlags';

type Container = {
rootID: string,
Expand Down Expand Up @@ -1020,6 +1020,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
},

createLegacyRoot() {
if (disableLegacyMode) {
throw new Error('createLegacyRoot: Unsupported Legacy Mode API.');
}

const container = {
rootID: '' + idCounter++,
pendingChildren: [],
Expand Down Expand Up @@ -1119,6 +1123,9 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
},

renderLegacySyncRoot(element: React$Element<any>, callback: ?Function) {
if (disableLegacyMode) {
throw new Error('createLegacyRoot: Unsupported Legacy Mode API.');
}
const rootID = DEFAULT_ROOT_ID;
const container = ReactNoop.getOrCreateRootContainer(rootID, LegacyRoot);
const root = roots.get(container.rootID);
Expand Down
2 changes: 1 addition & 1 deletion packages/react-reconciler/src/__tests__/Activity-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ describe('Activity', () => {
);
});

// @gate www
// @gate www && !disableLegacyMode
it('does not defer in legacy mode', async () => {
let setState;
function Foo() {
Expand Down
Loading

0 comments on commit d13bb69

Please sign in to comment.