Require the isomorphic React instead of internals from renderers (#7473)
This is needed for flat builds. It also lets us get rid of a bunch of special cases in the build scripts. It also allow us to just copy the source files into React Native instead of having to build first to resolve the special cases.
Sebastian Markbåge committed
Aug 11, 2016 at 18:56 UTC
1c5a639c37039a9c60752980dfee168129b76b32
23 files changed
+79
-89
flow/react-native-host-hooks.js
+3
-1
@@ -40,4 +40,6 @@ declare module 'UIManager' {
40
declare function setChildren() : void;
41
declare function updateView() : void;
42
}
43
-declare module 'View' { }
43
+declare module 'View' {
44
+ declare var exports : typeof ReactComponent;
45
+}
grunt/config/browserify.js
+1
-6
@@ -19,13 +19,8 @@ var SECRET_INTERNALS_NAME = 'React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_
19
var shimSharedModulesFiles = {
20
'./ReactCurrentOwner': SECRET_INTERNALS_NAME + '.ReactCurrentOwner',
21
'./ReactComponentTreeHook': SECRET_INTERNALS_NAME + '.ReactComponentTreeHook',
22
- // The methods we used here are exposed on the main React export.
23
- // TODO: Change all renderer code to require the isomorphic React directly
24
- // instead of these internals.
22
+ // Use the global, anywhere we require React
23
'./React': 'React',
26
- './ReactElement': 'React',
27
- './ReactPropTypes': 'React.PropTypes',
28
- './ReactChildren': 'React.Children',
24
};
25
26
// We can access these as absolute or relative. We need to shim both.
gulpfile.js
+2
-11
@@ -111,20 +111,11 @@ var moduleMapReact = Object.assign(
111
);
112
113
var rendererSharedState = {
114
+ // Alias
115
+ React: 'react/lib/React',
116
// Shared state
117
ReactCurrentOwner: 'react/lib/ReactCurrentOwner',
118
ReactComponentTreeHook: 'react/lib/ReactComponentTreeHook',
117
-
118
- // TODO: Move to shared since these are actually shared and can be copied.
119
- ReactPropTypeLocations: 'react/lib/ReactPropTypeLocations',
120
- ReactPropTypesSecret: 'react/lib/ReactPropTypesSecret',
121
- checkReactTypeSpec: 'react/lib/checkReactTypeSpec',
122
-
123
- // TODO: Update the source to just use the React module.
124
- React: 'react/lib/React',
125
- ReactElement: 'react/lib/ReactElement',
126
- ReactPropTypes: 'react/lib/ReactPropTypes',
127
- ReactChildren: 'react/lib/ReactChildren',
119
};
120
121
var moduleMapReactDOM = Object.assign(
src/isomorphic/classic/element/ReactElement.js
+1
-7
@@ -17,11 +17,7 @@ var warning = require('warning');
17
var canDefineProperty = require('canDefineProperty');
18
var hasOwnProperty = Object.prototype.hasOwnProperty;
19
20
-// The Symbol used to tag the ReactElement type. If there is no native Symbol
21
-// nor polyfill, then a plain number is used for performance.
22
-var REACT_ELEMENT_TYPE =
23
- (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
24
- 0xeac7;
20
+var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
21
22
var RESERVED_PROPS = {
23
key: true,
@@ -406,6 +402,4 @@ ReactElement.isValidElement = function(object) {
402
);
403
};
404
409
-ReactElement.REACT_ELEMENT_TYPE = REACT_ELEMENT_TYPE;
410
-
405
module.exports = ReactElement;
src/renderers/dom/client/ReactMount.js
+3
-3
@@ -13,12 +13,12 @@
13
14
var DOMLazyTree = require('DOMLazyTree');
15
var DOMProperty = require('DOMProperty');
16
+var React = require('React');
17
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
18
var ReactCurrentOwner = require('ReactCurrentOwner');
19
var ReactDOMComponentTree = require('ReactDOMComponentTree');
20
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
21
var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
21
-var ReactElement = require('ReactElement');
22
var ReactFeatureFlags = require('ReactFeatureFlags');
23
var ReactInstanceMap = require('ReactInstanceMap');
24
var ReactInstrumentation = require('ReactInstrumentation');
@@ -388,7 +388,7 @@ var ReactMount = {
388
_renderSubtreeIntoContainer: function(parentComponent, nextElement, container, callback) {
389
ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');
390
invariant(
391
- ReactElement.isValidElement(nextElement),
391
+ React.isValidElement(nextElement),
392
'ReactDOM.render(): Invalid component element.%s',
393
(
394
typeof nextElement === 'string' ?
@@ -415,7 +415,7 @@ var ReactMount = {
415
'for your app.'
416
);
417
418
- var nextWrappedElement = ReactElement.createElement(
418
+ var nextWrappedElement = React.createElement(
419
TopLevelWrapper,
420
{ child: nextElement }
421
);
src/renderers/dom/client/wrappers/LinkedValueUtils.js
+2
-2
@@ -11,7 +11,7 @@
11
12
'use strict';
13
14
-var ReactPropTypes = require('ReactPropTypes');
14
+var React = require('React');
15
var ReactPropTypeLocations = require('ReactPropTypeLocations');
16
var ReactPropTypesSecret = require('ReactPropTypesSecret');
17
@@ -84,7 +84,7 @@ var propTypes = {
84
'set either `onChange` or `readOnly`.'
85
);
86
},
87
- onChange: ReactPropTypes.func,
87
+ onChange: React.PropTypes.func,
88
};
89
90
var loggedTypeFailures = {};
src/renderers/dom/client/wrappers/ReactDOMOption.js
+2
-2
@@ -11,7 +11,7 @@
11
12
'use strict';
13
14
-var ReactChildren = require('ReactChildren');
14
+var React = require('React');
15
var ReactDOMComponentTree = require('ReactDOMComponentTree');
16
var ReactDOMSelect = require('ReactDOMSelect');
17
@@ -23,7 +23,7 @@ function flattenChildren(children) {
23
24
// Flatten children and warn if they aren't strings or numbers;
25
// invalid types are ignored.
26
- ReactChildren.forEach(children, function(child) {
26
+ React.Children.forEach(children, function(child) {
27
if (child == null) {
28
return;
29
}
src/renderers/dom/server/ReactServerRendering.js
+3
-3
@@ -10,9 +10,9 @@
10
*/
11
'use strict';
12
13
+var React = require('React');
14
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
15
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
15
-var ReactElement = require('ReactElement');
16
var ReactInstrumentation = require('ReactInstrumentation');
17
var ReactMarkupChecksum = require('ReactMarkupChecksum');
18
var ReactReconciler = require('ReactReconciler');
@@ -80,7 +80,7 @@ function renderToStringImpl(element, makeStaticMarkup) {
80
*/
81
function renderToString(element) {
82
invariant(
83
- ReactElement.isValidElement(element),
83
+ React.isValidElement(element),
84
'renderToString(): You must pass a valid ReactElement.'
85
);
86
return renderToStringImpl(element, false);
@@ -93,7 +93,7 @@ function renderToString(element) {
93
*/
94
function renderToStaticMarkup(element) {
95
invariant(
96
- ReactElement.isValidElement(element),
96
+ React.isValidElement(element),
97
'renderToStaticMarkup(): You must pass a valid ReactElement.'
98
);
99
return renderToStringImpl(element, true);
src/renderers/native/ReactNative.js
+1
-2
@@ -16,7 +16,6 @@
16
var ReactNativeComponentTree = require('ReactNativeComponentTree');
17
var ReactNativeDefaultInjection = require('ReactNativeDefaultInjection');
18
19
-var ReactElement = require('ReactElement');
19
var ReactNativeMount = require('ReactNativeMount');
20
var ReactUpdates = require('ReactUpdates');
21
@@ -25,7 +24,7 @@ var findNodeHandle = require('findNodeHandle');
24
ReactNativeDefaultInjection.inject();
25
26
var render = function(
28
- element: ReactElement,
27
+ element: ReactElement<any>,
28
mountInto: number,
29
callback?: ?(() => void)
30
): ?ReactComponent<any, any, any> {
src/renderers/native/ReactNativeDefaultInjection.js
+2
-2
@@ -22,9 +22,9 @@ require('InitializeJavaScriptAppEngine');
22
var EventPluginHub = require('EventPluginHub');
23
var EventPluginUtils = require('EventPluginUtils');
24
var RCTEventEmitter = require('RCTEventEmitter');
25
+var React = require('React');
26
var ReactComponentEnvironment = require('ReactComponentEnvironment');
27
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
27
-var ReactElement = require('ReactElement');
28
var ReactEmptyComponent = require('ReactEmptyComponent');
29
var ReactNativeBridgeEventPlugin = require('ReactNativeBridgeEventPlugin');
30
var ReactHostComponent = require('ReactHostComponent');
@@ -83,7 +83,7 @@ function inject() {
83
// Can't import View at the top because it depends on React to make its composite
84
var View = require('View');
85
return new ReactSimpleEmptyComponent(
86
- ReactElement.createElement(View, {
86
+ React.createElement(View, {
87
collapsable: true,
88
style: { position: 'absolute' },
89
}),
src/renderers/native/ReactNativeMount.js
+7
-12
@@ -11,7 +11,7 @@
11
*/
12
'use strict';
13
14
-var ReactElement = require('ReactElement');
14
+var React = require('React');
15
var ReactInstrumentation = require('ReactInstrumentation');
16
var ReactNativeContainerInfo = require('ReactNativeContainerInfo');
17
var ReactNativeTagHandles = require('ReactNativeTagHandles');
@@ -35,9 +35,9 @@ if (__DEV__) {
35
TopLevelWrapper.displayName = 'TopLevelWrapper';
36
}
37
TopLevelWrapper.prototype.render = function() {
38
- // this.props is actually a ReactElement
39
- return this.props;
38
+ return this.props.child;
39
};
40
+TopLevelWrapper.isReactTopLevelWrapper = true;
41
42
/**
43
* Mounts this component and inserts it into the DOM.
@@ -99,25 +99,20 @@ var ReactNativeMount = {
99
* @param {containerTag} containerView Handle to native view tag
100
*/
101
renderComponent: function(
102
- nextElement: ReactElement,
102
+ nextElement: ReactElement<*>,
103
containerTag: number,
104
callback?: ?(() => void)
105
): ?ReactComponent<any, any, any> {
106
- var nextWrappedElement = new ReactElement(
106
+ var nextWrappedElement = React.createElement(
107
TopLevelWrapper,
108
- null,
109
- null,
110
- null,
111
- null,
112
- null,
113
- nextElement
108
+ { child: nextElement }
109
);
110
111
var topRootNodeID = containerTag;
112
var prevComponent = ReactNativeMount._instancesByContainerID[topRootNodeID];
113
if (prevComponent) {
114
var prevWrappedElement = prevComponent._currentElement;
120
- var prevElement = prevWrappedElement.props;
115
+ var prevElement = prevWrappedElement.props.child;
116
if (shouldUpdateReactComponent(prevElement, nextElement)) {
117
ReactUpdateQueue.enqueueElementInternal(prevComponent, nextWrappedElement, emptyObject);
118
if (callback) {
src/renderers/shared/fiber/ReactChildFiber.js
+1
-3
@@ -18,9 +18,7 @@ import type { PriorityLevel } from 'ReactPriorityLevel';
18
19
import type { ReactNodeList } from 'ReactTypes';
20
21
-var {
22
- REACT_ELEMENT_TYPE,
23
-} = require('ReactElement');
21
+var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
22
var {
23
REACT_COROUTINE_TYPE,
24
REACT_YIELD_TYPE,
src/renderers/shared/fiber/ReactFiber.js
+2
-3
@@ -26,8 +26,6 @@ var {
26
YieldComponent,
27
} = ReactTypeOfWork;
28
29
-var ReactElement = require('ReactElement');
30
-
29
var {
30
NoWork,
31
} = require('ReactPriorityLevel');
@@ -201,7 +199,8 @@ exports.createHostContainerFiber = function() {
199
return fiber;
200
};
201
204
-exports.createFiberFromElement = function(element : ReactElement, priorityLevel : PriorityLevel) {
202
+exports.createFiberFromElement = function(element : ReactElement<*>, priorityLevel : PriorityLevel) {
203
+// $FlowFixMe: ReactElement.key is currently defined as ?string but should be defined as null | string in Flow.
204
const fiber = createFiberFromElementType(element.type, element.key);
205
fiber.pendingProps = element.props;
206
fiber.pendingWorkPriority = priorityLevel;
src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
+4
-4
@@ -11,9 +11,9 @@
11
12
'use strict';
13
14
+var React = require('React');
15
var ReactComponentEnvironment = require('ReactComponentEnvironment');
16
var ReactCurrentOwner = require('ReactCurrentOwner');
16
-var ReactElement = require('ReactElement');
17
var ReactErrorUtils = require('ReactErrorUtils');
18
var ReactInstanceMap = require('ReactInstanceMap');
19
var ReactInstrumentation = require('ReactInstrumentation');
@@ -49,7 +49,7 @@ StatelessComponent.prototype.render = function() {
49
function warnIfInvalidElement(Component, element) {
50
if (__DEV__) {
51
warning(
52
- element === null || element === false || ReactElement.isValidElement(element),
52
+ element === null || element === false || React.isValidElement(element),
53
'%s(...): A valid React element (or null) must be returned. You may have ' +
54
'returned undefined, an array or some other invalid object.',
55
Component.displayName || Component.name || 'Component'
@@ -229,7 +229,7 @@ var ReactCompositeComponentMixin = {
229
invariant(
230
inst === null ||
231
inst === false ||
232
- ReactElement.isValidElement(inst),
232
+ React.isValidElement(inst),
233
'%s(...): A valid React element (or null) must be returned. You may have ' +
234
'returned undefined, an array or some other invalid object.',
235
Component.displayName || Component.name || 'Component'
@@ -1145,7 +1145,7 @@ var ReactCompositeComponentMixin = {
1145
invariant(
1146
// TODO: An `isValidNode` function would probably be more appropriate
1147
renderedComponent === null || renderedComponent === false ||
1148
- ReactElement.isValidElement(renderedComponent),
1148
+ React.isValidElement(renderedComponent),
1149
'%s.render(): A valid React element (or null) must be returned. You may have ' +
1150
'returned undefined, an array or some other invalid object.',
1151
this.getName() || 'ReactCompositeComponent'
src/renderers/shared/stack/reconciler/ReactNodeTypes.js
+2
-2
@@ -14,7 +14,7 @@
14
15
type ReactNodeType = 0 | 1 | 2;
16
17
-var ReactElement = require('ReactElement');
17
+var React = require('React');
18
19
var invariant = require('invariant');
20
@@ -26,7 +26,7 @@ var ReactNodeTypes = {
26
getType: function(node: ReactElement<any>): ReactNodeType {
27
if (node === null || node === false) {
28
return ReactNodeTypes.EMPTY;
29
- } else if (ReactElement.isValidElement(node)) {
29
+ } else if (React.isValidElement(node)) {
30
if (typeof node.type === 'function') {
31
return ReactNodeTypes.COMPOSITE;
32
} else {
src/renderers/testing/ReactTestMount.js
+7
-17
@@ -11,7 +11,7 @@
11
*/
12
'use strict';
13
14
-var ReactElement = require('ReactElement');
14
+var React = require('React');
15
var ReactReconciler = require('ReactReconciler');
16
var ReactUpdates = require('ReactUpdates');
17
@@ -31,9 +31,9 @@ if (__DEV__) {
31
TopLevelWrapper.displayName = 'TopLevelWrapper';
32
}
33
TopLevelWrapper.prototype.render = function() {
34
- // this.props is actually a ReactElement
35
- return this.props;
34
+ return this.props.child;
35
};
36
+TopLevelWrapper.isReactTopLevelWrapper = true;
37
38
/**
39
* Mounts this component and inserts it into the DOM.
@@ -88,14 +88,9 @@ ReactTestInstance.prototype.update = function(nextElement) {
88
this._component,
89
"ReactTestRenderer: .update() can't be called after unmount."
90
);
91
- var nextWrappedElement = new ReactElement(
91
+ var nextWrappedElement = React.createElement(
92
TopLevelWrapper,
93
- null,
94
- null,
95
- null,
96
- null,
97
- null,
98
- nextElement
93
+ { child: nextElement }
94
);
95
var component = this._component;
96
ReactUpdates.batchedUpdates(function() {
@@ -139,14 +134,9 @@ var ReactTestMount = {
134
render: function(
135
nextElement: ReactElement
136
): ?ReactElement<any, any, any> {
142
- var nextWrappedElement = new ReactElement(
137
+ var nextWrappedElement = React.createElement(
138
TopLevelWrapper,
144
- null,
145
- null,
146
- null,
147
- null,
148
- null,
149
- nextElement
139
+ { child: nextElement }
140
);
141
142
var instance = instantiateReactComponent(nextWrappedElement, false);
src/shared/types/ReactPropTypeLocationNames.js
renamed
src/shared/types/ReactPropTypeLocations.js
renamed
src/shared/types/ReactPropTypesSecret.js
renamed
src/shared/types/checkReactTypeSpec.js
renamed
src/shared/utils/ReactElementSymbol.js
new
+20
@@ -0,0 +1,20 @@
1
+/**
2
+ * Copyright 2014-present, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactElementSymbol
10
+ */
11
+
12
+'use strict';
13
+
14
+// The Symbol used to tag the ReactElement type. If there is no native Symbol
15
+// nor polyfill, then a plain number is used for performance.
16
+var REACT_ELEMENT_TYPE =
17
+ (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
18
+ 0xeac7;
19
+
20
+module.exports = REACT_ELEMENT_TYPE;
src/shared/utils/traverseAllChildren.js
+10
-2
@@ -12,7 +12,7 @@
12
'use strict';
13
14
var ReactCurrentOwner = require('ReactCurrentOwner');
15
-var ReactElement = require('ReactElement');
15
+var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
16
17
var getIteratorFn = require('getIteratorFn');
18
var invariant = require('invariant');
@@ -22,6 +22,12 @@ var warning = require('warning');
22
var SEPARATOR = '.';
23
var SUBSEPARATOR = ':';
24
25
+/**
26
+ * This is inlined from ReactElement since this file is shared between
27
+ * isomorphic and renderers. We could extract this to a
28
+ *
29
+ */
30
+
31
/**
32
* TODO: Test that a single child and an array with one item have the same key
33
* pattern.
@@ -71,7 +77,9 @@ function traverseAllChildrenImpl(
77
if (children === null ||
78
type === 'string' ||
79
type === 'number' ||
74
- ReactElement.isValidElement(children)) {
80
+ // The following is inlined from ReactElement. This means we can optimize
81
+ // some checks. React Fiber also inlines this logic for similar purposes.
82
+ (type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE)) {
83
callback(
84
traverseContext,
85
children,
src/test/ReactTestUtils.js
+6
-7
@@ -19,7 +19,6 @@ var React = require('React');
19
var ReactDefaultInjection = require('ReactDefaultInjection');
20
var ReactDOM = require('ReactDOM');
21
var ReactDOMComponentTree = require('ReactDOMComponentTree');
22
-var ReactElement = require('ReactElement');
22
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
23
var ReactCompositeComponent = require('ReactCompositeComponent');
24
var ReactInstanceMap = require('ReactInstanceMap');
@@ -61,7 +60,7 @@ function findAllInRenderedTreeInternal(inst, test) {
60
);
61
}
62
} else if (
64
- ReactElement.isValidElement(currentElement) &&
63
+ React.isValidElement(currentElement) &&
64
typeof currentElement.type === 'function'
65
) {
66
ret = ret.concat(
@@ -92,12 +91,12 @@ var ReactTestUtils = {
91
},
92
93
isElement: function(element) {
95
- return ReactElement.isValidElement(element);
94
+ return React.isValidElement(element);
95
},
96
97
isElementOfType: function(inst, convenienceConstructor) {
98
return (
100
- ReactElement.isValidElement(inst) &&
99
+ React.isValidElement(inst) &&
100
inst.type === convenienceConstructor
101
);
102
},
@@ -108,7 +107,7 @@ var ReactTestUtils = {
107
108
isDOMComponentElement: function(inst) {
109
return !!(inst &&
111
- ReactElement.isValidElement(inst) &&
110
+ React.isValidElement(inst) &&
111
!!inst.tagName);
112
},
113
@@ -136,7 +135,7 @@ var ReactTestUtils = {
135
},
136
137
isCompositeComponentElement: function(inst) {
139
- if (!ReactElement.isValidElement(inst)) {
138
+ if (!React.isValidElement(inst)) {
139
return false;
140
}
141
// We check the prototype of the type that will get mounted, not the
@@ -440,7 +439,7 @@ ReactShallowRenderer.prototype.render = function(element, context) {
439
ReactDefaultInjection.inject();
440
441
invariant(
443
- ReactElement.isValidElement(element),
442
+ React.isValidElement(element),
443
'ReactShallowRenderer render(): Invalid component element.%s',
444
typeof element === 'function' ?
445
' Instead of passing a component class, make sure to instantiate ' +