[RN] Move view config registry to shims (#12569)
* Move view config registry to shims This ensures that both Fabric and RN renderers share the same view config registry since it is stateful. I had to duplicate in the mocks for testing. * Move createReactNativeComponentClass to shims and delete internal usage Since createReactNativeComponentClass is just an alias for the register there's no need to bundle it. This file should probably just move back to RN too.
Sebastian Markbåge committed
Apr 9, 2018 at 20:05 UTC
b99d0b14160150c566e091bd10b634beec9a58c3
19 files changed
+166
-91
packages/react-native-renderer/src/ReactFabric.js
-2
@@ -21,7 +21,6 @@ import ReactNativeComponent from './ReactNativeComponent';
21
import * as ReactNativeComponentTree from './ReactNativeComponentTree';
22
import ReactFabricRenderer from './ReactFabricRenderer';
23
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';
24
-import createReactNativeComponentClass from './createReactNativeComponentClass';
24
import {injectFindHostInstance} from './findNodeHandle';
25
import findNumericNodeHandle from './findNumericNodeHandle';
26
@@ -73,7 +72,6 @@ const ReactFabric: ReactFabricType = {
72
NativeMethodsMixin,
73
// Used by react-native-github/Libraries/ components
74
ReactNativeComponentTree, // ScrollResponder
76
- createReactNativeComponentClass, // RCTText, RCTView, ReactNativeART
75
},
76
};
77
packages/react-native-renderer/src/ReactFabricRenderer.js
+1
-1
@@ -18,7 +18,7 @@ import type {
18
import {mountSafeCallback, warnForStyleProps} from './NativeMethodsMixinUtils';
19
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
20
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
21
-import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
21
+import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
22
import ReactFiberReconciler from 'react-reconciler';
23
24
import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev';
packages/react-native-renderer/src/ReactNativeBridgeEventPlugin.js
+1
-1
@@ -12,7 +12,7 @@ import {
12
accumulateTwoPhaseDispatches,
13
accumulateDirectDispatches,
14
} from 'events/EventPropagators';
15
-import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
15
+import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
16
import SyntheticEvent from 'events/SyntheticEvent';
17
import invariant from 'fbjs/lib/invariant';
18
packages/react-native-renderer/src/ReactNativeFiberRenderer.js
+1
-1
@@ -16,7 +16,7 @@ import invariant from 'fbjs/lib/invariant';
16
import UIManager from 'UIManager';
17
import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev';
18
19
-import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
19
+import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
20
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
21
import {
22
precacheFiberNode,
packages/react-native-renderer/src/ReactNativeRenderer.js
-2
@@ -25,7 +25,6 @@ import ReactNativeComponent from './ReactNativeComponent';
25
import * as ReactNativeComponentTree from './ReactNativeComponentTree';
26
import ReactNativeFiberRenderer from './ReactNativeFiberRenderer';
27
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';
28
-import createReactNativeComponentClass from './createReactNativeComponentClass';
28
import {injectFindHostInstance} from './findNodeHandle';
29
import findNumericNodeHandle from './findNumericNodeHandle';
30
@@ -98,7 +97,6 @@ const ReactNativeRenderer: ReactNativeType = {
97
NativeMethodsMixin,
98
// Used by react-native-github/Libraries/ components
99
ReactNativeComponentTree, // ScrollResponder
101
- createReactNativeComponentClass, // RCTText, RCTView, ReactNativeART
100
computeComponentStackForErrorReporting,
101
},
102
};
packages/react-native-renderer/src/ReactNativeTypes.js
-4
@@ -71,10 +71,6 @@ export type NativeMethodsMixinType = {
71
72
type SecretInternalsType = {
73
NativeMethodsMixin: NativeMethodsMixinType,
74
- createReactNativeComponentClass(
75
- name: string,
76
- callback: ViewConfigGetter,
77
- ): any,
74
ReactNativeComponentTree: any,
75
// TODO (bvaughn) Decide which additional types to expose here?
76
// And how much information to fill in for the above types.
packages/react-native-renderer/src/__mocks__/ReactNativeViewConfigRegistry.js
renamed
+13
-8
@@ -6,18 +6,23 @@
6
*
7
* @flow
8
*/
9
+'use strict';
10
11
import type {
12
ReactNativeBaseComponentViewConfig,
13
ViewConfigGetter,
14
} from './ReactNativeTypes';
15
15
-import invariant from 'fbjs/lib/invariant';
16
+const invariant = require('fbjs/lib/invariant');
17
18
// Event configs
18
-export const customBubblingEventTypes = {};
19
-export const customDirectEventTypes = {};
20
-export const eventTypes = {};
19
+const customBubblingEventTypes = {};
20
+const customDirectEventTypes = {};
21
+const eventTypes = {};
22
+
23
+exports.customBubblingEventTypes = customBubblingEventTypes;
24
+exports.customDirectEventTypes = customDirectEventTypes;
25
+exports.eventTypes = eventTypes;
26
27
const viewConfigCallbacks = new Map();
28
const viewConfigs = new Map();
@@ -64,7 +69,7 @@ function processEventTypes(
69
* The callback is deferred until the view is actually rendered.
70
* This is done to avoid causing Prepack deopts.
71
*/
67
-export function register(name: string, callback: ViewConfigGetter): string {
72
+exports.register = function(name: string, callback: ViewConfigGetter): string {
73
invariant(
74
!viewConfigCallbacks.has(name),
75
'Tried to register two views with the same name %s',
@@ -72,14 +77,14 @@ export function register(name: string, callback: ViewConfigGetter): string {
77
);
78
viewConfigCallbacks.set(name, callback);
79
return name;
75
-}
80
+};
81
82
/**
83
* Retrieves a config for the specified view.
84
* If this is the first time the view has been used,
85
* This configuration will be lazy-loaded from UIManager.
86
*/
82
-export function get(name: string): ReactNativeBaseComponentViewConfig {
87
+exports.get = function(name: string): ReactNativeBaseComponentViewConfig {
88
let viewConfig;
89
if (!viewConfigs.has(name)) {
90
const callback = viewConfigCallbacks.get(name);
@@ -97,4 +102,4 @@ export function get(name: string): ReactNativeBaseComponentViewConfig {
102
}
103
invariant(viewConfig, 'View config not found for name %s', name);
104
return viewConfig;
100
-}
105
+};
packages/react-native-renderer/src/__mocks__/View.js
deleted
-18
@@ -1,18 +0,0 @@
1
-/**
2
- * Copyright (c) 2013-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
-'use strict';
9
-
10
-const createReactNativeComponentClass = require('../createReactNativeComponentClass')
11
- .default;
12
-
13
-const View = createReactNativeComponentClass({
14
- validAttributes: {},
15
- uiViewClassName: 'View',
16
-});
17
-
18
-module.exports = View;
packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
+2
-2
@@ -28,8 +28,8 @@ describe('ReactFabric', () => {
28
ReactFabric = require('react-native-renderer/fabric');
29
FabricUIManager = require('FabricUIManager');
30
UIManager = require('UIManager');
31
- createReactNativeComponentClass = require('../createReactNativeComponentClass')
32
- .default;
31
+ createReactNativeComponentClass = require('ReactNativeViewConfigRegistry')
32
+ .register;
33
});
34
35
it('should be able to create and render a native component', () => {
packages/react-native-renderer/src/__tests__/ReactFabricAndNative-test.internal.js
+2
-2
@@ -26,8 +26,8 @@ describe('ReactFabric', () => {
26
27
React = require('react');
28
ReactFabric = require('react-native-renderer/fabric');
29
- createReactNativeComponentClass = require('../createReactNativeComponentClass')
30
- .default;
29
+ createReactNativeComponentClass = require('ReactNativeViewConfigRegistry')
30
+ .register;
31
});
32
33
it('find Fabric nodes with the RN renderer', () => {
packages/react-native-renderer/src/__tests__/ReactNativeError-test.internal.js
+2
-2
@@ -25,8 +25,8 @@ describe('ReactNativeError', () => {
25
26
React = require('react');
27
ReactNative = require('react-native-renderer');
28
- createReactNativeComponentClass = require('../createReactNativeComponentClass')
29
- .default;
28
+ createReactNativeComponentClass = require('ReactNativeViewConfigRegistry')
29
+ .register;
30
computeComponentStackForErrorReporting =
31
ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
32
.computeComponentStackForErrorReporting;
packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js
+2
-2
@@ -69,8 +69,8 @@ beforeEach(() => {
69
ReactNative = require('react-native-renderer');
70
ResponderEventPlugin = require('events/ResponderEventPlugin').default;
71
UIManager = require('UIManager');
72
- createReactNativeComponentClass = require('../createReactNativeComponentClass')
73
- .default;
72
+ createReactNativeComponentClass = require('ReactNativeViewConfigRegistry')
73
+ .register;
74
});
75
76
it('fails if unknown/unsupported event types are dispatched', () => {
packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js
+2
-2
@@ -22,8 +22,8 @@ describe('ReactNative', () => {
22
React = require('react');
23
ReactNative = require('react-native-renderer');
24
UIManager = require('UIManager');
25
- createReactNativeComponentClass = require('../createReactNativeComponentClass')
26
- .default;
25
+ createReactNativeComponentClass = require('ReactNativeViewConfigRegistry')
26
+ .register;
27
});
28
29
it('should be able to create and render a native component', () => {
packages/react-native-renderer/src/__tests__/createReactNativeComponentClass-test.internal.js
+2
-2
@@ -18,8 +18,8 @@ describe('createReactNativeComponentClass', () => {
18
beforeEach(() => {
19
jest.resetModules();
20
21
- createReactNativeComponentClass = require('../createReactNativeComponentClass')
22
- .default;
21
+ createReactNativeComponentClass = require('ReactNativeViewConfigRegistry')
22
+ .register;
23
React = require('react');
24
ReactNative = require('react-native-renderer');
25
});
packages/react-native-renderer/src/createReactNativeComponentClass.js
deleted
-29
@@ -1,29 +0,0 @@
1
-/**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import type {ViewConfigGetter} from './ReactNativeTypes';
11
-
12
-import {register} from './ReactNativeViewConfigRegistry';
13
-
14
-/**
15
- * Creates a renderable ReactNative host component.
16
- * Use this method for view configs that are loaded from UIManager.
17
- * Use createReactNativeComponentClass() for view configs defined within JavaScript.
18
- *
19
- * @param {string} config iOS View configuration.
20
- * @private
21
- */
22
-const createReactNativeComponentClass = function(
23
- name: string,
24
- callback: ViewConfigGetter,
25
-): string {
26
- return register(name, callback);
27
-};
28
-
29
-export default createReactNativeComponentClass;
scripts/flow/react-native-host-hooks.js
+11
-6
@@ -9,6 +9,11 @@
9
10
/* eslint-disable */
11
12
+import type {
13
+ ReactNativeBaseComponentViewConfig,
14
+ ViewConfigGetter,
15
+} from 'react-native-renderer/src/ReactNativeTypes';
16
+
17
declare module 'deepDiffer' {
18
declare module.exports: (one: any, two: any) => boolean;
19
}
@@ -142,11 +147,11 @@ declare module 'BatchedBridge' {
147
declare function registerCallableModule(name: string, module: Object): void;
148
}
149
145
-declare module 'CSComponent' {
146
- declare type Element = any;
147
- declare type Options<Instance> = any;
148
-}
150
+declare module 'ReactNativeViewConfigRegistry' {
151
+ declare var customBubblingEventTypes: Object;
152
+ declare var customDirectEventTypes: Object;
153
+ declare var eventTypes: Object;
154
150
-declare module 'CSStatefulComponent' {
151
- declare function CSStatefulComponent(spec: any): any;
155
+ declare function register(name: string, callback: ViewConfigGetter): string;
156
+ declare function get(name: string): ReactNativeBaseComponentViewConfig;
157
}
scripts/rollup/bundles.js
+2
-2
@@ -124,10 +124,10 @@ const bundles = [
124
'RCTEventEmitter',
125
'TextInputState',
126
'UIManager',
127
- 'View',
127
'deepDiffer',
128
'deepFreezeAndThrowOnMutationInDev',
129
'flattenStyle',
130
+ 'ReactNativeViewConfigRegistry',
131
],
132
},
133
@@ -146,10 +146,10 @@ const bundles = [
146
'TextInputState',
147
'UIManager',
148
'FabricUIManager',
149
- 'View',
149
'deepDiffer',
150
'deepFreezeAndThrowOnMutationInDev',
151
'flattenStyle',
152
+ 'ReactNativeViewConfigRegistry',
153
],
154
},
155
scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js
new
+106
@@ -0,0 +1,106 @@
1
+/**
2
+ * Copyright (c) 2015-present, Facebook, Inc.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @providesModule ReactNativeViewConfigRegistry
8
+ * @flow
9
+ */
10
+'use strict';
11
+
12
+import type {
13
+ ReactNativeBaseComponentViewConfig,
14
+ ViewConfigGetter,
15
+} from './ReactNativeTypes';
16
+
17
+const invariant = require('fbjs/lib/invariant');
18
+
19
+// Event configs
20
+const customBubblingEventTypes = {};
21
+const customDirectEventTypes = {};
22
+const eventTypes = {};
23
+
24
+exports.customBubblingEventTypes = customBubblingEventTypes;
25
+exports.customDirectEventTypes = customDirectEventTypes;
26
+exports.eventTypes = eventTypes;
27
+
28
+const viewConfigCallbacks = new Map();
29
+const viewConfigs = new Map();
30
+
31
+function processEventTypes(
32
+ viewConfig: ReactNativeBaseComponentViewConfig,
33
+): void {
34
+ const {bubblingEventTypes, directEventTypes} = viewConfig;
35
+
36
+ if (__DEV__) {
37
+ if (bubblingEventTypes != null && directEventTypes != null) {
38
+ for (const topLevelType in directEventTypes) {
39
+ invariant(
40
+ bubblingEventTypes[topLevelType] == null,
41
+ 'Event cannot be both direct and bubbling: %s',
42
+ topLevelType,
43
+ );
44
+ }
45
+ }
46
+ }
47
+
48
+ if (bubblingEventTypes != null) {
49
+ for (const topLevelType in bubblingEventTypes) {
50
+ if (customBubblingEventTypes[topLevelType] == null) {
51
+ eventTypes[topLevelType] = customBubblingEventTypes[topLevelType] =
52
+ bubblingEventTypes[topLevelType];
53
+ }
54
+ }
55
+ }
56
+
57
+ if (directEventTypes != null) {
58
+ for (const topLevelType in directEventTypes) {
59
+ if (customDirectEventTypes[topLevelType] == null) {
60
+ eventTypes[topLevelType] = customDirectEventTypes[topLevelType] =
61
+ directEventTypes[topLevelType];
62
+ }
63
+ }
64
+ }
65
+}
66
+
67
+/**
68
+ * Registers a native view/component by name.
69
+ * A callback is provided to load the view config from UIManager.
70
+ * The callback is deferred until the view is actually rendered.
71
+ * This is done to avoid causing Prepack deopts.
72
+ */
73
+exports.register = function(name: string, callback: ViewConfigGetter): string {
74
+ invariant(
75
+ !viewConfigCallbacks.has(name),
76
+ 'Tried to register two views with the same name %s',
77
+ name,
78
+ );
79
+ viewConfigCallbacks.set(name, callback);
80
+ return name;
81
+};
82
+
83
+/**
84
+ * Retrieves a config for the specified view.
85
+ * If this is the first time the view has been used,
86
+ * This configuration will be lazy-loaded from UIManager.
87
+ */
88
+exports.get = function(name: string): ReactNativeBaseComponentViewConfig {
89
+ let viewConfig;
90
+ if (!viewConfigs.has(name)) {
91
+ const callback = viewConfigCallbacks.get(name);
92
+ invariant(
93
+ typeof callback === 'function',
94
+ 'View config not found for name %s',
95
+ name,
96
+ );
97
+ viewConfigCallbacks.set(name, null);
98
+ viewConfig = callback();
99
+ processEventTypes(viewConfig);
100
+ viewConfigs.set(name, viewConfig);
101
+ } else {
102
+ viewConfig = viewConfigs.get(name);
103
+ }
104
+ invariant(viewConfig, 'View config not found for name %s', name);
105
+ return viewConfig;
106
+};
scripts/rollup/shims/react-native/createReactNativeComponentClass.js
+19
-5
@@ -10,9 +10,23 @@
10
11
'use strict';
12
13
-const {
14
- __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
15
-} = require('ReactNative');
13
+import type {ViewConfigGetter} from './ReactNativeTypes';
14
17
-module.exports =
18
- __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.createReactNativeComponentClass;
15
+const {register} = require('ReactNativeViewConfigRegistry');
16
+
17
+/**
18
+ * Creates a renderable ReactNative host component.
19
+ * Use this method for view configs that are loaded from UIManager.
20
+ * Use createReactNativeComponentClass() for view configs defined within JavaScript.
21
+ *
22
+ * @param {string} config iOS View configuration.
23
+ * @private
24
+ */
25
+const createReactNativeComponentClass = function(
26
+ name: string,
27
+ callback: ViewConfigGetter,
28
+): string {
29
+ return register(name, callback);
30
+};
31
+
32
+export default createReactNativeComponentClass;