react 0.13.0-alpha.2 → 0.13.0-rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/JSXTransformer.js +1798 -1194
  2. package/dist/react-with-addons.js +2640 -2046
  3. package/dist/react-with-addons.min.js +7 -6
  4. package/dist/react.js +2459 -1930
  5. package/dist/react.min.js +6 -6
  6. package/lib/AutoFocusMixin.js +1 -1
  7. package/lib/BeforeInputEventPlugin.js +1 -5
  8. package/lib/CSSCore.js +1 -1
  9. package/lib/CSSProperty.js +3 -1
  10. package/lib/CSSPropertyOperations.js +43 -16
  11. package/lib/CallbackQueue.js +1 -1
  12. package/lib/ChangeEventPlugin.js +1 -1
  13. package/lib/ClientReactRootIndex.js +1 -1
  14. package/lib/DOMChildrenOperations.js +4 -43
  15. package/lib/DOMProperty.js +1 -1
  16. package/lib/DOMPropertyOperations.js +10 -15
  17. package/lib/Danger.js +1 -1
  18. package/lib/DefaultEventPluginOrder.js +2 -2
  19. package/lib/EnterLeaveEventPlugin.js +1 -1
  20. package/lib/EventConstants.js +1 -1
  21. package/lib/EventListener.js +1 -1
  22. package/lib/EventPluginHub.js +1 -1
  23. package/lib/EventPluginRegistry.js +1 -1
  24. package/lib/EventPluginUtils.js +3 -3
  25. package/lib/EventPropagators.js +1 -1
  26. package/lib/ExecutionEnvironment.js +1 -1
  27. package/lib/FallbackCompositionState.js +1 -1
  28. package/lib/HTMLDOMPropertyConfig.js +12 -5
  29. package/lib/LinkedStateMixin.js +1 -1
  30. package/lib/LinkedValueUtils.js +1 -1
  31. package/lib/LocalEventTrapMixin.js +9 -2
  32. package/lib/MobileSafariClickEventPlugin.js +1 -1
  33. package/lib/Object.assign.js +1 -1
  34. package/lib/PooledClass.js +1 -1
  35. package/lib/React.js +11 -14
  36. package/lib/ReactBrowserComponentMixin.js +1 -1
  37. package/lib/ReactBrowserEventEmitter.js +2 -2
  38. package/lib/ReactCSSTransitionGroup.js +1 -1
  39. package/lib/ReactCSSTransitionGroupChild.js +8 -5
  40. package/lib/ReactChildReconciler.js +9 -5
  41. package/lib/ReactChildren.js +3 -2
  42. package/lib/ReactClass.js +144 -76
  43. package/lib/ReactComponent.js +99 -166
  44. package/lib/ReactComponentBrowserEnvironment.js +1 -1
  45. package/lib/ReactComponentEnvironment.js +1 -1
  46. package/lib/ReactComponentWithPureRenderMixin.js +1 -1
  47. package/lib/ReactCompositeComponent.js +261 -480
  48. package/lib/ReactContext.js +13 -3
  49. package/lib/ReactCurrentOwner.js +1 -1
  50. package/lib/ReactDOM.js +1 -1
  51. package/lib/ReactDOMButton.js +1 -1
  52. package/lib/ReactDOMComponent.js +23 -48
  53. package/lib/ReactDOMForm.js +1 -1
  54. package/lib/ReactDOMIDOperations.js +3 -3
  55. package/lib/ReactDOMIframe.js +43 -0
  56. package/lib/ReactDOMImg.js +1 -1
  57. package/lib/ReactDOMInput.js +1 -1
  58. package/lib/ReactDOMOption.js +1 -1
  59. package/lib/ReactDOMSelect.js +1 -1
  60. package/lib/ReactDOMSelection.js +1 -1
  61. package/lib/ReactDOMTextComponent.js +3 -12
  62. package/lib/ReactDOMTextarea.js +1 -1
  63. package/lib/ReactDefaultBatchingStrategy.js +4 -4
  64. package/lib/ReactDefaultInjection.js +25 -1
  65. package/lib/ReactDefaultPerf.js +11 -3
  66. package/lib/ReactDefaultPerfAnalysis.js +1 -1
  67. package/lib/ReactElement.js +59 -4
  68. package/lib/ReactElementValidator.js +141 -85
  69. package/lib/ReactEmptyComponent.js +5 -5
  70. package/lib/ReactErrorUtils.js +1 -1
  71. package/lib/ReactEventEmitterMixin.js +1 -1
  72. package/lib/ReactEventListener.js +1 -2
  73. package/lib/ReactFragment.js +181 -0
  74. package/lib/ReactInjection.js +1 -1
  75. package/lib/ReactInputSelection.js +1 -1
  76. package/lib/ReactInstanceHandles.js +1 -1
  77. package/lib/ReactInstanceMap.js +1 -1
  78. package/lib/ReactLifeCycle.js +35 -0
  79. package/lib/ReactLink.js +1 -1
  80. package/lib/ReactMarkupChecksum.js +1 -1
  81. package/lib/ReactMount.js +77 -20
  82. package/lib/ReactMultiChild.js +7 -4
  83. package/lib/ReactMultiChildUpdateTypes.js +1 -1
  84. package/lib/ReactNativeComponent.js +33 -36
  85. package/lib/ReactOwner.js +1 -1
  86. package/lib/ReactPerf.js +1 -1
  87. package/lib/ReactPropTransferer.js +1 -1
  88. package/lib/ReactPropTypeLocationNames.js +1 -1
  89. package/lib/ReactPropTypeLocations.js +1 -1
  90. package/lib/ReactPropTypes.js +5 -3
  91. package/lib/ReactPutListenerQueue.js +1 -1
  92. package/lib/ReactReconcileTransaction.js +1 -1
  93. package/lib/ReactReconciler.js +120 -0
  94. package/lib/ReactRef.js +40 -67
  95. package/lib/ReactRootIndex.js +1 -1
  96. package/lib/ReactServerRendering.js +1 -1
  97. package/lib/ReactServerRenderingTransaction.js +1 -1
  98. package/lib/ReactStateSetters.js +1 -1
  99. package/lib/ReactTestUtils.js +48 -7
  100. package/lib/ReactTransitionChildMapping.js +7 -3
  101. package/lib/ReactTransitionEvents.js +1 -1
  102. package/lib/ReactTransitionGroup.js +5 -5
  103. package/lib/ReactUpdateQueue.js +295 -0
  104. package/lib/ReactUpdates.js +11 -20
  105. package/lib/ReactWithAddons.js +3 -1
  106. package/lib/SVGDOMPropertyConfig.js +1 -1
  107. package/lib/SelectEventPlugin.js +1 -1
  108. package/lib/ServerReactRootIndex.js +1 -1
  109. package/lib/SimpleEventPlugin.js +3 -3
  110. package/lib/SyntheticClipboardEvent.js +1 -1
  111. package/lib/SyntheticCompositionEvent.js +1 -1
  112. package/lib/SyntheticDragEvent.js +1 -1
  113. package/lib/SyntheticEvent.js +1 -1
  114. package/lib/SyntheticFocusEvent.js +1 -1
  115. package/lib/SyntheticInputEvent.js +1 -1
  116. package/lib/SyntheticKeyboardEvent.js +1 -1
  117. package/lib/SyntheticMouseEvent.js +1 -1
  118. package/lib/SyntheticTouchEvent.js +1 -1
  119. package/lib/SyntheticUIEvent.js +1 -1
  120. package/lib/SyntheticWheelEvent.js +1 -1
  121. package/lib/Transaction.js +2 -2
  122. package/lib/ViewportMetrics.js +1 -1
  123. package/lib/accumulateInto.js +1 -1
  124. package/lib/adler32.js +1 -1
  125. package/lib/camelize.js +1 -1
  126. package/lib/camelizeStyleName.js +1 -1
  127. package/lib/cloneWithProps.js +4 -4
  128. package/lib/containsNode.js +1 -1
  129. package/lib/{createArrayFrom.js → createArrayFromMixed.js} +6 -6
  130. package/lib/createFullPageComponent.js +1 -1
  131. package/lib/createNodesFromMarkup.js +4 -4
  132. package/lib/cx.js +16 -1
  133. package/lib/dangerousStyleValue.js +1 -1
  134. package/lib/emptyFunction.js +1 -1
  135. package/lib/emptyObject.js +1 -1
  136. package/lib/{escapeTextForBrowser.js → escapeTextContentForBrowser.js} +4 -5
  137. package/lib/findDOMNode.js +19 -1
  138. package/lib/flattenChildren.js +1 -1
  139. package/lib/focusNode.js +1 -1
  140. package/lib/forEachAccumulated.js +1 -1
  141. package/lib/getActiveElement.js +1 -1
  142. package/lib/getEventCharCode.js +1 -1
  143. package/lib/getEventKey.js +1 -1
  144. package/lib/getEventModifierState.js +1 -1
  145. package/lib/getEventTarget.js +1 -1
  146. package/lib/getIteratorFn.js +1 -1
  147. package/lib/getMarkupWrap.js +1 -1
  148. package/lib/getNodeForCharacterOffset.js +1 -1
  149. package/lib/getReactRootElementInContainer.js +1 -1
  150. package/lib/getTextContentAccessor.js +1 -1
  151. package/lib/getUnboundedScrollPosition.js +1 -1
  152. package/lib/hyphenate.js +1 -1
  153. package/lib/hyphenateStyleName.js +1 -1
  154. package/lib/instantiateReactComponent.js +20 -20
  155. package/lib/invariant.js +1 -1
  156. package/lib/isEventSupported.js +1 -1
  157. package/lib/isNode.js +1 -1
  158. package/lib/isTextInputElement.js +1 -1
  159. package/lib/isTextNode.js +1 -1
  160. package/lib/joinClasses.js +1 -1
  161. package/lib/keyMirror.js +1 -1
  162. package/lib/keyOf.js +1 -1
  163. package/lib/mapObject.js +1 -1
  164. package/lib/memoizeStringOnly.js +1 -1
  165. package/lib/onlyChild.js +1 -1
  166. package/lib/performance.js +1 -1
  167. package/lib/performanceNow.js +1 -1
  168. package/lib/quoteAttributeValueForBrowser.js +26 -0
  169. package/lib/setInnerHTML.js +1 -1
  170. package/lib/setTextContent.js +40 -0
  171. package/lib/shallowEqual.js +1 -1
  172. package/lib/shouldUpdateReactComponent.js +32 -10
  173. package/lib/toArray.js +2 -2
  174. package/lib/traverseAllChildren.js +18 -4
  175. package/lib/update.js +1 -1
  176. package/lib/warning.js +12 -1
  177. package/package.json +1 -1
  178. package/lib/ReactComponentBase.js +0 -126
  179. package/lib/accumulate.js +0 -47
  180. package/lib/copyProperties.js +0 -56
  181. package/lib/merge.js +0 -34
  182. package/lib/mergeInto.js +0 -24
  183. package/lib/monitorCodeUse.js +0 -30
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2013-2014, Facebook, Inc.
2
+ * Copyright 2013-2015, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under the BSD-style license found in the
@@ -11,188 +11,121 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var ReactElementValidator = require("./ReactElementValidator");
15
- var ReactOwner = require("./ReactOwner");
16
- var ReactRef = require("./ReactRef");
14
+ var ReactUpdateQueue = require("./ReactUpdateQueue");
17
15
 
