[React Native] Update core modules for React 0.13

This commit is contained in:
Ben Alpert 2015-03-06 16:29:59 -08:00
parent 582c05f4a0
commit b335f88efd
12 changed files with 214 additions and 152 deletions

View File

@ -65,7 +65,7 @@ var TouchableWithoutFeedback = React.createClass({
render: function() {
// Note(vjeux): use cloneWithProps once React has been upgraded
var child = onlyChild(this.props.children);
Object.assign(child.props, {
return React.cloneElement(child, {
accessible: true,
testID: this.props.testID,
onStartShouldSetResponder: this.touchableHandleStartShouldSetResponder,
@ -75,7 +75,6 @@ var TouchableWithoutFeedback = React.createClass({
onResponderRelease: this.touchableHandleResponderRelease,
onResponderTerminate: this.touchableHandleResponderTerminate
});
return child;
}
});

View File

@ -1,21 +0,0 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule RKRawText
* @typechecks static-only
*/
"use strict";
var ReactIOSViewAttributes = require('ReactIOSViewAttributes');
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
var RKRawText = createReactIOSNativeComponentClass({
validAttributes: {
text: true,
},
uiViewClassName: 'RCTRawText',
});
module.exports = RKRawText;

View File

@ -7,8 +7,8 @@
"use strict";
var ReactChildren = require('ReactChildren');
var ReactClass = require('ReactClass');
var ReactComponent = require('ReactComponent');
var ReactCompositeComponent = require('ReactCompositeComponent');
var ReactContext = require('ReactContext');
var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactElement = require('ReactElement');
@ -16,7 +16,6 @@ var ReactElementValidator = require('ReactElementValidator');
var ReactInstanceHandles = require('ReactInstanceHandles');
var ReactIOSDefaultInjection = require('ReactIOSDefaultInjection');
var ReactIOSMount = require('ReactIOSMount');
var ReactLegacyElement = require('ReactLegacyElement');
var ReactPropTypes = require('ReactPropTypes');
var deprecated = require('deprecated');
@ -27,20 +26,14 @@ ReactIOSDefaultInjection.inject();
var createElement = ReactElement.createElement;
var createFactory = ReactElement.createFactory;
var cloneElement = ReactElement.cloneElement;
if (__DEV__) {
createElement = ReactElementValidator.createElement;
createFactory = ReactElementValidator.createFactory;
cloneElement = ReactElementValidator.cloneElement;
}
// TODO: Drop legacy elements once classes no longer export these factories
createElement = ReactLegacyElement.wrapCreateElement(
createElement
);
createFactory = ReactLegacyElement.wrapCreateFactory(
createFactory
);
var resolveDefaultProps = function(element) {
// Could be optimized, but not currently in heavy use.
var defaultProps = element.type.defaultProps;
@ -82,9 +75,10 @@ var ReactIOS = {
only: onlyChild
},
PropTypes: ReactPropTypes,
createClass: ReactCompositeComponent.createClass,
createClass: ReactClass.createClass,
createElement: createElement,
createFactory: createFactory,
cloneElement: cloneElement,
_augmentElement: augmentElement,
render: render,
unmountComponentAtNode: ReactIOSMount.unmountComponentAtNode,

View File

@ -13,10 +13,9 @@ var ReactPerf = require('ReactPerf');
var ReactIOSComponentEnvironment = {
/**
* Will need to supply something that implements this.
*/
BackendIDOperations: ReactIOSDOMIDOperations,
processChildrenUpdates: ReactIOSDOMIDOperations.dangerouslyProcessChildrenUpdates,
replaceNodeWithMarkupByID: ReactIOSDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID,
/**
* Nothing to do for UIKit bridge.
@ -34,34 +33,6 @@ var ReactIOSComponentEnvironment = {
},
/**
* @param {View} view View tree image.
* @param {number} containerViewID View to insert sub-view into.
*/
mountImageIntoNode: ReactPerf.measure(
// FIXME(frantic): #4441289 Hack to avoid modifying react-tools
'ReactComponentBrowserEnvironment',
'mountImageIntoNode',
function(mountImage, containerID) {
// Since we now know that the `mountImage` has been mounted, we can
// mark it as such.
ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle(
mountImage.rootNodeID,
mountImage.tag
);
var addChildTags = [mountImage.tag];
var addAtIndices = [0];
RKUIManager.manageChildren(
ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID),
null, // moveFromIndices
null, // moveToIndices
addChildTags,
addAtIndices,
null // removeAtIndices
);
}
),
ReactReconcileTransaction: ReactIOSReconcileTransaction,
};

View File

@ -6,6 +6,7 @@
'use strict';
var ReactIOSTagHandles = require('ReactIOSTagHandles');
var ReactInstanceMap = require('ReactInstanceMap');
/**
* ReactNative vs ReactWeb
@ -55,11 +56,17 @@ var ReactIOSComponentMixin = {
* `getNodeHandle`.
*/
getNativeNode: function() {
return ReactIOSTagHandles.rootNodeIDToTag[this._rootNodeID];
// TODO (balpert): Wrap iOS native components in a composite wrapper, then
// ReactInstanceMap.get here will always succeed
return ReactIOSTagHandles.rootNodeIDToTag[
(ReactInstanceMap.get(this) || this)._rootNodeID
];
},
getNodeHandle: function() {
return ReactIOSTagHandles.rootNodeIDToTag[this._rootNodeID];
return ReactIOSTagHandles.rootNodeIDToTag[
(ReactInstanceMap.get(this) || this)._rootNodeID
];
}
};

View File

@ -15,20 +15,19 @@ var EventPluginUtils = require('EventPluginUtils');
var IOSDefaultEventPluginOrder = require('IOSDefaultEventPluginOrder');
var IOSNativeBridgeEventPlugin = require('IOSNativeBridgeEventPlugin');
var NodeHandle = require('NodeHandle');
var ReactComponent = require('ReactComponent');
var ReactCompositeComponent = require('ReactCompositeComponent');
var ReactClass = require('ReactClass');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
var ReactElement = require('ReactElement');
var ReactInstanceHandles = require('ReactInstanceHandles');
var ReactIOSComponentEnvironment = require('ReactIOSComponentEnvironment');
var ReactIOSComponentMixin = require('ReactIOSComponentMixin');
var ReactIOSGlobalInteractionHandler = require('ReactIOSGlobalInteractionHandler');
var ReactIOSGlobalResponderHandler = require('ReactIOSGlobalResponderHandler');
var ReactIOSMount = require('ReactIOSMount');
var ReactTextComponent = require('ReactTextComponent');
var ReactIOSTextComponent = require('ReactIOSTextComponent');
var ReactNativeComponent = require('ReactNativeComponent');
var ReactUpdates = require('ReactUpdates');
var ResponderEventPlugin = require('ResponderEventPlugin');
var RKRawText = require('RKRawText');
var UniversalWorkerNodeHandle = require('UniversalWorkerNodeHandle');
// Just to ensure this gets packaged, since its only caller is from Native.
@ -68,23 +67,17 @@ function inject() {
ReactDefaultBatchingStrategy
);
ReactComponent.injection.injectEnvironment(
ReactComponentEnvironment.injection.injectEnvironment(
ReactIOSComponentEnvironment
);
EventPluginUtils.injection.injectMount(ReactIOSMount);
ReactCompositeComponent.injection.injectMixin(ReactIOSComponentMixin);
ReactClass.injection.injectMixin(ReactIOSComponentMixin);
ReactTextComponent.inject(function(initialText) {
// RKRawText is a class so we can't invoke it directly. Instead of using
// a factory, we use the internal fast path to create a descriptor.
// RKRawText is not quite a class yet, so we access the real class from
// the type property. TODO: Change this once factory wrappers are gone.
return new ReactElement(RKRawText.type, null, null, null, null, {
text: initialText
});
});
ReactNativeComponent.injection.injectTextComponentClass(
ReactIOSTextComponent
);
NodeHandle.injection.injectImplementation(UniversalWorkerNodeHandle);
}

View File

@ -9,7 +9,10 @@ var RKUIManager = require('NativeModulesDeprecated').RKUIManager;
var ReactIOSTagHandles = require('ReactIOSTagHandles');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
var ReactUpdates = require('ReactUpdates');
var emptyObject = require('emptyObject');
var instantiateReactComponent = require('instantiateReactComponent');
var invariant = require('invariant');
@ -19,6 +22,49 @@ function instanceNumberToChildRootID(rootNodeID, instanceNumber) {
return rootNodeID + '[' + instanceNumber + ']';
}
/**
* Mounts this component and inserts it into the DOM.
*
* @param {ReactComponent} componentInstance The instance to mount.
* @param {number} rootID ID of the root node.
* @param {number} container container element to mount into.
* @param {ReactReconcileTransaction} transaction
*/
function mountComponentIntoNode(
componentInstance,
rootID,
container,
transaction) {
var markup = ReactReconciler.mountComponent(
componentInstance, rootID, transaction, emptyObject
);
componentInstance._isTopLevel = true;
ReactIOSMount._mountImageIntoNode(markup, container);
}
/**
* Batched mount.
*
* @param {ReactComponent} componentInstance The instance to mount.
* @param {number} rootID ID of the root node.
* @param {number} container container element to mount into.
*/
function batchedMountComponentIntoNode(
componentInstance,
rootID,
container) {
var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
transaction.perform(
mountComponentIntoNode,
null,
componentInstance,
rootID,
container,
transaction
);
ReactUpdates.ReactReconcileTransaction.release(transaction);
}
/**
* As soon as `ReactMount` is refactored to not rely on the DOM, we can share
* code between the two. For now, we'll hard code the ID logic.
@ -52,9 +98,47 @@ var ReactIOSMount = {
ReactIOSMount.instanceCount++
);
ReactIOSMount._instancesByContainerID[topRootNodeID] = instance;
instance.mountComponentIntoNode(childRootNodeID, topRootNodeID);
// The initial render is synchronous but any updates that happen during
// rendering, in componentWillMount or componentDidMount, will be batched
// according to the current batching strategy.
ReactUpdates.batchedUpdates(
batchedMountComponentIntoNode,
instance,
childRootNodeID,
topRootNodeID
);
},
/**
* @param {View} view View tree image.
* @param {number} containerViewID View to insert sub-view into.
*/
_mountImageIntoNode: ReactPerf.measure(
// FIXME(frantic): #4441289 Hack to avoid modifying react-tools
'ReactComponentBrowserEnvironment',
'mountImageIntoNode',
function(mountImage, containerID) {
// Since we now know that the `mountImage` has been mounted, we can
// mark it as such.
ReactIOSTagHandles.associateRootNodeIDWithMountedNodeHandle(
mountImage.rootNodeID,
mountImage.tag
);
var addChildTags = [mountImage.tag];
var addAtIndices = [0];
RKUIManager.manageChildren(
ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID),
null, // moveFromIndices
null, // moveToIndices
addChildTags,
addAtIndices,
null // removeAtIndices
);
}
),
/**
* Standard unmounting of the component that is rendered into `containerID`,
* but will also execute a command to remove the actual container view

View File

@ -6,7 +6,6 @@
'use strict';
var NativeMethodsMixin = require('NativeMethodsMixin');
var ReactComponent = require('ReactComponent');
var ReactIOSComponentMixin = require('ReactIOSComponentMixin');
var ReactIOSEventEmitter = require('ReactIOSEventEmitter');
var ReactIOSStyleAttributes = require('ReactIOSStyleAttributes');
@ -32,8 +31,6 @@ var deleteAllListeners = ReactIOSEventEmitter.deleteAllListeners;
*/
var ReactIOSNativeComponent = function(viewConfig) {
this.viewConfig = viewConfig;
this.props = null;
this.previousFlattenedStyle = null;
};
/**
@ -65,10 +62,19 @@ cachedIndexArray._cache = {};
* which is a `viewID` ... see the return value for `mountComponent` !
*/
ReactIOSNativeComponent.Mixin = {
getPublicInstance: function() {
// TODO: This should probably use a composite wrapper
return this;
},
construct: function(element) {
this._currentElement = element;
},
unmountComponent: function() {
deleteAllListeners(this._rootNodeID);
ReactComponent.Mixin.unmountComponent.call(this);
this.unmountChildren();
this._rootNodeID = null;
},
/**
@ -79,8 +85,8 @@ ReactIOSNativeComponent.Mixin = {
* a child of a container can confidently record that in
* `ReactIOSTagHandles`.
*/
initializeChildren: function(children, containerTag, transaction) {
var mountImages = this.mountChildren(children, transaction);
initializeChildren: function(children, containerTag, transaction, context) {
var mountImages = this.mountChildren(children, transaction, context);
// In a well balanced tree, half of the nodes are in the bottom row and have
// no children - let's avoid calling out to the native bridge for a large
// portion of the children.
@ -158,21 +164,18 @@ ReactIOSNativeComponent.Mixin = {
/**
* Updates the component's currently mounted representation.
*
* @param {object} nextElement
* @param {ReactReconcileTransaction} transaction
* @param {object} prevDescriptor
* @param {object} context
* @internal
*/
updateComponent: function(transaction, prevDescriptor) {
ReactComponent.Mixin.updateComponent.call(
this,
transaction,
prevDescriptor
);
var nextDescriptor = this._currentElement;
receiveComponent: function(nextElement, transaction, context) {
var prevElement = this._currentElement;
this._currentElement = nextElement;
var updatePayload = this.computeUpdatedProperties(
prevDescriptor.props,
nextDescriptor.props,
prevElement.props,
nextElement.props,
this.viewConfig.validAttributes
);
@ -185,10 +188,10 @@ ReactIOSNativeComponent.Mixin = {
}
this._reconcileListenersUponUpdate(
prevDescriptor.props,
nextDescriptor.props
prevElement.props,
nextElement.props
);
this.updateChildren(this.props.children, transaction);
this.updateChildren(nextElement.props.children, transaction, context);
},
/**
@ -223,25 +226,26 @@ ReactIOSNativeComponent.Mixin = {
* @param {Transaction} transaction For creating/updating.
* @return {string} Unique iOS view tag.
*/
mountComponent: function(rootID, transaction, mountDepth) {
ReactComponent.Mixin.mountComponent.call(
this,
rootID,
transaction,
mountDepth
);
mountComponent: function(rootID, transaction, context) {
this._rootNodeID = rootID;
var tag = ReactIOSTagHandles.allocateTag();
this.previousFlattenedStyle = {};
var updatePayload = this.computeUpdatedProperties(
{}, // previous props
this.props, // next props
this._currentElement.props, // next props
this.viewConfig.validAttributes
);
RKUIManager.createView(tag, this.viewConfig.uiViewClassName, updatePayload);
this._registerListenersUponCreation(this.props);
this.initializeChildren(this.props.children, tag, transaction);
this._registerListenersUponCreation(this._currentElement.props);
this.initializeChildren(
this._currentElement.props.children,
tag,
transaction,
context
);
return {
rootNodeID: rootID,
tag: tag
@ -255,7 +259,6 @@ ReactIOSNativeComponent.Mixin = {
*/
Object.assign(
ReactIOSNativeComponent.prototype,
ReactComponent.Mixin,
ReactMultiChild.Mixin,
ReactIOSNativeComponent.Mixin,
NativeMethodsMixin,

View File

@ -0,0 +1,62 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* @providesModule ReactIOSTextComponent
*/
'use strict';
var ReactIOSTagHandles = require('ReactIOSTagHandles');
var RKUIManager = require('NativeModulesDeprecated').RKUIManager;
var assign = require('Object.assign');
var ReactIOSTextComponent = function(props) {
// This constructor and its argument is currently used by mocks.
};
assign(ReactIOSTextComponent.prototype, {
construct: function(text) {
// This is really a ReactText (ReactNode), not a ReactElement
this._currentElement = text;
this._stringText = '' + text;
this._rootNodeID = null;
},
mountComponent: function(rootID, transaction, context) {
this._rootNodeID = rootID;
var tag = ReactIOSTagHandles.allocateTag();
RKUIManager.createView(tag, 'RCTRawText', {text: this._stringText});
return {
rootNodeID: rootID,
tag: tag,
};
},
receiveComponent: function(nextText, transaction, context) {
if (nextText !== this._currentElement) {
this._currentElement = nextText;
var nextStringText = '' + nextText;
if (nextStringText !== this._stringText) {
this._stringText = nextStringText;
RKUIManager.updateView(
ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(
this._rootNodeID
),
'RCTRawText',
{text: this._stringText}
);
}
}
},
unmountComponent: function() {
this._currentElement = null;
this._stringText = null;
this._rootNodeID = null;
}
});
module.exports = ReactIOSTextComponent;

View File

@ -1,30 +0,0 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @providesModule ReactTextComponent
* @typechecks static-only
*/
"use strict";
var InjectedTextComponent = null;
var ReactTextComponent = function() {
return InjectedTextComponent.apply(this, arguments);
};
ReactTextComponent.inject = function(textComponent) {
InjectedTextComponent = textComponent;
};
module.exports = ReactTextComponent;

View File

@ -7,7 +7,6 @@
"use strict";
var ReactElement = require('ReactElement');
var ReactLegacyElement = require('ReactLegacyElement');
var ReactIOSNativeComponent = require('ReactIOSNativeComponent');
/**
@ -15,15 +14,17 @@ var ReactIOSNativeComponent = require('ReactIOSNativeComponent');
* @private
*/
var createReactIOSNativeComponentClass = function(viewConfig) {
var Constructor = function(props) {
var Constructor = function(element) {
this._currentElement = element;
this._rootNodeID = null;
this._renderedChildren = null;
this.previousFlattenedStyle = null;
};
Constructor.displayName = viewConfig.uiViewClassName;
Constructor.prototype = new ReactIOSNativeComponent(viewConfig);
Constructor.prototype.constructor = Constructor;
return ReactLegacyElement.wrapFactory(
ReactElement.createFactory(Constructor)
);
return Constructor;
};
module.exports = createReactIOSNativeComponentClass;

View File

@ -22,7 +22,6 @@ var webBlacklist = [
var iosBlacklist = [
'node_modules/react-tools/src/browser/ui/React.js',
'node_modules/react-tools/src/browser/eventPlugins/ResponderEventPlugin.js',
'node_modules/react-tools/src/browser/ReactTextComponent.js',
// 'node_modules/react-tools/src/vendor/core/ExecutionEnvironment.js',
'.web.js',
'.android.js',