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.
(cherry picked from commit 1c5a639c37)
This commit is contained in:
Sebastian Markbåge 2016-08-11 18:56:55 -07:00 committed by Paul O’Shannessy
parent 5c2a88a9a1
commit cc2e5cc3d7
23 changed files with 79 additions and 89 deletions

View File

@ -40,4 +40,6 @@ declare module 'UIManager' {
declare function setChildren() : void;
declare function updateView() : void;
}
declare module 'View' { }
declare module 'View' {
declare var exports : typeof ReactComponent;
}

View File

@ -19,13 +19,8 @@ var SECRET_INTERNALS_NAME = 'React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_
var shimSharedModulesFiles = {
'./ReactCurrentOwner': SECRET_INTERNALS_NAME + '.ReactCurrentOwner',
'./ReactComponentTreeHook': SECRET_INTERNALS_NAME + '.ReactComponentTreeHook',
// The methods we used here are exposed on the main React export.
// TODO: Change all renderer code to require the isomorphic React directly
// instead of these internals.
// Use the global, anywhere we require React
'./React': 'React',
'./ReactElement': 'React',
'./ReactPropTypes': 'React.PropTypes',
'./ReactChildren': 'React.Children',
};
// We can access these as absolute or relative. We need to shim both.

View File

@ -111,20 +111,11 @@ var moduleMapReact = Object.assign(
);
var rendererSharedState = {
// Alias
React: 'react/lib/React',
// Shared state
ReactCurrentOwner: 'react/lib/ReactCurrentOwner',
ReactComponentTreeHook: 'react/lib/ReactComponentTreeHook',
// TODO: Move to shared since these are actually shared and can be copied.
ReactPropTypeLocations: 'react/lib/ReactPropTypeLocations',
ReactPropTypesSecret: 'react/lib/ReactPropTypesSecret',
checkReactTypeSpec: 'react/lib/checkReactTypeSpec',
// TODO: Update the source to just use the React module.
React: 'react/lib/React',
ReactElement: 'react/lib/ReactElement',
ReactPropTypes: 'react/lib/ReactPropTypes',
ReactChildren: 'react/lib/ReactChildren',
};
var moduleMapReactDOM = Object.assign(

View File

@ -17,11 +17,7 @@ var warning = require('warning');
var canDefineProperty = require('canDefineProperty');
var hasOwnProperty = Object.prototype.hasOwnProperty;
// The Symbol used to tag the ReactElement type. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
var REACT_ELEMENT_TYPE =
(typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
0xeac7;
var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
var RESERVED_PROPS = {
key: true,
@ -390,6 +386,4 @@ ReactElement.isValidElement = function(object) {
);
};
ReactElement.REACT_ELEMENT_TYPE = REACT_ELEMENT_TYPE;
module.exports = ReactElement;

View File

@ -13,12 +13,12 @@
var DOMLazyTree = require('DOMLazyTree');
var DOMProperty = require('DOMProperty');
var React = require('React');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
var ReactElement = require('ReactElement');
var ReactFeatureFlags = require('ReactFeatureFlags');
var ReactInstanceMap = require('ReactInstanceMap');
var ReactInstrumentation = require('ReactInstrumentation');
@ -423,7 +423,7 @@ var ReactMount = {
_renderSubtreeIntoContainer: function(parentComponent, nextElement, container, callback) {
ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');
invariant(
ReactElement.isValidElement(nextElement),
React.isValidElement(nextElement),
'ReactDOM.render(): Invalid component element.%s',
(
typeof nextElement === 'string' ?
@ -450,7 +450,7 @@ var ReactMount = {
'for your app.'
);
var nextWrappedElement = ReactElement.createElement(
var nextWrappedElement = React.createElement(
TopLevelWrapper,
{ child: nextElement }
);

View File

@ -11,7 +11,7 @@
'use strict';
var ReactPropTypes = require('ReactPropTypes');
var React = require('React');
var ReactPropTypeLocations = require('ReactPropTypeLocations');
var ReactPropTypesSecret = require('ReactPropTypesSecret');
@ -84,7 +84,7 @@ var propTypes = {
'set either `onChange` or `readOnly`.'
);
},
onChange: ReactPropTypes.func,
onChange: React.PropTypes.func,
};
var loggedTypeFailures = {};

View File

@ -11,7 +11,7 @@
'use strict';
var ReactChildren = require('ReactChildren');
var React = require('React');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactDOMSelect = require('ReactDOMSelect');
@ -23,7 +23,7 @@ function flattenChildren(children) {
// Flatten children and warn if they aren't strings or numbers;
// invalid types are ignored.
ReactChildren.forEach(children, function(child) {
React.Children.forEach(children, function(child) {
if (child == null) {
return;
}

View File

@ -10,9 +10,9 @@
*/
'use strict';
var React = require('React');
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
var ReactElement = require('ReactElement');
var ReactInstrumentation = require('ReactInstrumentation');
var ReactMarkupChecksum = require('ReactMarkupChecksum');
var ReactReconciler = require('ReactReconciler');
@ -80,7 +80,7 @@ function renderToStringImpl(element, makeStaticMarkup) {
*/
function renderToString(element) {
invariant(
ReactElement.isValidElement(element),
React.isValidElement(element),
'renderToString(): You must pass a valid ReactElement.'
);
return renderToStringImpl(element, false);
@ -93,7 +93,7 @@ function renderToString(element) {
*/
function renderToStaticMarkup(element) {
invariant(
ReactElement.isValidElement(element),
React.isValidElement(element),
'renderToStaticMarkup(): You must pass a valid ReactElement.'
);
return renderToStringImpl(element, true);

View File

@ -16,7 +16,6 @@
var ReactNativeComponentTree = require('ReactNativeComponentTree');
var ReactNativeDefaultInjection = require('ReactNativeDefaultInjection');
var ReactElement = require('ReactElement');
var ReactNativeMount = require('ReactNativeMount');
var ReactUpdates = require('ReactUpdates');
@ -25,7 +24,7 @@ var findNodeHandle = require('findNodeHandle');
ReactNativeDefaultInjection.inject();
var render = function(
element: ReactElement,
element: ReactElement<any>,
mountInto: number,
callback?: ?(() => void)
): ?ReactComponent<any, any, any> {

View File

@ -22,9 +22,9 @@ require('InitializeJavaScriptAppEngine');
var EventPluginHub = require('EventPluginHub');
var EventPluginUtils = require('EventPluginUtils');
var RCTEventEmitter = require('RCTEventEmitter');
var React = require('React');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
var ReactElement = require('ReactElement');
var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactNativeBridgeEventPlugin = require('ReactNativeBridgeEventPlugin');
var ReactHostComponent = require('ReactHostComponent');
@ -83,7 +83,7 @@ function inject() {
// Can't import View at the top because it depends on React to make its composite
var View = require('View');
return new ReactSimpleEmptyComponent(
ReactElement.createElement(View, {
React.createElement(View, {
collapsable: true,
style: { position: 'absolute' },
}),

View File

@ -11,7 +11,7 @@
*/
'use strict';
var ReactElement = require('ReactElement');
var React = require('React');
var ReactInstrumentation = require('ReactInstrumentation');
var ReactNativeContainerInfo = require('ReactNativeContainerInfo');
var ReactNativeTagHandles = require('ReactNativeTagHandles');
@ -35,9 +35,9 @@ if (__DEV__) {
TopLevelWrapper.displayName = 'TopLevelWrapper';
}
TopLevelWrapper.prototype.render = function() {
// this.props is actually a ReactElement
return this.props;
return this.props.child;
};
TopLevelWrapper.isReactTopLevelWrapper = true;
/**
* Mounts this component and inserts it into the DOM.
@ -99,25 +99,20 @@ var ReactNativeMount = {
* @param {containerTag} containerView Handle to native view tag
*/
renderComponent: function(
nextElement: ReactElement,
nextElement: ReactElement<*>,
containerTag: number,
callback?: ?(() => void)
): ?ReactComponent<any, any, any> {
var nextWrappedElement = new ReactElement(
var nextWrappedElement = React.createElement(
TopLevelWrapper,
null,
null,
null,
null,
null,
nextElement
{ child: nextElement }
);
var topRootNodeID = containerTag;
var prevComponent = ReactNativeMount._instancesByContainerID[topRootNodeID];
if (prevComponent) {
var prevWrappedElement = prevComponent._currentElement;
var prevElement = prevWrappedElement.props;
var prevElement = prevWrappedElement.props.child;
if (shouldUpdateReactComponent(prevElement, nextElement)) {
ReactUpdateQueue.enqueueElementInternal(prevComponent, nextWrappedElement, emptyObject);
if (callback) {

View File

@ -18,9 +18,7 @@ import type { PriorityLevel } from 'ReactPriorityLevel';
import type { ReactNodeList } from 'ReactTypes';
var {
REACT_ELEMENT_TYPE,
} = require('ReactElement');
var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
var {
REACT_COROUTINE_TYPE,
REACT_YIELD_TYPE,

View File

@ -26,8 +26,6 @@ var {
YieldComponent,
} = ReactTypeOfWork;
var ReactElement = require('ReactElement');
var {
NoWork,
} = require('ReactPriorityLevel');
@ -201,7 +199,8 @@ exports.createHostContainerFiber = function() {
return fiber;
};
exports.createFiberFromElement = function(element : ReactElement, priorityLevel : PriorityLevel) {
exports.createFiberFromElement = function(element : ReactElement<*>, priorityLevel : PriorityLevel) {
// $FlowFixMe: ReactElement.key is currently defined as ?string but should be defined as null | string in Flow.
const fiber = createFiberFromElementType(element.type, element.key);
fiber.pendingProps = element.props;
fiber.pendingWorkPriority = priorityLevel;

View File

@ -11,9 +11,9 @@
'use strict';
var React = require('React');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactElement = require('ReactElement');
var ReactErrorUtils = require('ReactErrorUtils');
var ReactInstanceMap = require('ReactInstanceMap');
var ReactInstrumentation = require('ReactInstrumentation');
@ -49,7 +49,7 @@ StatelessComponent.prototype.render = function() {
function warnIfInvalidElement(Component, element) {
if (__DEV__) {
warning(
element === null || element === false || ReactElement.isValidElement(element),
element === null || element === false || React.isValidElement(element),
'%s(...): A valid React element (or null) must be returned. You may have ' +
'returned undefined, an array or some other invalid object.',
Component.displayName || Component.name || 'Component'
@ -212,7 +212,7 @@ var ReactCompositeComponentMixin = {
invariant(
inst === null ||
inst === false ||
ReactElement.isValidElement(inst),
React.isValidElement(inst),
'%s(...): A valid React element (or null) must be returned. You may have ' +
'returned undefined, an array or some other invalid object.',
Component.displayName || Component.name || 'Component'
@ -1078,7 +1078,7 @@ var ReactCompositeComponentMixin = {
invariant(
// TODO: An `isValidNode` function would probably be more appropriate
renderedComponent === null || renderedComponent === false ||
ReactElement.isValidElement(renderedComponent),
React.isValidElement(renderedComponent),
'%s.render(): A valid React element (or null) must be returned. You may have ' +
'returned undefined, an array or some other invalid object.',
this.getName() || 'ReactCompositeComponent'

View File

@ -14,7 +14,7 @@
type ReactNodeType = 0 | 1 | 2;
var ReactElement = require('ReactElement');
var React = require('React');
var invariant = require('invariant');
@ -26,7 +26,7 @@ var ReactNodeTypes = {
getType: function(node: ReactElement<any>): ReactNodeType {
if (node === null || node === false) {
return ReactNodeTypes.EMPTY;
} else if (ReactElement.isValidElement(node)) {
} else if (React.isValidElement(node)) {
if (typeof node.type === 'function') {
return ReactNodeTypes.COMPOSITE;
} else {

View File

@ -11,7 +11,7 @@
*/
'use strict';
var ReactElement = require('ReactElement');
var React = require('React');
var ReactReconciler = require('ReactReconciler');
var ReactUpdates = require('ReactUpdates');
@ -31,9 +31,9 @@ if (__DEV__) {
TopLevelWrapper.displayName = 'TopLevelWrapper';
}
TopLevelWrapper.prototype.render = function() {
// this.props is actually a ReactElement
return this.props;
return this.props.child;
};
TopLevelWrapper.isReactTopLevelWrapper = true;
/**
* Mounts this component and inserts it into the DOM.
@ -88,14 +88,9 @@ ReactTestInstance.prototype.update = function(nextElement) {
this._component,
"ReactTestRenderer: .update() can't be called after unmount."
);
var nextWrappedElement = new ReactElement(
var nextWrappedElement = React.createElement(
TopLevelWrapper,
null,
null,
null,
null,
null,
nextElement
{ child: nextElement }
);
var component = this._component;
ReactUpdates.batchedUpdates(function() {
@ -142,14 +137,9 @@ var ReactTestMount = {
render: function(
nextElement: ReactElement<any>
): ReactTestInstance {
var nextWrappedElement = new ReactElement(
var nextWrappedElement = React.createElement(
TopLevelWrapper,
null,
null,
null,
null,
null,
nextElement
{ child: nextElement }
);
var instance = instantiateReactComponent(nextWrappedElement, false);

View File

@ -0,0 +1,20 @@
/**
* Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactElementSymbol
*/
'use strict';
// The Symbol used to tag the ReactElement type. If there is no native Symbol
// nor polyfill, then a plain number is used for performance.
var REACT_ELEMENT_TYPE =
(typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
0xeac7;
module.exports = REACT_ELEMENT_TYPE;

View File

@ -12,7 +12,7 @@
'use strict';
var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactElement = require('ReactElement');
var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
var getIteratorFn = require('getIteratorFn');
var invariant = require('invariant');
@ -22,6 +22,12 @@ var warning = require('warning');
var SEPARATOR = '.';
var SUBSEPARATOR = ':';
/**
* This is inlined from ReactElement since this file is shared between
* isomorphic and renderers. We could extract this to a
*
*/
/**
* TODO: Test that a single child and an array with one item have the same key
* pattern.
@ -71,7 +77,9 @@ function traverseAllChildrenImpl(
if (children === null ||
type === 'string' ||
type === 'number' ||
ReactElement.isValidElement(children)) {
// The following is inlined from ReactElement. This means we can optimize
// some checks. React Fiber also inlines this logic for similar purposes.
(type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE)) {
callback(
traverseContext,
children,

View File

@ -19,7 +19,6 @@ var React = require('React');
var ReactDefaultInjection = require('ReactDefaultInjection');
var ReactDOM = require('ReactDOM');
var ReactDOMComponentTree = require('ReactDOMComponentTree');
var ReactElement = require('ReactElement');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactCompositeComponent = require('ReactCompositeComponent');
var ReactInstanceMap = require('ReactInstanceMap');
@ -61,7 +60,7 @@ function findAllInRenderedTreeInternal(inst, test) {
);
}
} else if (
ReactElement.isValidElement(currentElement) &&
React.isValidElement(currentElement) &&
typeof currentElement.type === 'function'
) {
ret = ret.concat(
@ -92,12 +91,12 @@ var ReactTestUtils = {
},
isElement: function(element) {
return ReactElement.isValidElement(element);
return React.isValidElement(element);
},
isElementOfType: function(inst, convenienceConstructor) {
return (
ReactElement.isValidElement(inst) &&
React.isValidElement(inst) &&
inst.type === convenienceConstructor
);
},
@ -108,7 +107,7 @@ var ReactTestUtils = {
isDOMComponentElement: function(inst) {
return !!(inst &&
ReactElement.isValidElement(inst) &&
React.isValidElement(inst) &&
!!inst.tagName);
},
@ -136,7 +135,7 @@ var ReactTestUtils = {
},
isCompositeComponentElement: function(inst) {
if (!ReactElement.isValidElement(inst)) {
if (!React.isValidElement(inst)) {
return false;
}
// We check the prototype of the type that will get mounted, not the
@ -440,7 +439,7 @@ ReactShallowRenderer.prototype.render = function(element, context) {
ReactDefaultInjection.inject();
invariant(
ReactElement.isValidElement(element),
React.isValidElement(element),
'ReactShallowRenderer render(): Invalid component element.%s',
typeof element === 'function' ?
' Instead of passing a component class, make sure to instantiate ' +