18
16
  var invariant = require("./invariant");
17
+ var warning = require("./warning");
19
18
 
20
- function attachRef(ref, component, owner) {
21
- if (ref instanceof ReactRef) {
22
- ReactRef.attachRef(ref, component);
23
- } else {
24
- ReactOwner.addComponentAsRefTo(component, ref, owner);
25
- }
26
- }
27
-
28
- function detachRef(ref, component, owner) {
29
- if (ref instanceof ReactRef) {
30
- ReactRef.detachRef(ref, component);
31
- } else {
32
- ReactOwner.removeComponentAsRefFrom(component, ref, owner);
33
- }
19
+ /**
20
+ * Base class helpers for the updating state of a component.
21
+ */
22
+ function ReactComponent(props, context) {
23
+ this.props = props;
24
+ this.context = context;
34
25
  }
35
26
 
36
27
  /**
37
- * Components are the basic units of composition in React.
28
+ * Sets a subset of the state. Always use this to mutate
29
+ * state. You should treat `this.state` as immutable.
38
30
  *
39
- * Every component accepts a set of keyed input parameters known as "props" that
40
- * are initialized by the constructor. Once a component is mounted, the props
41
- * can be mutated using `setProps` or `replaceProps`.
31
+ * There is no guarantee that `this.state` will be immediately updated, so
32
+ * accessing `this.state` after calling this method may return the old value.
42
33
  *
43
- * Every component is capable of the following operations:
34
+ * There is no guarantee that calls to `setState` will run synchronously,
35
+ * as they may eventually be batched together. You can provide an optional
36
+ * callback that will be executed when the call to setState is actually
37
+ * completed.
44
38
  *
45
- * `mountComponent`
46
- * Initializes the component, renders markup, and registers event listeners.
39
+ * When a function is provided to setState, it will be called at some point in
40
+ * the future (not synchronously). It will be called with the up to date
41
+ * component arguments (state, props, context). These values can be different
42
+ * from this.* because your function may be called after receiveProps but before
43
+ * shouldComponentUpdate, and this new state, props, and context will not yet be
44
+ * assigned to this.
47
45
  *
48
- * `receiveComponent`
49
- * Updates the rendered DOM nodes to match the given component.
46
+ * @param {object|function} partialState Next partial state or function to
47
+ * produce next partial state to be merged with current state.
48
+ * @param {?function} callback Called after state is updated.
49
+ * @final
50
+ * @protected
51
+ */
52
+ ReactComponent.prototype.setState = function(partialState, callback) {
53
+ ("production" !== process.env.NODE_ENV ? invariant(
54
+ typeof partialState === 'object' ||
55
+ typeof partialState === 'function' ||
56
+ partialState == null,
57
+ 'setState(...): takes an object of state variables to update or a ' +
58
+ 'function which returns an object of state variables.'
59
+ ) : invariant(typeof partialState === 'object' ||
60
+ typeof partialState === 'function' ||
61
+ partialState == null));
62
+ if ("production" !== process.env.NODE_ENV) {
63
+ ("production" !== process.env.NODE_ENV ? warning(
64
+ partialState != null,
65
+ 'setState(...): You passed an undefined or null state object; ' +
66
+ 'instead, use forceUpdate().'
67
+ ) : null);
68
+ }
69
+ ReactUpdateQueue.enqueueSetState(this, partialState);
70
+ if (callback) {
71
+ ReactUpdateQueue.enqueueCallback(this, callback);
72
+ }
73
+ };
74
+
75
+ /**
76
+ * Forces an update. This should only be invoked when it is known with
77
+ * certainty that we are **not** in a DOM transaction.
50
78
  *
51
- * `unmountComponent`
52
- * Releases any resources allocated by this component.
79
+ * You may want to call this when you know that some deeper aspect of the
80
+ * component's state has changed but `setState` was not called.
53
81
  *
54
- * Components can also be "owned" by other components. Being owned by another
55
- * component means being constructed by that component. This is different from
56
- * being the child of a component, which means having a DOM representation that
57
- * is a child of the DOM representation of that component.
82
+ * This will not invoke `shouldUpdateComponent`, but it will invoke
83
+ * `componentWillUpdate` and `componentDidUpdate`.
58
84
  *
59
- * @class ReactComponent
85
+ * @param {?function} callback Called after update is complete.
86
+ * @final
87
+ * @protected
60
88
  */
61
- var ReactComponent = {
62
-
63
- /**
64
- * Injected module that provides ability to mutate individual properties.
65
- * Injected into the base class because many different subclasses need access
66
- * to this.
67
- *
68
- * @internal
69
- */
70
- BackendIDOperations: null,
71
-
72
- /**
73
- * Base functionality for every ReactComponent constructor. Mixed into the
74
- * `ReactComponent` prototype, but exposed statically for easy access.
75
- *
76
- * @lends {ReactComponent.prototype}
77
- */
78
- Mixin: {
79
-
80
- /**
81
- * Base constructor for all React components.
82
- *
83
- * Subclasses that override this method should make sure to invoke
84
- * `ReactComponent.Mixin.construct.call(this, ...)`.
85
- *
86
- * @param {ReactElement} element
87
- * @internal
88
- */
89
- construct: function(element) {
90
- // We keep the old element and a reference to the pending element
91
- // to track updates.
92
- this._currentElement = element;
93
- // These two fields are used by the DOM and ART diffing algorithms
94
- // respectively. Instead of using expandos on components, we should be
95
- // storing the state needed by the diffing algorithms elsewhere.
96
- this._mountIndex = 0;
97
- this._mountImage = null;
98
- },
99
-
100
- /**
101
- * Initializes the component, renders markup, and registers event listeners.
102
- *
103
- * NOTE: This does not insert any nodes into the DOM.
104
- *
105
- * Subclasses that override this method should make sure to invoke
106
- * `ReactComponent.Mixin.mountComponent.call(this, ...)`.
107
- *
108
- * @param {string} rootID DOM ID of the root node.
109
- * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
110
- * @return {?string} Rendered markup to be inserted into the DOM.
111
- * @internal
112
- */
113
- mountComponent: function(rootID, transaction, context) {
114
- if ("production" !== process.env.NODE_ENV) {
115
- ReactElementValidator.checkAndWarnForMutatedProps(this._currentElement);
116
- }
117
-
118
- var ref = this._currentElement.ref;
119
- if (ref != null) {
120
- var owner = this._currentElement._owner;
121
- attachRef(ref, this, owner);
122
- }
123
- // Effectively: return '';
124
- },
125
-
126
- /**
127
- * Releases any resources allocated by `mountComponent`.
128
- *
129
- * NOTE: This does not remove any nodes from the DOM.
130
- *
131
- * Subclasses that override this method should make sure to invoke
132
- * `ReactComponent.Mixin.unmountComponent.call(this)`.
133
- *
134
- * @internal
135
- */
136
- unmountComponent: function() {
137
- var ref = this._currentElement.ref;
138
- if (ref != null) {
139
- detachRef(ref, this, this._currentElement._owner);
140
- }
141
- },
142
-
143
- /**
144
- * Updates the component's currently mounted representation.
145
- *
146
- * @param {ReactReconcileTransaction} transaction
147
- * @param {object} prevElement
148
- * @param {object} nextElement
149
- * @internal
150
- */
151
- updateComponent: function(transaction, prevElement, nextElement, context) {
152
- if ("production" !== process.env.NODE_ENV) {
153
- ReactElementValidator.checkAndWarnForMutatedProps(nextElement);
154
- }
155
-
156
- // If either the owner or a `ref` has changed, make sure the newest owner
157
- // has stored a reference to `this`, and the previous owner (if different)
158
- // has forgotten the reference to `this`. We use the element instead
159
- // of the public this.props because the post processing cannot determine
160
- // a ref. The ref conceptually lives on the element.
161
-
162
- // TODO: Should this even be possible? The owner cannot change because
163
- // it's forbidden by shouldUpdateReactComponent. The ref can change
164
- // if you swap the keys of but not the refs. Reconsider where this check
165
- // is made. It probably belongs where the key checking and
166
- // instantiateReactComponent is done.
89
+ ReactComponent.prototype.forceUpdate = function(callback) {
90
+ ReactUpdateQueue.enqueueForceUpdate(this);
91
+ if (callback) {
92
+ ReactUpdateQueue.enqueueCallback(this, callback);
93
+ }
94
+ };
167
95
 
168
- if (nextElement._owner !== prevElement._owner ||
169
- nextElement.ref !== prevElement.ref) {
170
- if (prevElement.ref != null) {
171
- detachRef(prevElement.ref, this, prevElement._owner);
172
- }
173
- // Correct, even if the owner is the same, and only the ref has changed.
174
- if (nextElement.ref != null) {
175
- attachRef(nextElement.ref, this, nextElement._owner);
96
+ /**
97
+ * Deprecated APIs. These APIs used to exist on classic React classes but since
98
+ * we would like to deprecate them, we're not going to move them over to this
99
+ * modern base class. Instead, we define a getter that warns if it's accessed.
100
+ */
101
+ if ("production" !== process.env.NODE_ENV) {
102
+ var deprecatedAPIs = {
103
+ getDOMNode: 'getDOMNode',
104
+ isMounted: 'isMounted',
105
+ replaceState: 'replaceState',
106
+ setProps: 'setProps'
107
+ };
108
+ var defineDeprecationWarning = function(methodName, displayName) {
109
+ try {
110
+ Object.defineProperty(ReactComponent.prototype, methodName, {
111
+ get: function() {
112
+ ("production" !== process.env.NODE_ENV ? warning(
113
+ false,
114
+ '%s(...) is deprecated in plain JavaScript React classes.',
115
+ displayName
116
+ ) : null);
117
+ return undefined;
176
118
  }
177
- }
178
- },
179
-
180
- /**
181
- * Get the publicly accessible representation of this component - i.e. what
182
- * is exposed by refs and returned by React.render. Can be null for
183
- * stateless components.
184
- *
185
- * @return {?ReactComponent} the actual sibling Component.
186
- * @internal
187
- */
188
- getPublicInstance: function() {
189
- ("production" !== process.env.NODE_ENV ? invariant(
190
- false,
191
- 'getPublicInstance should never be called on the base class. It must ' +
192
- 'be overridden.'
193
- ) : invariant(false));
119
+ });
120
+ } catch (x) {
121
+ // IE will fail on defineProperty (es5-shim/sham too)
122
+ }
123
+ };
124
+ for (var fnName in deprecatedAPIs) {
125
+ if (deprecatedAPIs.hasOwnProperty(fnName)) {
126
+ defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
194
127
  }
195
128
  }
196
- };
129
+ }
197
130
 
198
131
  module.exports = ReactComponent;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2013-2014, Facebook, Inc.
2
+ * Copyright 2013-2015, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under the BSD-style license found in the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2014, Facebook, Inc.
2
+ * Copyright 2014-2015, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under the BSD-style license found in the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2013-2014, Facebook, Inc.
2
+ * Copyright 2013-2015, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under the BSD-style license found in the
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2013-2014, Facebook, Inc.
2
+ * Copyright 2013-2015, Facebook, Inc.
3
3
  * All rights reserved.
4
4
  *
5
5
  * This source code is licensed under the BSD-style license found in the
@@ -11,21 +11,23 @@
11
11
 
12
12
  'use strict';
13
13
 
14
- var ReactComponent = require("./ReactComponent");
15
14
  var ReactComponentEnvironment = require("./ReactComponentEnvironment");
16
15
  var ReactContext = require("./ReactContext");
17
16
  var ReactCurrentOwner = require("./ReactCurrentOwner");
18
17
  var ReactElement = require("./ReactElement");
18
+ var ReactElementValidator = require("./ReactElementValidator");
19
19
  var ReactInstanceMap = require("./ReactInstanceMap");
20
+ var ReactLifeCycle = require("./ReactLifeCycle");
21
+ var ReactNativeComponent = require("./ReactNativeComponent");
20
22
  var ReactPerf = require("./ReactPerf");
21
23
  var ReactPropTypeLocations = require("./ReactPropTypeLocations");
22
24
  var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
25
+ var ReactReconciler = require("./ReactReconciler");
23
26
  var ReactUpdates = require("./ReactUpdates");
24
27
 
25
28
  var assign = require("./Object.assign");
26
29
  var emptyObject = require("./emptyObject");
27
30
  var invariant = require("./invariant");
28
- var keyMirror = require("./keyMirror");
29
31
  var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
30
32
  var warning = require("./warning");
31
33
 
@@ -40,63 +42,32 @@ function getDeclarationErrorAddendum(component) {
40
42
  return '';
41
43
  }
42
44
 
43
- function validateLifeCycleOnReplaceState(instance) {
44
- var compositeLifeCycleState = instance._compositeLifeCycleState;
45
- ("production" !== process.env.NODE_ENV ? invariant(
46
- ReactCurrentOwner.current == null,
47
- 'replaceState(...): Cannot update during an existing state transition ' +
48
- '(such as within `render`). Render methods should be a pure function ' +
49
- 'of props and state.'
50
- ) : invariant(ReactCurrentOwner.current == null));
51
- ("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
52
- 'replaceState(...): Cannot update while unmounting component. This ' +
53
- 'usually means you called setState() on an unmounted component.'
54
- ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
55
- }
56
-
57
45
  /**
58
- * `ReactCompositeComponent` maintains an auxiliary life cycle state in
59
- * `this._compositeLifeCycleState` (which can be null).
46
+ * ------------------ The Life-Cycle of a Composite Component ------------------
60
47
  *
61
- * This is different from the life cycle state maintained by `ReactComponent`.
62
- * The following diagram shows how the states overlap in
63
- * time. There are times when the CompositeLifeCycle is null - at those times it
64
- * is only meaningful to look at ComponentLifeCycle alone.
48
+ * - constructor: Initialization of state. The instance is now retained.
49
+ * - componentWillMount
50
+ * - render
51
+ * - [children's constructors]
52
+ * - [children's componentWillMount and render]
53
+ * - [children's componentDidMount]
54
+ * - componentDidMount
65
55
  *
66
- * Top Row: ReactComponent.ComponentLifeCycle
67
- * Low Row: ReactComponent.CompositeLifeCycle
56
+ * Update Phases:
57
+ * - componentWillReceiveProps (only called if parent updated)
58
+ * - shouldComponentUpdate
59
+ * - componentWillUpdate
60
+ * - render
61
+ * - [children's constructors or receive props phases]
62
+ * - componentDidUpdate
68
63
  *
69
- * +-------+---------------------------------+--------+
70
- * | UN | MOUNTED | UN |
71
- * |MOUNTED| | MOUNTED|
72
- * +-------+---------------------------------+--------+
73
- * | ^--------+ +-------+ +--------^ |
74
- * | | | | | | | |
75
- * | 0--|MOUNTING|-0-|RECEIVE|-0-| UN |--->0 |
76
- * | | | |PROPS | |MOUNTING| |
77
- * | | | | | | | |
78
- * | | | | | | | |
79
- * | +--------+ +-------+ +--------+ |
80
- * | | | |
81
- * +-------+---------------------------------+--------+
64
+ * - componentWillUnmount
65
+ * - [children's componentWillUnmount]
66
+ * - [children destroyed]
67
+ * - (destroyed): The instance is now blank, released by React and ready for GC.
68
+ *
69
+ * -----------------------------------------------------------------------------
82
70
  */
83
- var CompositeLifeCycle = keyMirror({
84
- /**
85
- * Components in the process of being mounted respond to state changes
86
- * differently.
87
- */
88
- MOUNTING: null,
89
- /**
90
- * Components in the process of being unmounted are guarded against state
91
- * changes.
92
- */
93
- UNMOUNTING: null,
94
- /**
95
- * Components that are mounted and receiving new props respond to state
96
- * changes differently.
97
- */
98
- RECEIVING_PROPS: null
99
- });
100
71
 
101
72
  /**
102
73
  * An incrementing ID assigned to each component when it is mounted. This is
@@ -109,8 +80,7 @@ var nextMountID = 1;
109
80
  /**
110
81
  * @lends {ReactCompositeComponent.prototype}
111
82
  */
112
- var ReactCompositeComponentMixin = assign({},
113
- ReactComponent.Mixin, {
83
+ var ReactCompositeComponentMixin = {
114
84
 
115
85
  /**
116
86
  * Base constructor for all composite component.
@@ -120,42 +90,26 @@ var ReactCompositeComponentMixin = assign({},
120
90
  * @internal
121
91
  */
122
92
  construct: function(element) {
93
+ this._currentElement = element;
123
94
  this._rootNodeID = null;
95
+ this._instance = null;
124
96
 
125
- this._instance.props = element.props;
126
- this._instance.state = null;
127
- this._instance.context = null;
128
- this._instance.refs = emptyObject;
129
-
97
+ // See ReactUpdateQueue
130
98
  this._pendingElement = null;
131
- this._pendingContext = null;
132
- this._pendingState = null;
99
+ this._pendingStateQueue = null;
100
+ this._pendingReplaceState = false;
133
101
  this._pendingForceUpdate = false;
134
- this._compositeLifeCycleState = null;
135
102
 
136
103
  this._renderedComponent = null;
137
104
 
138
- // Children can be either an array or more than one argument
139
- ReactComponent.Mixin.construct.apply(this, arguments);
140
-
141
105
  this._context = null;
142
106
  this._mountOrder = 0;
143
107
  this._isTopLevel = false;
144
108
 
145
- // See ReactUpdates.
109
+ // See ReactUpdates and ReactUpdateQueue.
146
110
  this._pendingCallbacks = null;
147
111
  },
148
112
 
149
- /**
150
- * Checks whether or not this composite component is mounted.
151
- * @return {boolean} True if mounted, false otherwise.
152
- * @protected
153
- * @final
154
- */
155
- isMounted: function() {
156
- return this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
157
- },
158
-
159
113
  /**
160
114
  * Initializes the component, renders markup, and registers event listeners.
161
115
  *
@@ -166,39 +120,35 @@ var ReactCompositeComponentMixin = assign({},
166
120
  * @internal
167
121
  */
168
122
  mountComponent: function(rootID, transaction, context) {
169
- ReactComponent.Mixin.mountComponent.call(
170
- this,
171
- rootID,
172
- transaction,
173
- context
174
- );
175
-
176
123
  this._context = context;
177
124
  this._mountOrder = nextMountID++;
178
125
  this._rootNodeID = rootID;
179
126
 
180
- var inst = this._instance;
127
+ var publicProps = this._processProps(this._currentElement.props);
128
+ var publicContext = this._processContext(this._currentElement._context);
129
+
130
+ var Component = ReactNativeComponent.getComponentClassForElement(
131
+ this._currentElement
132
+ );
133
+
134
+ // Initialize the public class
135
+ var inst = new Component(publicProps, publicContext);
136
+ // These should be set up in the constructor, but as a convenience for
137
+ // simpler class abstractions, we set them up after the fact.
138
+ inst.props = publicProps;
139
+ inst.context = publicContext;
140
+ inst.refs = emptyObject;
141
+
142
+ this._instance = inst;
181
143
 
182
144
  // Store a reference from the instance back to the internal representation
183
145
  ReactInstanceMap.set(inst, this);
184
146
 
185
- this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
186
-
187
- inst.context = this._processContext(this._currentElement._context);
188
147
  if ("production" !== process.env.NODE_ENV) {
189
148
  this._warnIfContextsDiffer(this._currentElement._context, context);
190
149
  }
191
- inst.props = this._processProps(this._currentElement.props);
192
150
 
193
- var initialState = inst.getInitialState ? inst.getInitialState() : null;
194
151
  if ("production" !== process.env.NODE_ENV) {
195
- // We allow auto-mocks to proceed as if they're returning null.
196
- if (typeof initialState === 'undefined' &&
197
- inst.getInitialState._isMockFunction) {
198
- // This is probably bad practice. Consider warning here and
199
- // deprecating this convenience.
200
- initialState = null;
201
- }
202
152
  // Since plain JS classes are defined without any special initialization
203
153
  // logic, we can not catch common errors early. Therefore, we have to
204
154
  // catch them here, at initialization time, instead.
@@ -210,14 +160,6 @@ var ReactCompositeComponentMixin = assign({},
210
160
  'Did you mean to define a state property instead?',
211
161
  this.getName() || 'a component'
212
162
  ) : null);
213
- ("production" !== process.env.NODE_ENV ? warning(
214
- !inst.componentWillMount ||
215
- inst.componentWillMount.isReactClassApproved,
216
- 'componentWillMount was defined on %s, a plain JavaScript class. ' +
217
- 'This is only supported for classes created using React.createClass. ' +
218
- 'Did you mean to define a constructor instead?',
219
- this.getName() || 'a component'
220
- ) : null);
221
163
  ("production" !== process.env.NODE_ENV ? warning(
222
164
  !inst.propTypes,
223
165
  'propTypes was defined as an instance property on %s. Use a static ' +
@@ -239,35 +181,47 @@ var ReactCompositeComponentMixin = assign({},
239
181
  (this.getName() || 'A component')
240
182
  ) : null);
241
183
  }
184
+
185
+ var initialState = inst.state;
186
+ if (initialState === undefined) {
187
+ inst.state = initialState = null;
188
+ }
242
189
  ("production" !== process.env.NODE_ENV ? invariant(
243
190
  typeof initialState === 'object' && !Array.isArray(initialState),
244
- '%s.getInitialState(): must return an object or null',
191
+ '%s.state: must be set to an object or null',
245
192
  this.getName() || 'ReactCompositeComponent'
246
193
  ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
247
- inst.state = initialState;
248
194
 
249
- this._pendingState = null;
195
+ this._pendingStateQueue = null;
196
+ this._pendingReplaceState = false;
250
197
  this._pendingForceUpdate = false;
251
198
 
252
- if (inst.componentWillMount) {
253
- inst.componentWillMount();
254
- // When mounting, calls to `setState` by `componentWillMount` will set
255
- // `this._pendingState` without triggering a re-render.
256
- if (this._pendingState) {
257
- inst.state = this._pendingState;
258
- this._pendingState = null;
199
+ var renderedElement;
200
+
201
+ var previouslyMounting = ReactLifeCycle.currentlyMountingInstance;
202
+ ReactLifeCycle.currentlyMountingInstance = this;
203
+ try {
204
+ if (inst.componentWillMount) {
205
+ inst.componentWillMount();
206
+ // When mounting, calls to `setState` by `componentWillMount` will set
207
+ // `this._pendingStateQueue` without triggering a re-render.
208
+ if (this._pendingStateQueue) {
209
+ inst.state = this._processPendingState(inst.props, inst.context);
210
+ }
259
211
  }
212
+
213
+ renderedElement = this._renderValidatedComponent();
214
+ } finally {
215
+ ReactLifeCycle.currentlyMountingInstance = previouslyMounting;
260
216
  }
261
217
 
262
- var renderedElement = this._renderValidatedComponent();
263
218
  this._renderedComponent = this._instantiateReactComponent(
264
219
  renderedElement,
265
220
  this._currentElement.type // The wrapping type
266
221
  );
267
222
 
268
- // Done with mounting, `setState` will now trigger UI changes.
269
- this._compositeLifeCycleState = null;
270
- var markup = this._renderedComponent.mountComponent(
223
+ var markup = ReactReconciler.mountComponent(
224
+ this._renderedComponent,
271
225
  rootID,
272
226
  transaction,
273
227
  this._processChildContext(context)
@@ -275,6 +229,7 @@ var ReactCompositeComponentMixin = assign({},
275
229
  if (inst.componentDidMount) {
276
230
  transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
277
231
  }
232
+
278
233
  return markup;
279
234
  },
280
235
 
@@ -287,25 +242,28 @@ var ReactCompositeComponentMixin = assign({},
287
242
  unmountComponent: function() {
288
243
  var inst = this._instance;
289
244
 
290
- this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
291
245
  if (inst.componentWillUnmount) {
292
- inst.componentWillUnmount();
246
+ var previouslyUnmounting = ReactLifeCycle.currentlyUnmountingInstance;
247
+ ReactLifeCycle.currentlyUnmountingInstance = this;
248
+ try {
249
+ inst.componentWillUnmount();
250
+ } finally {
251
+ ReactLifeCycle.currentlyUnmountingInstance = previouslyUnmounting;
252
+ }
293
253
  }
294
- this._compositeLifeCycleState = null;
295
254
 
296
- this._renderedComponent.unmountComponent();
255
+ ReactReconciler.unmountComponent(this._renderedComponent);
297
256
  this._renderedComponent = null;
298
257
 
299
258
  // Reset pending fields
300
- this._pendingState = null;
259
+ this._pendingStateQueue = null;
260
+ this._pendingReplaceState = false;
301
261
  this._pendingForceUpdate = false;
302
262
  this._pendingCallbacks = null;
303
263
  this._pendingElement = null;
304
264
 
305
- ReactComponent.Mixin.unmountComponent.call(this);
306
-
307
- ReactComponentEnvironment.unmountIDFromEnvironment(this._rootNodeID);
308
-
265
+ // These fields do not really need to be reset since this object is no
266
+ // longer accessible.
309
267
  this._context = null;
310
268
  this._rootNodeID = null;
311
269
 
@@ -321,50 +279,6 @@ var ReactCompositeComponentMixin = assign({},
321
279
  // TODO: inst.context = null;
322
280
  },
323
281
 
324
- /**
325
- * Sets a subset of the props.
326
- *
327
- * @param {object} partialProps Subset of the next props.
328
- * @param {?function} callback Called after props are updated.
329
- * @final
330
- * @public
331
- */
332
- setProps: function(partialProps, callback) {
333
- // Merge with the pending element if it exists, otherwise with existing
334
- // element props.
335
- var element = this._pendingElement || this._currentElement;
336
- this.replaceProps(
337
- assign({}, element.props, partialProps),
338
- callback
339
- );
340
- },
341
-
342
- /**
343
- * Replaces all of the props.
344
- *
345
- * @param {object} props New props.
346
- * @param {?function} callback Called after props are updated.
347
- * @final
348
- * @public
349
- */
350
- replaceProps: function(props, callback) {
351
- ("production" !== process.env.NODE_ENV ? invariant(
352
- this._isTopLevel,
353
- 'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
354
- 'component with a parent. This is an anti-pattern since props will ' +
355
- 'get reactively updated when rendered. Instead, change the owner\'s ' +
356
- '`render` method to pass the correct value as props to the component ' +
357
- 'where it is created.'
358
- ) : invariant(this._isTopLevel));
359
- // This is a deoptimized path. We optimize for always having an element.
360
- // This creates an extra internal element.
361
- this._pendingElement = ReactElement.cloneAndReplaceProps(
362
- this._pendingElement || this._currentElement,
363
- props
364
- );
365
- ReactUpdates.enqueueUpdate(this, callback);
366
- },
367
-
368
282
  /**
369
283
  * Schedule a partial update to the props. Only used for internal testing.
370
284
  *
@@ -384,89 +298,22 @@ var ReactCompositeComponentMixin = assign({},
384
298
  ReactUpdates.enqueueUpdate(this, callback);
385
299
  },
386
300
 
387
- /**
388
- * Sets a subset of the state. This only exists because _pendingState is
389
- * internal. This provides a merging strategy that is not available to deep
390
- * properties which is confusing. TODO: Expose pendingState or don't use it
391
- * during the merge.
392
- *
393
- * @param {object} partialState Next partial state to be merged with state.
394
- * @param {?function} callback Called after state is updated.
395
- * @final
396
- * @protected
397
- */
398
- setState: function(partialState, callback) {
399
- // Merge with `_pendingState` if it exists, otherwise with existing state.
400
- this.replaceState(
401
- assign({}, this._pendingState || this._instance.state, partialState),
402
- callback
403
- );
404
- },
405
-
406
- /**
407
- * Replaces all of the state. Always use this or `setState` to mutate state.
408
- * You should treat `this.state` as immutable.
409
- *
410
- * There is no guarantee that `this.state` will be immediately updated, so
411
- * accessing `this.state` after calling this method may return the old value.
412
- *
413
- * @param {object} completeState Next state.
414
- * @param {?function} callback Called after state is updated.
415
- * @final
416
- * @protected
417
- */
418
- replaceState: function(completeState, callback) {
419
- validateLifeCycleOnReplaceState(this);
420
- this._pendingState = completeState;
421
- if (this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING) {
422
- // If we're in a componentWillMount handler, don't enqueue a rerender
423
- // because ReactUpdates assumes we're in a browser context (which is wrong
424
- // for server rendering) and we're about to do a render anyway.
425
- // TODO: The callback here is ignored when setState is called from
426
- // componentWillMount. Either fix it or disallow doing so completely in
427
- // favor of getInitialState.
428
- ReactUpdates.enqueueUpdate(this, callback);
429
- }
430
- },
431
-
432
- /**
433
- * Forces an update. This should only be invoked when it is known with
434
- * certainty that we are **not** in a DOM transaction.
435
- *
436
- * You may want to call this when you know that some deeper aspect of the
437
- * component's state has changed but `setState` was not called.
438
- *
439
- * This will not invoke `shouldUpdateComponent`, but it will invoke
440
- * `componentWillUpdate` and `componentDidUpdate`.
441
- *
442
- * @param {?function} callback Called after update is complete.isM
443
- * @final
444
- * @protected
445
- */
446
- forceUpdate: function(callback) {
447
- var compositeLifeCycleState = this._compositeLifeCycleState;
448
- ("production" !== process.env.NODE_ENV ? invariant(
449
- compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
450
- compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
451
- 'forceUpdate(...): Cannot force an update while unmounting component ' +
452
- 'or during an existing state transition (such as within `render`).'
453
- ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
454
- compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
455
- this._pendingForceUpdate = true;
456
- ReactUpdates.enqueueUpdate(this, callback);
457
- },
458
-
459
301
  /**
460
302
  * Filters the context object to only contain keys specified in
461
- * `contextTypes`, and asserts that they are valid.
303
+ * `contextTypes`
462
304
  *
463
305
  * @param {object} context
464
306
  * @return {?object}
465
307
  * @private
466
308
  */
467
- _processContext: function(context) {
309
+ _maskContext: function(context) {
468
310
  var maskedContext = null;
469
- var contextTypes = this._instance.constructor.contextTypes;
311
+ // This really should be getting the component class for the element,
312
+ // but we know that we're not going to need it for built-ins.
313
+ if (typeof this._currentElement.type === 'string') {
314
+ return emptyObject;
315
+ }
316
+ var contextTypes = this._currentElement.type.contextTypes;
470
317
  if (!contextTypes) {
471
318
  return emptyObject;
472
319
  }
@@ -474,12 +321,30 @@ var ReactCompositeComponentMixin = assign({},
474
321
  for (var contextName in contextTypes) {
475
322
  maskedContext[contextName] = context[contextName];
476
323
  }
324
+ return maskedContext;
325
+ },
326
+
327
+ /**
328
+ * Filters the context object to only contain keys specified in
329
+ * `contextTypes`, and asserts that they are valid.
330
+ *
331
+ * @param {object} context
332
+ * @return {?object}
333
+ * @private
334
+ */
335
+ _processContext: function(context) {
336
+ var maskedContext = this._maskContext(context);
477
337
  if ("production" !== process.env.NODE_ENV) {
478
- this._checkPropTypes(
479
- contextTypes,
480
- maskedContext,
481
- ReactPropTypeLocations.context
338
+ var Component = ReactNativeComponent.getComponentClassForElement(
339
+ this._currentElement
482
340
  );
341
+ if (Component.contextTypes) {
342
+ this._checkPropTypes(
343
+ Component.contextTypes,
344
+ maskedContext,
345
+ ReactPropTypeLocations.context
346
+ );
347
+ }
483
348
  }
484
349
  return maskedContext;
485
350
  },
@@ -530,10 +395,15 @@ var ReactCompositeComponentMixin = assign({},
530
395
  */
531
396
  _processProps: function(newProps) {
532
397
  if ("production" !== process.env.NODE_ENV) {
533
- var inst = this._instance;
534
- var propTypes = inst.constructor.propTypes;
535
- if (propTypes) {
536
- this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop);
398
+ var Component = ReactNativeComponent.getComponentClassForElement(
399
+ this._currentElement
400
+ );
401
+ if (Component.propTypes) {
402
+ this._checkPropTypes(
403
+ Component.propTypes,
404
+ newProps,
405
+ ReactPropTypeLocations.prop
406
+ );
537
407
  }
538
408
  }
539
409
  return newProps;
@@ -574,74 +444,75 @@ var ReactCompositeComponentMixin = assign({},
574
444
  // React.render calls, so I'm abstracting it away into
575
445
  // a function to minimize refactoring in the future
576
446
  var addendum = getDeclarationErrorAddendum(this);
577
- ("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null);
447
+
448
+ if (location === ReactPropTypeLocations.prop) {
449
+ // Preface gives us something to blacklist in warning module
450
+ ("production" !== process.env.NODE_ENV ? warning(
451
+ false,
452
+ 'Failed Composite propType: %s%s',
453
+ error.message,
454
+ addendum
455
+ ) : null);
456
+ } else {
457
+ ("production" !== process.env.NODE_ENV ? warning(
458
+ false,
459
+ 'Failed Context Types: %s%s',
460
+ error.message,
461
+ addendum
462
+ ) : null);
463
+ }
578
464
  }
579
465
  }
580
466
  }
581
467
  },
582
468
 
583
- receiveComponent: function(nextElement, transaction, context) {
584
- if (nextElement === this._currentElement &&
585
- nextElement._owner != null) {
586
- // Since elements are immutable after the owner is rendered,
587
- // we can do a cheap identity compare here to determine if this is a
588
- // superfluous reconcile. It's possible for state to be mutable but such
589
- // change should trigger an update of the owner which would recreate
590
- // the element. We explicitly check for the existence of an owner since
591
- // it's possible for an element created outside a composite to be
592
- // deeply mutated and reused.
593
- return;
594
- }
469
+ receiveComponent: function(nextElement, transaction, nextContext) {
470
+ var prevElement = this._currentElement;
471
+ var prevContext = this._context;
595
472
 
596
- this._pendingElement = nextElement;
597
- this._pendingContext = context;
598
- this.performUpdateIfNecessary(transaction);
473
+ this._pendingElement = null;
474
+
475
+ this.updateComponent(
476
+ transaction,
477
+ prevElement,
478
+ nextElement,
479
+ prevContext,
480
+ nextContext
481
+ );
599
482
  },
600
483
 
601
484
  /**
602
- * If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate`
485
+ * If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`
603
486
  * is set, update the component.
604
487
  *
605
488
  * @param {ReactReconcileTransaction} transaction
606
489
  * @internal
607
490
  */
608
491
  performUpdateIfNecessary: function(transaction) {
609
- var compositeLifeCycleState = this._compositeLifeCycleState;
610
- // Do not trigger a state transition if we are in the middle of mounting or
611
- // receiving props because both of those will already be doing this.
612
- if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
613
- compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
614
- return;
615
- }
616
-
617
- if (this._pendingElement == null &&
618
- this._pendingState == null &&
619
- this._pendingContext == null &&
620
- !this._pendingForceUpdate) {
621
- return;
622
- }
623
-
624
- var prevElement = this._currentElement;
625
- var nextElement = prevElement;
626
492
  if (this._pendingElement != null) {
627
- nextElement = this._pendingElement;
628
- this._pendingElement = null;
493
+ ReactReconciler.receiveComponent(
494
+ this,
495
+ this._pendingElement || this._currentElement,
496
+ transaction,
497
+ this._context
498
+ );
629
499
  }
630
500
 
631
- var prevContext = this._context;
632
- var nextContext = prevContext;
633
- if (this._pendingContext != null) {
634
- nextContext = this._pendingContext;
635
- this._pendingContext = null;
636
- }
501
+ if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
502
+ if ("production" !== process.env.NODE_ENV) {
503
+ ReactElementValidator.checkAndWarnForMutatedProps(
504
+ this._currentElement
505
+ );
506
+ }
637
507
 
638
- this.updateComponent(
639
- transaction,
640
- prevElement,
641
- nextElement,
642
- prevContext,
643
- nextContext
644
- );
508
+ this.updateComponent(
509
+ transaction,
510
+ this._currentElement,
511
+ this._currentElement,
512
+ this._context,
513
+ this._context
514
+ );
515
+ }
645
516
  },
646
517
 
647
518
  /**
@@ -649,35 +520,22 @@ var ReactCompositeComponentMixin = assign({},
649
520
  * TODO: Remove this check when owner-context is removed
650
521
  */
651
522
  _warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) {
652
- var ownerKeys = Object.keys(ownerBasedContext).sort();
523
+ ownerBasedContext = this._maskContext(ownerBasedContext);
524
+ parentBasedContext = this._maskContext(parentBasedContext);
653
525
  var parentKeys = Object.keys(parentBasedContext).sort();
654
526
  var displayName = this.getName() || 'ReactCompositeComponent';
655
- if (ownerKeys.length !== parentKeys.length ||
656
- ownerKeys.toString() !== parentKeys.toString()) {
527
+ for (var i = 0; i < parentKeys.length; i++) {
528
+ var key = parentKeys[i];
657
529
  ("production" !== process.env.NODE_ENV ? warning(
658
- ownerKeys.length === parentKeys.length &&
659
- ownerKeys.toString() === parentKeys.toString(),
660
- 'owner based context (keys: %s) does not equal parent based ' +
661
- 'context (keys: %s) while mounting %s ' +
530
+ ownerBasedContext[key] === parentBasedContext[key],
531
+ 'owner-based and parent-based contexts differ ' +
532
+ '(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
662
533
  '(see: http://fb.me/react-context-by-parent)',
663
- Object.keys(ownerBasedContext),
664
- Object.keys(parentBasedContext),
534
+ ownerBasedContext[key],
535
+ parentBasedContext[key],
536
+ key,
665
537
  displayName
666
538
  ) : null);
667
- } else {
668
- for (var i = 0; i < parentKeys.length; i++) {
669
- var key = parentKeys[i];
670
- ("production" !== process.env.NODE_ENV ? warning(
671
- ownerBasedContext[key] === parentBasedContext[key],
672
- 'owner-based and parent-based contexts differ ' +
673
- '(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
674
- '(see: http://fb.me/react-context-by-parent)',
675
- ownerBasedContext[key],
676
- parentBasedContext[key],
677
- key,
678
- displayName
679
- ) : null);
680
- }
681
539
  }
682
540
  },
683
541
 
@@ -703,22 +561,11 @@ var ReactCompositeComponentMixin = assign({},
703
561
  prevUnmaskedContext,
704
562
  nextUnmaskedContext
705
563
  ) {
706
- // Update refs regardless of what shouldComponentUpdate returns
707
- ReactComponent.Mixin.updateComponent.call(
708
- this,
709
- transaction,
710
- prevParentElement,
711
- nextParentElement,
712
- prevUnmaskedContext,
713
- nextUnmaskedContext
714
- );
715
-
716
564
  var inst = this._instance;
717
565
 
718
- var prevContext = inst.context;
719
- var prevProps = inst.props;
720
- var nextContext = prevContext;
721
- var nextProps = prevProps;
566
+ var nextContext = inst.context;
567
+ var nextProps = inst.props;
568
+
722
569
  // Distinguish between a props update versus a simple state update
723
570
  if (prevParentElement !== nextParentElement) {
724
571
  nextContext = this._processContext(nextParentElement._context);
@@ -726,20 +573,23 @@ var ReactCompositeComponentMixin = assign({},
726
573
 
727
574
  if ("production" !== process.env.NODE_ENV) {
728
575
  if (nextUnmaskedContext != null) {
729
- this._warnIfContextsDiffer(nextParentElement._context, nextUnmaskedContext);
576
+ this._warnIfContextsDiffer(
577
+ nextParentElement._context,
578
+ nextUnmaskedContext
579
+ );
730
580
  }
731
581
  }
732
582
 
733
- this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
583
+ // An update here will schedule an update but immediately set
584
+ // _pendingStateQueue which will ensure that any state updates gets
585
+ // immediately reconciled instead of waiting for the next batch.
586
+
734
587
  if (inst.componentWillReceiveProps) {
735
588
  inst.componentWillReceiveProps(nextProps, nextContext);
736
589
  }
737
590
  }
738
591
 
739
- this._compositeLifeCycleState = null;
740
-
741
- var nextState = this._pendingState || inst.state;
742
- this._pendingState = null;
592
+ var nextState = this._processPendingState(nextProps, nextContext);
743
593
 
744
594
  var shouldUpdate =
745
595
  this._pendingForceUpdate ||
@@ -747,16 +597,26 @@ var ReactCompositeComponentMixin = assign({},
747
597
  inst.shouldComponentUpdate(nextProps, nextState, nextContext);
748
598
 
749
599
  if ("production" !== process.env.NODE_ENV) {
750
- if (typeof shouldUpdate === 'undefined') {
751
- console.warn(
752
- (this.getName() || 'ReactCompositeComponent') +
753
- '.shouldComponentUpdate(): Returned undefined instead of a ' +
754
- 'boolean value. Make sure to return true or false.'
755
- );
756
- }
600
+ ("production" !== process.env.NODE_ENV ? warning(
601
+ typeof shouldUpdate !== 'undefined',
602
+ '%s.shouldComponentUpdate(): Returned undefined instead of a ' +
603
+ 'boolean value. Make sure to return true or false.',
604
+ this.getName() || 'ReactCompositeComponent'
605
+ ) : null);
757
606
  }
758
607
 
759
- if (!shouldUpdate) {
608
+ if (shouldUpdate) {
609
+ this._pendingForceUpdate = false;
610
+ // Will set `this.props`, `this.state` and `this.context`.
611
+ this._performComponentUpdate(
612
+ nextParentElement,
613
+ nextProps,
614
+ nextState,
615
+ nextContext,
616
+ transaction,
617
+ nextUnmaskedContext
618
+ );
619
+ } else {
760
620
  // If it's determined that a component should not update, we still want
761
621
  // to set props and state but we shortcut the rest of the update.
762
622
  this._currentElement = nextParentElement;
@@ -764,19 +624,32 @@ var ReactCompositeComponentMixin = assign({},
764
624
  inst.props = nextProps;
765
625
  inst.state = nextState;
766
626
  inst.context = nextContext;
767
- return;
768
627
  }
628
+ },
769
629
 
770
- this._pendingForceUpdate = false;
771
- // Will set `this.props`, `this.state` and `this.context`.
772
- this._performComponentUpdate(
773
- nextParentElement,
774
- nextProps,
775
- nextState,
776
- nextContext,
777
- transaction,
778
- nextUnmaskedContext
779
- );
630
+ _processPendingState: function(props, context) {
631
+ var inst = this._instance;
632
+ var queue = this._pendingStateQueue;
633
+ var replace = this._pendingReplaceState;
634
+ this._pendingReplaceState = false;
635
+ this._pendingStateQueue = null;
636
+
637
+ if (!queue) {
638
+ return inst.state;
639
+ }
640
+
641
+ var nextState = assign({}, replace ? queue[0] : inst.state);
642
+ for (var i = replace ? 1 : 0; i < queue.length; i++) {
643
+ var partial = queue[i];
644
+ assign(
645
+ nextState,
646
+ typeof partial === 'function' ?
647
+ partial.call(inst, nextState, props, context) :
648
+ partial
649
+ );
650
+ }
651
+
652
+ return nextState;
780
653
  },
781
654
 
782
655
  /**
@@ -836,7 +709,8 @@ var ReactCompositeComponentMixin = assign({},
836
709
  var prevRenderedElement = prevComponentInstance._currentElement;
837
710
  var nextRenderedElement = this._renderValidatedComponent();
838
711
  if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
839
- prevComponentInstance.receiveComponent(
712
+ ReactReconciler.receiveComponent(
713
+ prevComponentInstance,
840
714
  nextRenderedElement,
841
715
  transaction,
842
716
  this._processChildContext(context)
@@ -845,26 +719,34 @@ var ReactCompositeComponentMixin = assign({},
845
719
  // These two IDs are actually the same! But nothing should rely on that.
846
720
  var thisID = this._rootNodeID;
847
721
  var prevComponentID = prevComponentInstance._rootNodeID;
848
- prevComponentInstance.unmountComponent();
722
+ ReactReconciler.unmountComponent(prevComponentInstance);
849
723
 
850
724
  this._renderedComponent = this._instantiateReactComponent(
851
725
  nextRenderedElement,
852
726
  this._currentElement.type
853
727
  );
854
- var nextMarkup = this._renderedComponent.mountComponent(
728
+ var nextMarkup = ReactReconciler.mountComponent(
729
+ this._renderedComponent,
855
730
  thisID,
856
731
  transaction,
857
732
  context
858
733
  );
859
- ReactComponentEnvironment.replaceNodeWithMarkupByID(
860
- prevComponentID,
861
- nextMarkup
862
- );
734
+ this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
863
735
  }
864
736
  },
865
737
 
866
738
  /**
867
- * @private
739
+ * @protected
740
+ */
741
+ _replaceNodeWithMarkupByID: function(prevComponentID, nextMarkup) {
742
+ ReactComponentEnvironment.replaceNodeWithMarkupByID(
743
+ prevComponentID,
744
+ nextMarkup
745
+ );
746
+ },
747
+
748
+ /**
749
+ * @protected
868
750
  */
869
751
  _renderValidatedComponentWithoutOwnerOrContext: function() {
870
752
  var inst = this._instance;
@@ -892,7 +774,6 @@ var ReactCompositeComponentMixin = assign({},
892
774
  this._currentElement._context
893
775
  );
894
776
  ReactCurrentOwner.current = this;
895
- var inst = this._instance;
896
777
  try {
897
778
  renderedComponent =
898
779
  this._renderValidatedComponentWithoutOwnerOrContext();
@@ -947,7 +828,7 @@ var ReactCompositeComponentMixin = assign({},
947
828
  */
948
829
  getName: function() {
949
830
  var type = this._currentElement.type;
950
- var constructor = this._instance.constructor;
831
+ var constructor = this._instance && this._instance.constructor;
951
832
  return (
952
833
  type.displayName || (constructor && constructor.displayName) ||
953
834
  type.name || (constructor && constructor.name) ||
@@ -970,103 +851,7 @@ var ReactCompositeComponentMixin = assign({},
970
851
  // Stub
971
852
  _instantiateReactComponent: null
972
853
 
973
- });
974
-
975
- var ShallowMixin = assign({},
976
- ReactCompositeComponentMixin, {
977
-
978
- /**
979
- * Initializes the component, renders markup, and registers event listeners.
980
- *
981
- * @param {string} rootID DOM ID of the root node.
982
- * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
983
- * @return {ReactElement} Shallow rendering of the component.
984
- * @final
985
- * @internal
986
- */
987
- mountComponent: function(rootID, transaction, context) {
988
- ReactComponent.Mixin.mountComponent.call(
989
- this,
990
- rootID,
991
- transaction,
992
- context
993
- );
994
-
995
- var inst = this._instance;
996
-
997
- // Store a reference from the instance back to the internal representation
998
- ReactInstanceMap.set(inst, this);
999
-
1000
- this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
1001
-
1002
- // No context for shallow-mounted components.
1003
- inst.props = this._processProps(this._currentElement.props);
1004
-
1005
- var initialState = inst.getInitialState ? inst.getInitialState() : null;
1006
- if ("production" !== process.env.NODE_ENV) {
1007
- // We allow auto-mocks to proceed as if they're returning null.
1008
- if (typeof initialState === 'undefined' &&
1009
- inst.getInitialState._isMockFunction) {
1010
- // This is probably bad practice. Consider warning here and
1011
- // deprecating this convenience.
1012
- initialState = null;
1013
- }
1014
- }
1015
- ("production" !== process.env.NODE_ENV ? invariant(
1016
- typeof initialState === 'object' && !Array.isArray(initialState),
1017
- '%s.getInitialState(): must return an object or null',
1018
- this.getName() || 'ReactCompositeComponent'
1019
- ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
1020
- inst.state = initialState;
1021
-
1022
- this._pendingState = null;
1023
- this._pendingForceUpdate = false;
1024
-
1025
- if (inst.componentWillMount) {
1026
- inst.componentWillMount();
1027
- // When mounting, calls to `setState` by `componentWillMount` will set
1028
- // `this._pendingState` without triggering a re-render.
1029
- if (this._pendingState) {
1030
- inst.state = this._pendingState;
1031
- this._pendingState = null;
1032
- }
1033
- }
1034
-
1035
- // No recursive call to instantiateReactComponent for shallow rendering.
1036
- this._renderedComponent =
1037
- this._renderValidatedComponentWithoutOwnerOrContext();
1038
-
1039
- // Done with mounting, `setState` will now trigger UI changes.
1040
- this._compositeLifeCycleState = null;
1041
-
1042
- // No call to this._renderedComponent.mountComponent for shallow
1043
- // rendering.
1044
-
1045
- if (inst.componentDidMount) {
1046
- transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
1047
- }
1048
-
1049
- return this._renderedComponent;
1050
- },
1051
-
1052
- /**
1053
- * Call the component's `render` method and update the DOM accordingly.
1054
- *
1055
- * @param {ReactReconcileTransaction} transaction
1056
- * @internal
1057
- */
1058
- _updateRenderedComponent: function(transaction) {
1059
- var prevComponentInstance = this._renderedComponent;
1060
- var prevRenderedElement = prevComponentInstance._currentElement;
1061
- // Use the without-owner-or-context variant of _rVC below:
1062
- var nextRenderedElement =
1063
- this._renderValidatedComponentWithoutOwnerOrContext();
1064
- // This is a noop in shallow render
1065
- shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement);
1066
- this._renderedComponent = nextRenderedElement;
1067
- }
1068
-
1069
- });
854
+ };
1070
855
 
1071
856
  ReactPerf.measureMethods(
1072
857
  ReactCompositeComponentMixin,
@@ -1080,11 +865,7 @@ ReactPerf.measureMethods(
1080
865
 
1081
866
  var ReactCompositeComponent = {
1082
867
 
1083
- LifeCycle: CompositeLifeCycle,
1084
-
1085
- Mixin: ReactCompositeComponentMixin,
1086
-
1087
- ShallowMixin: ShallowMixin
868
+ Mixin: ReactCompositeComponentMixin
1088
869
 
1089
870
  };
1090
871