diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index ebabdd9cc..ccc784e6a 100644 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -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; } }); diff --git a/Libraries/ReactIOS/NativeModules/RKRawText.js b/Libraries/ReactIOS/NativeModules/RKRawText.js deleted file mode 100644 index c56f0f68f..000000000 --- a/Libraries/ReactIOS/NativeModules/RKRawText.js +++ /dev/null @@ -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; diff --git a/Libraries/ReactIOS/ReactIOS.js b/Libraries/ReactIOS/ReactIOS.js index 0022e09bd..4b4b19db0 100644 --- a/Libraries/ReactIOS/ReactIOS.js +++ b/Libraries/ReactIOS/ReactIOS.js @@ -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, diff --git a/Libraries/ReactIOS/ReactIOSComponentEnvironment.js b/Libraries/ReactIOS/ReactIOSComponentEnvironment.js index 67da68b13..ac67a7580 100644 --- a/Libraries/ReactIOS/ReactIOSComponentEnvironment.js +++ b/Libraries/ReactIOS/ReactIOSComponentEnvironment.js @@ -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, }; diff --git a/Libraries/ReactIOS/ReactIOSComponentMixin.js b/Libraries/ReactIOS/ReactIOSComponentMixin.js index 7abb213ee..f9ddde2c2 100644 --- a/Libraries/ReactIOS/ReactIOSComponentMixin.js +++ b/Libraries/ReactIOS/ReactIOSComponentMixin.js @@ -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 + ]; } }; diff --git a/Libraries/ReactIOS/ReactIOSDefaultInjection.js b/Libraries/ReactIOS/ReactIOSDefaultInjection.js index 729c294e5..09dc9ea0a 100644 --- a/Libraries/ReactIOS/ReactIOSDefaultInjection.js +++ b/Libraries/ReactIOS/ReactIOSDefaultInjection.js @@ -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); } diff --git a/Libraries/ReactIOS/ReactIOSMount.js b/Libraries/ReactIOS/ReactIOSMount.js index 4e29be92f..23691143a 100644 --- a/Libraries/ReactIOS/ReactIOSMount.js +++ b/Libraries/ReactIOS/ReactIOSMount.js @@ -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 diff --git a/Libraries/ReactIOS/ReactIOSNativeComponent.js b/Libraries/ReactIOS/ReactIOSNativeComponent.js index 7c8381855..df8b59833 100644 --- a/Libraries/ReactIOS/ReactIOSNativeComponent.js +++ b/Libraries/ReactIOS/ReactIOSNativeComponent.js @@ -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, diff --git a/Libraries/ReactIOS/ReactIOSTextComponent.js b/Libraries/ReactIOS/ReactIOSTextComponent.js new file mode 100644 index 000000000..4ec0c7a1a --- /dev/null +++ b/Libraries/ReactIOS/ReactIOSTextComponent.js @@ -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; diff --git a/Libraries/ReactIOS/ReactTextComponent.js b/Libraries/ReactIOS/ReactTextComponent.js deleted file mode 100644 index 7ecbed18a..000000000 --- a/Libraries/ReactIOS/ReactTextComponent.js +++ /dev/null @@ -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; diff --git a/Libraries/ReactIOS/createReactIOSNativeComponentClass.js b/Libraries/ReactIOS/createReactIOSNativeComponentClass.js index 8df2f510b..465b26ba4 100644 --- a/Libraries/ReactIOS/createReactIOSNativeComponentClass.js +++ b/Libraries/ReactIOS/createReactIOSNativeComponentClass.js @@ -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; diff --git a/Libraries/vendor/core/copyProperties.js b/Libraries/vendor/core/copyProperties.js new file mode 100644 index 000000000..e5a2638d9 --- /dev/null +++ b/Libraries/vendor/core/copyProperties.js @@ -0,0 +1,53 @@ +/** + * @generated SignedSource<> + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !! This file is a check-in of a static_upstream project! !! + * !! !! + * !! You should not modify this file directly. Instead: !! + * !! 1) Use `fjs use-upstream` to temporarily replace this with !! + * !! the latest version from upstream. !! + * !! 2) Make your changes, test them, etc. !! + * !! 3) Use `fjs push-upstream` to copy your changes back to !! + * !! static_upstream. !! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * @providesModule copyProperties + */ + +/** + * Copy properties from one or more objects (up to 5) into the first object. + * This is a shallow copy. It mutates the first object and also returns it. + * + * NOTE: `arguments` has a very significant performance penalty, which is why + * we don't support unlimited arguments. + */ +function copyProperties(obj, a, b, c, d, e, f) { + obj = obj || {}; + + if (__DEV__) { + if (f) { + throw new Error('Too many arguments passed to copyProperties'); + } + } + + var args = [a, b, c, d, e]; + var ii = 0, v; + while (args[ii]) { + v = args[ii++]; + for (var k in v) { + obj[k] = v[k]; + } + + // IE ignores toString in object iteration.. See: + // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html + if (v.hasOwnProperty && v.hasOwnProperty('toString') && + (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { + obj.toString = v.toString; + } + } + + return obj; +} + +module.exports = copyProperties; diff --git a/Libraries/vendor/core/mergeHelpers.js b/Libraries/vendor/core/mergeHelpers.js new file mode 100644 index 000000000..58fa238d4 --- /dev/null +++ b/Libraries/vendor/core/mergeHelpers.js @@ -0,0 +1,160 @@ +/** + * @generated SignedSource<> + * + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * !! This file is a check-in of a static_upstream project! !! + * !! !! + * !! You should not modify this file directly. Instead: !! + * !! 1) Use `fjs use-upstream` to temporarily replace this with !! + * !! the latest version from upstream. !! + * !! 2) Make your changes, test them, etc. !! + * !! 3) Use `fjs push-upstream` to copy your changes back to !! + * !! static_upstream. !! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * + * Copyright 2013-2014 Facebook, Inc. + * + * 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 mergeHelpers + * + * requiresPolyfills: Array.isArray + */ + +"use strict"; + +var invariant = require('invariant'); +var keyMirror = require('keyMirror'); + +/** + * Maximum number of levels to traverse. Will catch circular structures. + * @const + */ +var MAX_MERGE_DEPTH = 36; + +/** + * We won't worry about edge cases like new String('x') or new Boolean(true). + * Functions are considered terminals, and arrays are not. + * @param {*} o The item/object/value to test. + * @return {boolean} true iff the argument is a terminal. + */ +var isTerminal = function(o) { + return typeof o !== 'object' || o === null; +}; + +var mergeHelpers = { + + MAX_MERGE_DEPTH: MAX_MERGE_DEPTH, + + isTerminal: isTerminal, + + /** + * Converts null/undefined values into empty object. + * + * @param {?Object=} arg Argument to be normalized (nullable optional) + * @return {!Object} + */ + normalizeMergeArg: function(arg) { + return arg === undefined || arg === null ? {} : arg; + }, + + /** + * If merging Arrays, a merge strategy *must* be supplied. If not, it is + * likely the caller's fault. If this function is ever called with anything + * but `one` and `two` being `Array`s, it is the fault of the merge utilities. + * + * @param {*} one Array to merge into. + * @param {*} two Array to merge from. + */ + checkMergeArrayArgs: function(one, two) { + invariant( + Array.isArray(one) && Array.isArray(two), + 'Tried to merge arrays, instead got %s and %s.', + one, + two + ); + }, + + /** + * @param {*} one Object to merge into. + * @param {*} two Object to merge from. + */ + checkMergeObjectArgs: function(one, two) { + mergeHelpers.checkMergeObjectArg(one); + mergeHelpers.checkMergeObjectArg(two); + }, + + /** + * @param {*} arg + */ + checkMergeObjectArg: function(arg) { + invariant( + !isTerminal(arg) && !Array.isArray(arg), + 'Tried to merge an object, instead got %s.', + arg + ); + }, + + /** + * @param {*} arg + */ + checkMergeIntoObjectArg: function(arg) { + invariant( + (!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg), + 'Tried to merge into an object, instead got %s.', + arg + ); + }, + + /** + * Checks that a merge was not given a circular object or an object that had + * too great of depth. + * + * @param {number} Level of recursion to validate against maximum. + */ + checkMergeLevel: function(level) { + invariant( + level < MAX_MERGE_DEPTH, + 'Maximum deep merge depth exceeded. You may be attempting to merge ' + + 'circular structures in an unsupported way.' + ); + }, + + /** + * Checks that the supplied merge strategy is valid. + * + * @param {string} Array merge strategy. + */ + checkArrayStrategy: function(strategy) { + invariant( + strategy === undefined || strategy in mergeHelpers.ArrayStrategies, + 'You must provide an array strategy to deep merge functions to ' + + 'instruct the deep merge how to resolve merging two arrays.' + ); + }, + + /** + * Set of possible behaviors of merge algorithms when encountering two Arrays + * that must be merged together. + * - `clobber`: The left `Array` is ignored. + * - `indexByIndex`: The result is achieved by recursively deep merging at + * each index. (not yet supported.) + */ + ArrayStrategies: keyMirror({ + Clobber: true, + IndexByIndex: true + }) + +}; + +module.exports = mergeHelpers; diff --git a/package.json b/package.json index 18516ccbc..f0af6823e 100644 --- a/package.json +++ b/package.json @@ -28,19 +28,19 @@ "absolute-path": "0.0.0", "connect": "2.8.3", "debug": "~2.1.0", - "jstransform": "8.2.0", + "joi": "~5.1.0", + "jstransform": "10.0.1", "module-deps": "3.5.6", "optimist": "0.6.1", "q": "1.0.1", - "react-tools": "0.12.2", + "react-tools": "0.13.0-rc2", "sane": "1.0.1", "source-map": "0.1.31", "stacktrace-parser": "0.1.1", + "uglify-js": "~2.4.16", "underscore": "1.7.0", "worker-farm": "1.1.0", - "yargs": "1.3.2", - "joi": "~5.1.0", - "uglify-js": "~2.4.16" + "yargs": "1.3.2" }, "devDependencies": { "jest-cli": "0.2.1", diff --git a/packager/blacklist.js b/packager/blacklist.js index 2b710af62..eb81f4524 100644 --- a/packager/blacklist.js +++ b/packager/blacklist.js @@ -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',