react 0.6.2 → 0.8.0

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 (204) hide show
  1. package/README.md +15 -217
  2. package/ReactJSErrors.js +40 -0
  3. package/addons.js +4 -0
  4. package/lib/$.js +46 -0
  5. package/lib/CSSCore.js +114 -0
  6. package/lib/CSSProperty.js +90 -0
  7. package/lib/CSSPropertyOperations.js +97 -0
  8. package/lib/CallbackRegistry.js +91 -0
  9. package/lib/ChangeEventPlugin.js +365 -0
  10. package/lib/CompositionEventPlugin.js +212 -0
  11. package/lib/DOMChildrenOperations.js +135 -0
  12. package/lib/DOMProperty.js +266 -0
  13. package/lib/DOMPropertyOperations.js +168 -0
  14. package/lib/Danger.js +186 -0
  15. package/lib/DefaultDOMPropertyConfig.js +187 -0
  16. package/lib/DefaultEventPluginOrder.js +44 -0
  17. package/lib/EnterLeaveEventPlugin.js +112 -0
  18. package/lib/EventConstants.js +73 -0
  19. package/lib/EventListener.js +61 -0
  20. package/lib/EventPluginHub.js +190 -0
  21. package/lib/EventPluginRegistry.js +237 -0
  22. package/lib/EventPluginUtils.js +185 -0
  23. package/lib/EventPropagators.js +179 -0
  24. package/lib/ExecutionEnvironment.js +41 -0
  25. package/lib/LinkedStateMixin.js +46 -0
  26. package/lib/LinkedValueMixin.js +68 -0
  27. package/lib/MobileSafariClickEventPlugin.js +63 -0
  28. package/lib/PooledClass.js +113 -0
  29. package/lib/React.js +71 -0
  30. package/lib/ReactChildren.js +132 -0
  31. package/lib/ReactComponent.js +515 -0
  32. package/lib/ReactComponentBrowserEnvironment.js +140 -0
  33. package/lib/ReactComponentEnvironment.js +24 -0
  34. package/lib/ReactCompositeComponent.js +1020 -0
  35. package/lib/ReactCurrentOwner.js +39 -0
  36. package/lib/ReactDOM.js +194 -0
  37. package/lib/ReactDOMButton.js +64 -0
  38. package/lib/ReactDOMComponent.js +374 -0
  39. package/lib/ReactDOMForm.js +52 -0
  40. package/lib/ReactDOMIDOperations.js +173 -0
  41. package/lib/ReactDOMInput.js +169 -0
  42. package/lib/ReactDOMOption.js +50 -0
  43. package/lib/ReactDOMSelect.js +160 -0
  44. package/lib/ReactDOMSelection.js +189 -0
  45. package/lib/ReactDOMTextarea.js +136 -0
  46. package/lib/ReactDefaultBatchingStrategy.js +75 -0
  47. package/lib/ReactDefaultInjection.js +91 -0
  48. package/lib/ReactDefaultPerf.js +407 -0
  49. package/lib/ReactErrorUtils.js +46 -0
  50. package/lib/ReactEventEmitter.js +341 -0
  51. package/lib/ReactEventEmitterMixin.js +89 -0
  52. package/lib/ReactEventTopLevelCallback.js +89 -0
  53. package/lib/ReactInputSelection.js +140 -0
  54. package/lib/ReactInstanceHandles.js +322 -0
  55. package/lib/ReactLink.js +54 -0
  56. package/lib/ReactMarkupChecksum.js +53 -0
  57. package/lib/ReactMount.js +617 -0
  58. package/lib/ReactMountReady.js +95 -0
  59. package/lib/ReactMultiChild.js +441 -0
  60. package/lib/ReactMultiChildUpdateTypes.js +36 -0
  61. package/lib/ReactOwner.js +146 -0
  62. package/lib/ReactPerf.js +88 -0
  63. package/lib/ReactPropTransferer.js +128 -0
  64. package/lib/ReactPropTypes.js +158 -0
  65. package/lib/ReactReconcileTransaction.js +161 -0
  66. package/lib/ReactServerRendering.js +62 -0
  67. package/lib/ReactStateSetters.js +111 -0
  68. package/lib/ReactTextComponent.js +94 -0
  69. package/lib/ReactTransitionEvents.js +97 -0
  70. package/lib/ReactTransitionGroup.js +112 -0
  71. package/lib/ReactTransitionKeySet.js +111 -0
  72. package/lib/ReactTransitionableChild.js +152 -0
  73. package/lib/ReactUpdates.js +145 -0
  74. package/lib/ReactWithAddons.js +41 -0
  75. package/lib/SelectEventPlugin.js +217 -0
  76. package/lib/SimpleEventPlugin.js +365 -0
  77. package/lib/SyntheticClipboardEvent.js +45 -0
  78. package/lib/SyntheticCompositionEvent.js +51 -0
  79. package/lib/SyntheticEvent.js +163 -0
  80. package/lib/SyntheticFocusEvent.js +44 -0
  81. package/lib/SyntheticKeyboardEvent.js +56 -0
  82. package/lib/SyntheticMouseEvent.js +85 -0
  83. package/lib/SyntheticTouchEvent.js +50 -0
  84. package/lib/SyntheticUIEvent.js +45 -0
  85. package/lib/SyntheticWheelEvent.js +63 -0
  86. package/lib/Transaction.js +251 -0
  87. package/lib/ViewportMetrics.js +37 -0
  88. package/lib/accumulate.js +54 -0
  89. package/lib/adler32.js +39 -0
  90. package/lib/containsNode.js +49 -0
  91. package/lib/copyProperties.js +54 -0
  92. package/lib/createArrayFrom.js +94 -0
  93. package/lib/createNodesFromMarkup.js +93 -0
  94. package/lib/createObjectFrom.js +61 -0
  95. package/lib/cx.js +44 -0
  96. package/lib/dangerousStyleValue.js +57 -0
  97. package/lib/emptyFunction.js +43 -0
  98. package/lib/escapeTextForBrowser.js +47 -0
  99. package/lib/ex.js +49 -0
  100. package/lib/filterAttributes.js +45 -0
  101. package/lib/flattenChildren.js +54 -0
  102. package/lib/forEachAccumulated.js +36 -0
  103. package/lib/ge.js +76 -0
  104. package/lib/getActiveElement.js +33 -0
  105. package/lib/getEventTarget.js +36 -0
  106. package/lib/getMarkupWrap.js +108 -0
  107. package/lib/getNodeForCharacterOffset.js +80 -0
  108. package/lib/getReactRootElementInContainer.js +40 -0
  109. package/lib/getTextContentAccessor.js +40 -0
  110. package/lib/getUnboundedScrollPosition.js +45 -0
  111. package/lib/hyphenate.js +35 -0
  112. package/lib/invariant.js +54 -0
  113. package/lib/isEventSupported.js +74 -0
  114. package/lib/isNode.js +33 -0
  115. package/lib/isTextInputElement.js +49 -0
  116. package/lib/isTextNode.js +30 -0
  117. package/lib/joinClasses.js +44 -0
  118. package/lib/keyMirror.js +58 -0
  119. package/lib/keyOf.js +41 -0
  120. package/lib/memoizeStringOnly.js +39 -0
  121. package/lib/merge.js +37 -0
  122. package/lib/mergeHelpers.js +137 -0
  123. package/lib/mergeInto.js +45 -0
  124. package/lib/mixInto.js +34 -0
  125. package/lib/mutateHTMLNodeWithMarkup.js +100 -0
  126. package/lib/objMap.js +47 -0
  127. package/lib/objMapKeyVal.js +47 -0
  128. package/lib/performanceNow.js +42 -0
  129. package/lib/shallowEqual.js +49 -0
  130. package/lib/traverseAllChildren.js +127 -0
  131. package/package.json +33 -21
  132. package/react.js +4 -0
  133. package/.npmignore +0 -7
  134. package/.travis.yml +0 -5
  135. package/Jakefile.js +0 -39
  136. package/LICENSE +0 -19
  137. package/browser-test/dist.html +0 -89
  138. package/browser-test/index.html +0 -85
  139. package/browser-test/min.html +0 -89
  140. package/dist/react.js +0 -3094
  141. package/dist/react.min.js +0 -22
  142. package/doc/advanced.md +0 -166
  143. package/doc/color-def.graffle +0 -938
  144. package/doc/color-def.png +0 -0
  145. package/doc/simple.dot +0 -25
  146. package/doc/simple.png +0 -0
  147. package/examples/longer-example.js +0 -41
  148. package/examples/simple.js +0 -45
  149. package/examples/using-ast-directly.js +0 -30
  150. package/examples/using-events1.js +0 -79
  151. package/examples/using-log-events.js +0 -43
  152. package/lib/base-task.js +0 -123
  153. package/lib/cb-task.js +0 -84
  154. package/lib/core.js +0 -138
  155. package/lib/dsl.js +0 -138
  156. package/lib/error.js +0 -55
  157. package/lib/event-collector.js +0 -81
  158. package/lib/event-manager.js +0 -85
  159. package/lib/eventemitter.js +0 -20
  160. package/lib/finalcb-first-task.js +0 -68
  161. package/lib/finalcb-task.js +0 -65
  162. package/lib/id.js +0 -22
  163. package/lib/input-parser.js +0 -56
  164. package/lib/log-events.js +0 -92
  165. package/lib/parse.js +0 -41
  166. package/lib/promise-resolve.js +0 -50
  167. package/lib/promise-task.js +0 -93
  168. package/lib/react.js +0 -59
  169. package/lib/ret-task.js +0 -71
  170. package/lib/sprintf.js +0 -18
  171. package/lib/status.js +0 -14
  172. package/lib/task.js +0 -251
  173. package/lib/track-tasks.js +0 -74
  174. package/lib/validate.js +0 -159
  175. package/lib/vcon.js +0 -90
  176. package/lib/when-task.js +0 -85
  177. package/src/dist.build.requirejs +0 -20
  178. package/test/ast.mocha.js +0 -136
  179. package/test/cb-task.mocha.js +0 -220
  180. package/test/core-deferred.mocha.js +0 -143
  181. package/test/core-when.mocha.js +0 -96
  182. package/test/core.mocha.js +0 -589
  183. package/test/dsl.mocha.js +0 -350
  184. package/test/event-manager.mocha.js +0 -119
  185. package/test/exec-options.mocha.js +0 -48
  186. package/test/finalcb-task.mocha.js +0 -58
  187. package/test/input-parser.mocha.js +0 -86
  188. package/test/mocha.opts +0 -2
  189. package/test/module-use.mocha.js +0 -147
  190. package/test/promise-auto-resolve.mocha.js +0 -68
  191. package/test/ret-task.mocha.js +0 -220
  192. package/test/task.mocha.js +0 -42
  193. package/test/validate-cb-task.mocha.js +0 -100
  194. package/test/validate-ret-task.mocha.js +0 -110
  195. package/test/validate.mocha.js +0 -324
  196. package/test/vcon.mocha.js +0 -193
  197. package/vendor/chai/chai.js +0 -2038
  198. package/vendor/jquery/jquery-1.7.1.js +0 -9266
  199. package/vendor/jquery/jquery-1.7.1.min.js +0 -4
  200. package/vendor/mocha/mocha.css +0 -135
  201. package/vendor/mocha/mocha.js +0 -3589
  202. package/vendor/node/util.js +0 -531
  203. package/vendor/requirejs/require.js +0 -2053
  204. package/vendor/requirejs/require.min.js +0 -33
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactComponentBrowserEnvironment
17
+ */
18
+
19
+ /*jslint evil: true */
20
+
21
+ "use strict";
22
+
23
+ var ReactDOMIDOperations = require("./ReactDOMIDOperations");
24
+ var ReactMarkupChecksum = require("./ReactMarkupChecksum");
25
+ var ReactMount = require("./ReactMount");
26
+ var ReactReconcileTransaction = require("./ReactReconcileTransaction");
27
+
28
+ var getReactRootElementInContainer = require("./getReactRootElementInContainer");
29
+ var invariant = require("./invariant");
30
+ var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup");
31
+
32
+
33
+ var ELEMENT_NODE_TYPE = 1;
34
+ var DOC_NODE_TYPE = 9;
35
+
36
+
37
+ /**
38
+ * Abstracts away all functionality of `ReactComponent` requires knowledge of
39
+ * the browser context.
40
+ */
41
+ var ReactComponentBrowserEnvironment = {
42
+ /**
43
+ * Mixed into every component instance.
44
+ */
45
+ Mixin: {
46
+ /**
47
+ * Returns the DOM node rendered by this component.
48
+ *
49
+ * @return {DOMElement} The root node of this component.
50
+ * @final
51
+ * @protected
52
+ */
53
+ getDOMNode: function() {
54
+ ("production" !== process.env.NODE_ENV ? invariant(
55
+ this.isMounted(),
56
+ 'getDOMNode(): A component must be mounted to have a DOM node.'
57
+ ) : invariant(this.isMounted()));
58
+ return ReactMount.getNode(this._rootNodeID);
59
+ }
60
+ },
61
+
62
+ ReactReconcileTransaction: ReactReconcileTransaction,
63
+
64
+ DOMIDOperations: ReactDOMIDOperations,
65
+
66
+ /**
67
+ * If a particular environment requires that some resources be cleaned up,
68
+ * specify this in the injected Mixin. In the DOM, we would likely want to
69
+ * purge any cached node ID lookups.
70
+ *
71
+ * @private
72
+ */
73
+ unmountIDFromEnvironment: function(rootNodeID) {
74
+ ReactMount.purgeID(rootNodeID);
75
+ },
76
+
77
+ /**
78
+ * @param {string} markup Markup string to place into the DOM Element.
79
+ * @param {DOMElement} container DOM Element to insert markup into.
80
+ * @param {boolean} shouldReuseMarkup Should reuse the existing markup in the
81
+ * container if possible.
82
+ */
83
+ mountImageIntoNode: function(markup, container, shouldReuseMarkup) {
84
+ ("production" !== process.env.NODE_ENV ? invariant(
85
+ container && (
86
+ container.nodeType === ELEMENT_NODE_TYPE ||
87
+ container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender
88
+ ),
89
+ 'mountComponentIntoNode(...): Target container is not valid.'
90
+ ) : invariant(container && (
91
+ container.nodeType === ELEMENT_NODE_TYPE ||
92
+ container.nodeType === DOC_NODE_TYPE && ReactMount.allowFullPageRender
93
+ )));
94
+ if (shouldReuseMarkup) {
95
+ if (ReactMarkupChecksum.canReuseMarkup(
96
+ markup,
97
+ getReactRootElementInContainer(container))) {
98
+ return;
99
+ } else {
100
+ if ("production" !== process.env.NODE_ENV) {
101
+ console.warn(
102
+ 'React attempted to use reuse markup in a container but the ' +
103
+ 'checksum was invalid. This generally means that you are using ' +
104
+ 'server rendering and the markup generated on the server was ' +
105
+ 'not what the client was expecting. React injected new markup ' +
106
+ 'to compensate which works but you have lost many of the ' +
107
+ 'benefits of server rendering. Instead, figure out why the ' +
108
+ 'markup being generated is different on the client or server.'
109
+ );
110
+ }
111
+ }
112
+ }
113
+
114
+ // You can't naively set the innerHTML of the entire document. You need
115
+ // to mutate documentElement which requires doing some crazy tricks. See
116
+ // mutateHTMLNodeWithMarkup()
117
+ if (container.nodeType === DOC_NODE_TYPE) {
118
+ mutateHTMLNodeWithMarkup(container.documentElement, markup);
119
+ return;
120
+ }
121
+
122
+ // Asynchronously inject markup by ensuring that the container is not in
123
+ // the document when settings its `innerHTML`.
124
+ var parent = container.parentNode;
125
+ if (parent) {
126
+ var next = container.nextSibling;
127
+ parent.removeChild(container);
128
+ container.innerHTML = markup;
129
+ if (next) {
130
+ parent.insertBefore(container, next);
131
+ } else {
132
+ parent.appendChild(container);
133
+ }
134
+ } else {
135
+ container.innerHTML = markup;
136
+ }
137
+ }
138
+ };
139
+
140
+ module.exports = ReactComponentBrowserEnvironment;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactComponentEnvironment
17
+ */
18
+
19
+ var ReactComponentBrowserEnvironment =
20
+ require("./ReactComponentBrowserEnvironment");
21
+
22
+ var ReactComponentEnvironment = ReactComponentBrowserEnvironment;
23
+
24
+ module.exports = ReactComponentEnvironment;
@@ -0,0 +1,1020 @@
1
+ /**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactCompositeComponent
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var ReactComponent = require("./ReactComponent");
22
+ var ReactCurrentOwner = require("./ReactCurrentOwner");
23
+ var ReactErrorUtils = require("./ReactErrorUtils");
24
+ var ReactOwner = require("./ReactOwner");
25
+ var ReactPerf = require("./ReactPerf");
26
+ var ReactPropTransferer = require("./ReactPropTransferer");
27
+ var ReactUpdates = require("./ReactUpdates");
28
+
29
+ var invariant = require("./invariant");
30
+ var keyMirror = require("./keyMirror");
31
+ var merge = require("./merge");
32
+ var mixInto = require("./mixInto");
33
+ var objMap = require("./objMap");
34
+
35
+ /**
36
+ * Policies that describe methods in `ReactCompositeComponentInterface`.
37
+ */
38
+ var SpecPolicy = keyMirror({
39
+ /**
40
+ * These methods may be defined only once by the class specification or mixin.
41
+ */
42
+ DEFINE_ONCE: null,
43
+ /**
44
+ * These methods may be defined by both the class specification and mixins.
45
+ * Subsequent definitions will be chained. These methods must return void.
46
+ */
47
+ DEFINE_MANY: null,
48
+ /**
49
+ * These methods are overriding the base ReactCompositeComponent class.
50
+ */
51
+ OVERRIDE_BASE: null,
52
+ /**
53
+ * These methods are similar to DEFINE_MANY, except we assume they return
54
+ * objects. We try to merge the keys of the return values of all the mixed in
55
+ * functions. If there is a key conflict we throw.
56
+ */
57
+ DEFINE_MANY_MERGED: null
58
+ });
59
+
60
+ /**
61
+ * Composite components are higher-level components that compose other composite
62
+ * or native components.
63
+ *
64
+ * To create a new type of `ReactCompositeComponent`, pass a specification of
65
+ * your new class to `React.createClass`. The only requirement of your class
66
+ * specification is that you implement a `render` method.
67
+ *
68
+ * var MyComponent = React.createClass({
69
+ * render: function() {
70
+ * return <div>Hello World</div>;
71
+ * }
72
+ * });
73
+ *
74
+ * The class specification supports a specific protocol of methods that have
75
+ * special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for
76
+ * more the comprehensive protocol. Any other properties and methods in the
77
+ * class specification will available on the prototype.
78
+ *
79
+ * @interface ReactCompositeComponentInterface
80
+ * @internal
81
+ */
82
+ var ReactCompositeComponentInterface = {
83
+
84
+ /**
85
+ * An array of Mixin objects to include when defining your component.
86
+ *
87
+ * @type {array}
88
+ * @optional
89
+ */
90
+ mixins: SpecPolicy.DEFINE_MANY,
91
+
92
+ /**
93
+ * Definition of prop types for this component.
94
+ *
95
+ * @type {object}
96
+ * @optional
97
+ */
98
+ propTypes: SpecPolicy.DEFINE_ONCE,
99
+
100
+
101
+
102
+ // ==== Definition methods ====
103
+
104
+ /**
105
+ * Invoked when the component is mounted. Values in the mapping will be set on
106
+ * `this.props` if that prop is not specified (i.e. using an `in` check).
107
+ *
108
+ * This method is invoked before `getInitialState` and therefore cannot rely
109
+ * on `this.state` or use `this.setState`.
110
+ *
111
+ * @return {object}
112
+ * @optional
113
+ */
114
+ getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,
115
+
116
+ /**
117
+ * Invoked once before the component is mounted. The return value will be used
118
+ * as the initial value of `this.state`.
119
+ *
120
+ * getInitialState: function() {
121
+ * return {
122
+ * isOn: false,
123
+ * fooBaz: new BazFoo()
124
+ * }
125
+ * }
126
+ *
127
+ * @return {object}
128
+ * @optional
129
+ */
130
+ getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
131
+
132
+ /**
133
+ * Uses props from `this.props` and state from `this.state` to render the
134
+ * structure of the component.
135
+ *
136
+ * No guarantees are made about when or how often this method is invoked, so
137
+ * it must not have side effects.
138
+ *
139
+ * render: function() {
140
+ * var name = this.props.name;
141
+ * return <div>Hello, {name}!</div>;
142
+ * }
143
+ *
144
+ * @return {ReactComponent}
145
+ * @nosideeffects
146
+ * @required
147
+ */
148
+ render: SpecPolicy.DEFINE_ONCE,
149
+
150
+
151
+
152
+ // ==== Delegate methods ====
153
+
154
+ /**
155
+ * Invoked when the component is initially created and about to be mounted.
156
+ * This may have side effects, but any external subscriptions or data created
157
+ * by this method must be cleaned up in `componentWillUnmount`.
158
+ *
159
+ * @optional
160
+ */
161
+ componentWillMount: SpecPolicy.DEFINE_MANY,
162
+
163
+ /**
164
+ * Invoked when the component has been mounted and has a DOM representation.
165
+ * However, there is no guarantee that the DOM node is in the document.
166
+ *
167
+ * Use this as an opportunity to operate on the DOM when the component has
168
+ * been mounted (initialized and rendered) for the first time.
169
+ *
170
+ * @param {DOMElement} rootNode DOM element representing the component.
171
+ * @optional
172
+ */
173
+ componentDidMount: SpecPolicy.DEFINE_MANY,
174
+
175
+ /**
176
+ * Invoked before the component receives new props.
177
+ *
178
+ * Use this as an opportunity to react to a prop transition by updating the
179
+ * state using `this.setState`. Current props are accessed via `this.props`.
180
+ *
181
+ * componentWillReceiveProps: function(nextProps) {
182
+ * this.setState({
183
+ * likesIncreasing: nextProps.likeCount > this.props.likeCount
184
+ * });
185
+ * }
186
+ *
187
+ * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
188
+ * transition may cause a state change, but the opposite is not true. If you
189
+ * need it, you are probably looking for `componentWillUpdate`.
190
+ *
191
+ * @param {object} nextProps
192
+ * @optional
193
+ */
194
+ componentWillReceiveProps: SpecPolicy.DEFINE_MANY,
195
+
196
+ /**
197
+ * Invoked while deciding if the component should be updated as a result of
198
+ * receiving new props and state.
199
+ *
200
+ * Use this as an opportunity to `return false` when you're certain that the
201
+ * transition to the new props and state will not require a component update.
202
+ *
203
+ * shouldComponentUpdate: function(nextProps, nextState) {
204
+ * return !equal(nextProps, this.props) || !equal(nextState, this.state);
205
+ * }
206
+ *
207
+ * @param {object} nextProps
208
+ * @param {?object} nextState
209
+ * @return {boolean} True if the component should update.
210
+ * @optional
211
+ */
212
+ shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,
213
+
214
+ /**
215
+ * Invoked when the component is about to update due to a transition from
216
+ * `this.props` and `this.state` to `nextProps` and `nextState`.
217
+ *
218
+ * Use this as an opportunity to perform preparation before an update occurs.
219
+ *
220
+ * NOTE: You **cannot** use `this.setState()` in this method.
221
+ *
222
+ * @param {object} nextProps
223
+ * @param {?object} nextState
224
+ * @param {ReactReconcileTransaction} transaction
225
+ * @optional
226
+ */
227
+ componentWillUpdate: SpecPolicy.DEFINE_MANY,
228
+
229
+ /**
230
+ * Invoked when the component's DOM representation has been updated.
231
+ *
232
+ * Use this as an opportunity to operate on the DOM when the component has
233
+ * been updated.
234
+ *
235
+ * @param {object} prevProps
236
+ * @param {?object} prevState
237
+ * @param {DOMElement} rootNode DOM element representing the component.
238
+ * @optional
239
+ */
240
+ componentDidUpdate: SpecPolicy.DEFINE_MANY,
241
+
242
+ /**
243
+ * Invoked when the component is about to be removed from its parent and have
244
+ * its DOM representation destroyed.
245
+ *
246
+ * Use this as an opportunity to deallocate any external resources.
247
+ *
248
+ * NOTE: There is no `componentDidUnmount` since your component will have been
249
+ * destroyed by that point.
250
+ *
251
+ * @optional
252
+ */
253
+ componentWillUnmount: SpecPolicy.DEFINE_MANY,
254
+
255
+
256
+
257
+ // ==== Advanced methods ====
258
+
259
+ /**
260
+ * Updates the component's currently mounted DOM representation.
261
+ *
262
+ * By default, this implements React's rendering and reconciliation algorithm.
263
+ * Sophisticated clients may wish to override this.
264
+ *
265
+ * @param {ReactReconcileTransaction} transaction
266
+ * @internal
267
+ * @overridable
268
+ */
269
+ updateComponent: SpecPolicy.OVERRIDE_BASE
270
+
271
+ };
272
+
273
+ /**
274
+ * Mapping from class specification keys to special processing functions.
275
+ *
276
+ * Although these are declared in the specification when defining classes
277
+ * using `React.createClass`, they will not be on the component's prototype.
278
+ */
279
+ var RESERVED_SPEC_KEYS = {
280
+ displayName: function(Constructor, displayName) {
281
+ Constructor.displayName = displayName;
282
+ },
283
+ mixins: function(Constructor, mixins) {
284
+ if (mixins) {
285
+ for (var i = 0; i < mixins.length; i++) {
286
+ mixSpecIntoComponent(Constructor, mixins[i]);
287
+ }
288
+ }
289
+ },
290
+ propTypes: function(Constructor, propTypes) {
291
+ Constructor.propTypes = propTypes;
292
+ }
293
+ };
294
+
295
+ function validateMethodOverride(proto, name) {
296
+ var specPolicy = ReactCompositeComponentInterface[name];
297
+
298
+ // Disallow overriding of base class methods unless explicitly allowed.
299
+ if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
300
+ ("production" !== process.env.NODE_ENV ? invariant(
301
+ specPolicy === SpecPolicy.OVERRIDE_BASE,
302
+ 'ReactCompositeComponentInterface: You are attempting to override ' +
303
+ '`%s` from your class specification. Ensure that your method names ' +
304
+ 'do not overlap with React methods.',
305
+ name
306
+ ) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE));
307
+ }
308
+
309
+ // Disallow defining methods more than once unless explicitly allowed.
310
+ if (proto.hasOwnProperty(name)) {
311
+ ("production" !== process.env.NODE_ENV ? invariant(
312
+ specPolicy === SpecPolicy.DEFINE_MANY ||
313
+ specPolicy === SpecPolicy.DEFINE_MANY_MERGED,
314
+ 'ReactCompositeComponentInterface: You are attempting to define ' +
315
+ '`%s` on your component more than once. This conflict may be due ' +
316
+ 'to a mixin.',
317
+ name
318
+ ) : invariant(specPolicy === SpecPolicy.DEFINE_MANY ||
319
+ specPolicy === SpecPolicy.DEFINE_MANY_MERGED));
320
+ }
321
+ }
322
+
323
+
324
+ function validateLifeCycleOnReplaceState(instance) {
325
+ var compositeLifeCycleState = instance._compositeLifeCycleState;
326
+ ("production" !== process.env.NODE_ENV ? invariant(
327
+ instance.isMounted() ||
328
+ compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
329
+ 'replaceState(...): Can only update a mounted or mounting component.'
330
+ ) : invariant(instance.isMounted() ||
331
+ compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
332
+ ("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE,
333
+ 'replaceState(...): Cannot update during an existing state transition ' +
334
+ '(such as within `render`). This could potentially cause an infinite ' +
335
+ 'loop so it is forbidden.'
336
+ ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE));
337
+ ("production" !== process.env.NODE_ENV ? invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
338
+ 'replaceState(...): Cannot update while unmounting component. This ' +
339
+ 'usually means you called setState() on an unmounted component.'
340
+ ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
341
+ }
342
+
343
+ /**
344
+ * Custom version of `mixInto` which handles policy validation and reserved
345
+ * specification keys when building `ReactCompositeComponent` classses.
346
+ */
347
+ function mixSpecIntoComponent(Constructor, spec) {
348
+ var proto = Constructor.prototype;
349
+ for (var name in spec) {
350
+ var property = spec[name];
351
+ if (!spec.hasOwnProperty(name) || !property) {
352
+ continue;
353
+ }
354
+ validateMethodOverride(proto, name);
355
+
356
+ if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
357
+ RESERVED_SPEC_KEYS[name](Constructor, property);
358
+ } else {
359
+ // Setup methods on prototype:
360
+ // The following member methods should not be automatically bound:
361
+ // 1. Expected ReactCompositeComponent methods (in the "interface").
362
+ // 2. Overridden methods (that were mixed in).
363
+ var isCompositeComponentMethod = name in ReactCompositeComponentInterface;
364
+ var isInherited = name in proto;
365
+ var markedDontBind = property.__reactDontBind;
366
+ var isFunction = typeof property === 'function';
367
+ var shouldAutoBind =
368
+ isFunction &&
369
+ !isCompositeComponentMethod &&
370
+ !isInherited &&
371
+ !markedDontBind;
372
+
373
+ if (shouldAutoBind) {
374
+ if (!proto.__reactAutoBindMap) {
375
+ proto.__reactAutoBindMap = {};
376
+ }
377
+ proto.__reactAutoBindMap[name] = property;
378
+ proto[name] = property;
379
+ } else {
380
+ if (isInherited) {
381
+ // For methods which are defined more than once, call the existing
382
+ // methods before calling the new property.
383
+ if (ReactCompositeComponentInterface[name] ===
384
+ SpecPolicy.DEFINE_MANY_MERGED) {
385
+ proto[name] = createMergedResultFunction(proto[name], property);
386
+ } else {
387
+ proto[name] = createChainedFunction(proto[name], property);
388
+ }
389
+ } else {
390
+ proto[name] = property;
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Merge two objects, but throw if both contain the same key.
399
+ *
400
+ * @param {object} one The first object, which is mutated.
401
+ * @param {object} two The second object
402
+ * @return {object} one after it has been mutated to contain everything in two.
403
+ */
404
+ function mergeObjectsWithNoDuplicateKeys(one, two) {
405
+ ("production" !== process.env.NODE_ENV ? invariant(
406
+ one && two && typeof one === 'object' && typeof two === 'object',
407
+ 'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
408
+ ) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
409
+
410
+ objMap(two, function(value, key) {
411
+ ("production" !== process.env.NODE_ENV ? invariant(
412
+ one[key] === undefined,
413
+ 'mergeObjectsWithNoDuplicateKeys(): ' +
414
+ 'Tried to merge two objects with the same key: %s',
415
+ key
416
+ ) : invariant(one[key] === undefined));
417
+ one[key] = value;
418
+ });
419
+ return one;
420
+ }
421
+
422
+ /**
423
+ * Creates a function that invokes two functions and merges their return values.
424
+ *
425
+ * @param {function} one Function to invoke first.
426
+ * @param {function} two Function to invoke second.
427
+ * @return {function} Function that invokes the two argument functions.
428
+ * @private
429
+ */
430
+ function createMergedResultFunction(one, two) {
431
+ return function mergedResult() {
432
+ return mergeObjectsWithNoDuplicateKeys(
433
+ one.apply(this, arguments),
434
+ two.apply(this, arguments)
435
+ );
436
+ };
437
+ }
438
+
439
+ /**
440
+ * Creates a function that invokes two functions and ignores their return vales.
441
+ *
442
+ * @param {function} one Function to invoke first.
443
+ * @param {function} two Function to invoke second.
444
+ * @return {function} Function that invokes the two argument functions.
445
+ * @private
446
+ */
447
+ function createChainedFunction(one, two) {
448
+ return function chainedFunction() {
449
+ one.apply(this, arguments);
450
+ two.apply(this, arguments);
451
+ };
452
+ }
453
+
454
+ /**
455
+ * `ReactCompositeComponent` maintains an auxiliary life cycle state in
456
+ * `this._compositeLifeCycleState` (which can be null).
457
+ *
458
+ * This is different from the life cycle state maintained by `ReactComponent` in
459
+ * `this._lifeCycleState`. The following diagram shows how the states overlap in
460
+ * time. There are times when the CompositeLifeCycle is null - at those times it
461
+ * is only meaningful to look at ComponentLifeCycle alone.
462
+ *
463
+ * Top Row: ReactComponent.ComponentLifeCycle
464
+ * Low Row: ReactComponent.CompositeLifeCycle
465
+ *
466
+ * +-------+------------------------------------------------------+--------+
467
+ * | UN | MOUNTED | UN |
468
+ * |MOUNTED| | MOUNTED|
469
+ * +-------+------------------------------------------------------+--------+
470
+ * | ^--------+ +------+ +------+ +------+ +--------^ |
471
+ * | | | | | | | | | | | |
472
+ * | 0--|MOUNTING|-0-|RECEIV|-0-|RECEIV|-0-|RECEIV|-0-| UN |--->0 |
473
+ * | | | |PROPS | | PROPS| | STATE| |MOUNTING| |
474
+ * | | | | | | | | | | | |
475
+ * | | | | | | | | | | | |
476
+ * | +--------+ +------+ +------+ +------+ +--------+ |
477
+ * | | | |
478
+ * +-------+------------------------------------------------------+--------+
479
+ */
480
+ var CompositeLifeCycle = keyMirror({
481
+ /**
482
+ * Components in the process of being mounted respond to state changes
483
+ * differently.
484
+ */
485
+ MOUNTING: null,
486
+ /**
487
+ * Components in the process of being unmounted are guarded against state
488
+ * changes.
489
+ */
490
+ UNMOUNTING: null,
491
+ /**
492
+ * Components that are mounted and receiving new props respond to state
493
+ * changes differently.
494
+ */
495
+ RECEIVING_PROPS: null,
496
+ /**
497
+ * Components that are mounted and receiving new state are guarded against
498
+ * additional state changes.
499
+ */
500
+ RECEIVING_STATE: null
501
+ });
502
+
503
+ /**
504
+ * @lends {ReactCompositeComponent.prototype}
505
+ */
506
+ var ReactCompositeComponentMixin = {
507
+
508
+ /**
509
+ * Base constructor for all composite component.
510
+ *
511
+ * @param {?object} initialProps
512
+ * @param {*} children
513
+ * @final
514
+ * @internal
515
+ */
516
+ construct: function(initialProps, children) {
517
+ // Children can be either an array or more than one argument
518
+ ReactComponent.Mixin.construct.apply(this, arguments);
519
+ this.state = null;
520
+ this._pendingState = null;
521
+ this._compositeLifeCycleState = null;
522
+ },
523
+
524
+ /**
525
+ * Checks whether or not this composite component is mounted.
526
+ * @return {boolean} True if mounted, false otherwise.
527
+ * @protected
528
+ * @final
529
+ */
530
+ isMounted: function() {
531
+ return ReactComponent.Mixin.isMounted.call(this) &&
532
+ this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
533
+ },
534
+
535
+ /**
536
+ * Initializes the component, renders markup, and registers event listeners.
537
+ *
538
+ * @param {string} rootID DOM ID of the root node.
539
+ * @param {ReactReconcileTransaction} transaction
540
+ * @param {number} mountDepth number of components in the owner hierarchy
541
+ * @return {?string} Rendered markup to be inserted into the DOM.
542
+ * @final
543
+ * @internal
544
+ */
545
+ mountComponent: ReactPerf.measure(
546
+ 'ReactCompositeComponent',
547
+ 'mountComponent',
548
+ function(rootID, transaction, mountDepth) {
549
+ ReactComponent.Mixin.mountComponent.call(
550
+ this,
551
+ rootID,
552
+ transaction,
553
+ mountDepth
554
+ );
555
+ this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
556
+
557
+ this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
558
+ this._processProps(this.props);
559
+
560
+ if (this.__reactAutoBindMap) {
561
+ this._bindAutoBindMethods();
562
+ }
563
+
564
+ this.state = this.getInitialState ? this.getInitialState() : null;
565
+ this._pendingState = null;
566
+ this._pendingForceUpdate = false;
567
+
568
+ if (this.componentWillMount) {
569
+ this.componentWillMount();
570
+ // When mounting, calls to `setState` by `componentWillMount` will set
571
+ // `this._pendingState` without triggering a re-render.
572
+ if (this._pendingState) {
573
+ this.state = this._pendingState;
574
+ this._pendingState = null;
575
+ }
576
+ }
577
+
578
+ this._renderedComponent = this._renderValidatedComponent();
579
+
580
+ // Done with mounting, `setState` will now trigger UI changes.
581
+ this._compositeLifeCycleState = null;
582
+ var markup = this._renderedComponent.mountComponent(
583
+ rootID,
584
+ transaction,
585
+ mountDepth + 1
586
+ );
587
+ if (this.componentDidMount) {
588
+ transaction.getReactMountReady().enqueue(this, this.componentDidMount);
589
+ }
590
+ return markup;
591
+ }
592
+ ),
593
+
594
+ /**
595
+ * Releases any resources allocated by `mountComponent`.
596
+ *
597
+ * @final
598
+ * @internal
599
+ */
600
+ unmountComponent: function() {
601
+ this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
602
+ if (this.componentWillUnmount) {
603
+ this.componentWillUnmount();
604
+ }
605
+ this._compositeLifeCycleState = null;
606
+
607
+ this._defaultProps = null;
608
+
609
+ ReactComponent.Mixin.unmountComponent.call(this);
610
+ this._renderedComponent.unmountComponent();
611
+ this._renderedComponent = null;
612
+
613
+ if (this.refs) {
614
+ this.refs = null;
615
+ }
616
+
617
+ // Some existing components rely on this.props even after they've been
618
+ // destroyed (in event handlers).
619
+ // TODO: this.props = null;
620
+ // TODO: this.state = null;
621
+ },
622
+
623
+ /**
624
+ * Sets a subset of the state. Always use this or `replaceState` to mutate
625
+ * state. You should treat `this.state` as immutable.
626
+ *
627
+ * There is no guarantee that `this.state` will be immediately updated, so
628
+ * accessing `this.state` after calling this method may return the old value.
629
+ *
630
+ * There is no guarantee that calls to `setState` will run synchronously,
631
+ * as they may eventually be batched together. You can provide an optional
632
+ * callback that will be executed when the call to setState is actually
633
+ * completed.
634
+ *
635
+ * @param {object} partialState Next partial state to be merged with state.
636
+ * @param {?function} callback Called after state is updated.
637
+ * @final
638
+ * @protected
639
+ */
640
+ setState: function(partialState, callback) {
641
+ // Merge with `_pendingState` if it exists, otherwise with existing state.
642
+ this.replaceState(
643
+ merge(this._pendingState || this.state, partialState),
644
+ callback
645
+ );
646
+ },
647
+
648
+ /**
649
+ * Replaces all of the state. Always use this or `setState` to mutate state.
650
+ * You should treat `this.state` as immutable.
651
+ *
652
+ * There is no guarantee that `this.state` will be immediately updated, so
653
+ * accessing `this.state` after calling this method may return the old value.
654
+ *
655
+ * @param {object} completeState Next state.
656
+ * @param {?function} callback Called after state is updated.
657
+ * @final
658
+ * @protected
659
+ */
660
+ replaceState: function(completeState, callback) {
661
+ validateLifeCycleOnReplaceState(this);
662
+ this._pendingState = completeState;
663
+ ReactUpdates.enqueueUpdate(this, callback);
664
+ },
665
+
666
+ /**
667
+ * Processes props by setting default values for unspecified props and
668
+ * asserting that the props are valid.
669
+ *
670
+ * @param {object} props
671
+ * @private
672
+ */
673
+ _processProps: function(props) {
674
+ var propName;
675
+ var defaultProps = this._defaultProps;
676
+ for (propName in defaultProps) {
677
+ if (!(propName in props)) {
678
+ props[propName] = defaultProps[propName];
679
+ }
680
+ }
681
+ var propTypes = this.constructor.propTypes;
682
+ if (propTypes) {
683
+ var componentName = this.constructor.displayName;
684
+ for (propName in propTypes) {
685
+ var checkProp = propTypes[propName];
686
+ if (checkProp) {
687
+ checkProp(props, propName, componentName);
688
+ }
689
+ }
690
+ }
691
+ },
692
+
693
+ performUpdateIfNecessary: function() {
694
+ var compositeLifeCycleState = this._compositeLifeCycleState;
695
+ // Do not trigger a state transition if we are in the middle of mounting or
696
+ // receiving props because both of those will already be doing this.
697
+ if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
698
+ compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
699
+ return;
700
+ }
701
+ ReactComponent.Mixin.performUpdateIfNecessary.call(this);
702
+ },
703
+
704
+ /**
705
+ * If any of `_pendingProps`, `_pendingState`, or `_pendingForceUpdate` is
706
+ * set, update the component.
707
+ *
708
+ * @param {ReactReconcileTransaction} transaction
709
+ * @internal
710
+ */
711
+ _performUpdateIfNecessary: function(transaction) {
712
+ if (this._pendingProps == null &&
713
+ this._pendingState == null &&
714
+ !this._pendingForceUpdate) {
715
+ return;
716
+ }
717
+
718
+ var nextProps = this.props;
719
+ if (this._pendingProps != null) {
720
+ nextProps = this._pendingProps;
721
+ this._processProps(nextProps);
722
+ this._pendingProps = null;
723
+
724
+ this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
725
+ if (this.componentWillReceiveProps) {
726
+ this.componentWillReceiveProps(nextProps, transaction);
727
+ }
728
+ }
729
+
730
+ this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
731
+
732
+ var nextState = this._pendingState || this.state;
733
+ this._pendingState = null;
734
+
735
+ if (this._pendingForceUpdate ||
736
+ !this.shouldComponentUpdate ||
737
+ this.shouldComponentUpdate(nextProps, nextState)) {
738
+ this._pendingForceUpdate = false;
739
+ // Will set `this.props` and `this.state`.
740
+ this._performComponentUpdate(nextProps, nextState, transaction);
741
+ } else {
742
+ // If it's determined that a component should not update, we still want
743
+ // to set props and state.
744
+ this.props = nextProps;
745
+ this.state = nextState;
746
+ }
747
+
748
+ this._compositeLifeCycleState = null;
749
+ },
750
+
751
+ /**
752
+ * Merges new props and state, notifies delegate methods of update and
753
+ * performs update.
754
+ *
755
+ * @param {object} nextProps Next object to set as properties.
756
+ * @param {?object} nextState Next object to set as state.
757
+ * @param {ReactReconcileTransaction} transaction
758
+ * @private
759
+ */
760
+ _performComponentUpdate: function(nextProps, nextState, transaction) {
761
+ var prevProps = this.props;
762
+ var prevState = this.state;
763
+
764
+ if (this.componentWillUpdate) {
765
+ this.componentWillUpdate(nextProps, nextState, transaction);
766
+ }
767
+
768
+ this.props = nextProps;
769
+ this.state = nextState;
770
+
771
+ this.updateComponent(transaction, prevProps, prevState);
772
+
773
+ if (this.componentDidUpdate) {
774
+ transaction.getReactMountReady().enqueue(
775
+ this,
776
+ this.componentDidUpdate.bind(this, prevProps, prevState)
777
+ );
778
+ }
779
+ },
780
+
781
+ /**
782
+ * Updates the component's currently mounted DOM representation.
783
+ *
784
+ * By default, this implements React's rendering and reconciliation algorithm.
785
+ * Sophisticated clients may wish to override this.
786
+ *
787
+ * @param {ReactReconcileTransaction} transaction
788
+ * @param {object} prevProps
789
+ * @param {?object} prevState
790
+ * @internal
791
+ * @overridable
792
+ */
793
+ updateComponent: ReactPerf.measure(
794
+ 'ReactCompositeComponent',
795
+ 'updateComponent',
796
+ function(transaction, prevProps, prevState) {
797
+ ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps);
798
+ var currentComponent = this._renderedComponent;
799
+ var nextComponent = this._renderValidatedComponent();
800
+ if (currentComponent.constructor === nextComponent.constructor) {
801
+ currentComponent.receiveComponent(nextComponent, transaction);
802
+ } else {
803
+ // These two IDs are actually the same! But nothing should rely on that.
804
+ var thisID = this._rootNodeID;
805
+ var currentComponentID = currentComponent._rootNodeID;
806
+ currentComponent.unmountComponent();
807
+ this._renderedComponent = nextComponent;
808
+ var nextMarkup = nextComponent.mountComponent(
809
+ thisID,
810
+ transaction,
811
+ this._mountDepth + 1
812
+ );
813
+ ReactComponent.DOMIDOperations.dangerouslyReplaceNodeWithMarkupByID(
814
+ currentComponentID,
815
+ nextMarkup
816
+ );
817
+ }
818
+ }
819
+ ),
820
+
821
+ /**
822
+ * Forces an update. This should only be invoked when it is known with
823
+ * certainty that we are **not** in a DOM transaction.
824
+ *
825
+ * You may want to call this when you know that some deeper aspect of the
826
+ * component's state has changed but `setState` was not called.
827
+ *
828
+ * This will not invoke `shouldUpdateComponent`, but it will invoke
829
+ * `componentWillUpdate` and `componentDidUpdate`.
830
+ *
831
+ * @param {?function} callback Called after update is complete.
832
+ * @final
833
+ * @protected
834
+ */
835
+ forceUpdate: function(callback) {
836
+ var compositeLifeCycleState = this._compositeLifeCycleState;
837
+ ("production" !== process.env.NODE_ENV ? invariant(
838
+ this.isMounted() ||
839
+ compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
840
+ 'forceUpdate(...): Can only force an update on mounted or mounting ' +
841
+ 'components.'
842
+ ) : invariant(this.isMounted() ||
843
+ compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
844
+ ("production" !== process.env.NODE_ENV ? invariant(
845
+ compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
846
+ compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
847
+ 'forceUpdate(...): Cannot force an update while unmounting component ' +
848
+ 'or during an existing state transition (such as within `render`).'
849
+ ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
850
+ compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
851
+ this._pendingForceUpdate = true;
852
+ ReactUpdates.enqueueUpdate(this, callback);
853
+ },
854
+
855
+ /**
856
+ * @private
857
+ */
858
+ _renderValidatedComponent: function() {
859
+ var renderedComponent;
860
+ ReactCurrentOwner.current = this;
861
+ try {
862
+ renderedComponent = this.render();
863
+ } catch (error) {
864
+ // IE8 requires `catch` in order to use `finally`.
865
+ throw error;
866
+ } finally {
867
+ ReactCurrentOwner.current = null;
868
+ }
869
+ ("production" !== process.env.NODE_ENV ? invariant(
870
+ ReactComponent.isValidComponent(renderedComponent),
871
+ '%s.render(): A valid ReactComponent must be returned. You may have ' +
872
+ 'returned null, undefined, an array, or some other invalid object.',
873
+ this.constructor.displayName || 'ReactCompositeComponent'
874
+ ) : invariant(ReactComponent.isValidComponent(renderedComponent)));
875
+ return renderedComponent;
876
+ },
877
+
878
+ /**
879
+ * @private
880
+ */
881
+ _bindAutoBindMethods: function() {
882
+ for (var autoBindKey in this.__reactAutoBindMap) {
883
+ if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
884
+ continue;
885
+ }
886
+ var method = this.__reactAutoBindMap[autoBindKey];
887
+ this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard(
888
+ method,
889
+ this.constructor.displayName + '.' + autoBindKey
890
+ ));
891
+ }
892
+ },
893
+
894
+ /**
895
+ * Binds a method to the component.
896
+ *
897
+ * @param {function} method Method to be bound.
898
+ * @private
899
+ */
900
+ _bindAutoBindMethod: function(method) {
901
+ var component = this;
902
+ var boundMethod = function() {
903
+ return method.apply(component, arguments);
904
+ };
905
+ if ("production" !== process.env.NODE_ENV) {
906
+ boundMethod.__reactBoundContext = component;
907
+ boundMethod.__reactBoundMethod = method;
908
+ boundMethod.__reactBoundArguments = null;
909
+ var componentName = component.constructor.displayName;
910
+ var _bind = boundMethod.bind;
911
+ boundMethod.bind = function(newThis) {
912
+ // User is trying to bind() an autobound method; we effectively will
913
+ // ignore the value of "this" that the user is trying to use, so
914
+ // let's warn.
915
+ if (newThis !== component && newThis !== null) {
916
+ console.warn(
917
+ 'bind(): React component methods may only be bound to the ' +
918
+ 'component instance. See ' + componentName
919
+ );
920
+ } else if (arguments.length === 1) {
921
+ console.warn(
922
+ 'bind(): You are binding a component method to the component. ' +
923
+ 'React does this for you automatically in a high-performance ' +
924
+ 'way, so you can safely remove this call. See ' + componentName
925
+ );
926
+ return boundMethod;
927
+ }
928
+ var reboundMethod = _bind.apply(boundMethod, arguments);
929
+ reboundMethod.__reactBoundContext = component;
930
+ reboundMethod.__reactBoundMethod = method;
931
+ reboundMethod.__reactBoundArguments =
932
+ Array.prototype.slice.call(arguments, 1);
933
+ return reboundMethod;
934
+ };
935
+ }
936
+ return boundMethod;
937
+ }
938
+ };
939
+
940
+ var ReactCompositeComponentBase = function() {};
941
+ mixInto(ReactCompositeComponentBase, ReactComponent.Mixin);
942
+ mixInto(ReactCompositeComponentBase, ReactOwner.Mixin);
943
+ mixInto(ReactCompositeComponentBase, ReactPropTransferer.Mixin);
944
+ mixInto(ReactCompositeComponentBase, ReactCompositeComponentMixin);
945
+
946
+ /**
947
+ * Module for creating composite components.
948
+ *
949
+ * @class ReactCompositeComponent
950
+ * @extends ReactComponent
951
+ * @extends ReactOwner
952
+ * @extends ReactPropTransferer
953
+ */
954
+ var ReactCompositeComponent = {
955
+
956
+ LifeCycle: CompositeLifeCycle,
957
+
958
+ Base: ReactCompositeComponentBase,
959
+
960
+ /**
961
+ * Creates a composite component class given a class specification.
962
+ *
963
+ * @param {object} spec Class specification (which must define `render`).
964
+ * @return {function} Component constructor function.
965
+ * @public
966
+ */
967
+ createClass: function(spec) {
968
+ var Constructor = function() {};
969
+ Constructor.prototype = new ReactCompositeComponentBase();
970
+ Constructor.prototype.constructor = Constructor;
971
+ mixSpecIntoComponent(Constructor, spec);
972
+
973
+ ("production" !== process.env.NODE_ENV ? invariant(
974
+ Constructor.prototype.render,
975
+ 'createClass(...): Class specification must implement a `render` method.'
976
+ ) : invariant(Constructor.prototype.render));
977
+
978
+ if ("production" !== process.env.NODE_ENV) {
979
+ if (Constructor.prototype.componentShouldUpdate) {
980
+ console.warn(
981
+ (spec.displayName || 'A component') + ' has a method called ' +
982
+ 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
983
+ 'The name is phrased as a question because the function is ' +
984
+ 'expected to return a value.'
985
+ );
986
+ }
987
+ }
988
+
989
+ // Reduce time spent doing lookups by setting these on the prototype.
990
+ for (var methodName in ReactCompositeComponentInterface) {
991
+ if (!Constructor.prototype[methodName]) {
992
+ Constructor.prototype[methodName] = null;
993
+ }
994
+ }
995
+
996
+ var ConvenienceConstructor = function(props, children) {
997
+ var instance = new Constructor();
998
+ instance.construct.apply(instance, arguments);
999
+ return instance;
1000
+ };
1001
+ ConvenienceConstructor.componentConstructor = Constructor;
1002
+ ConvenienceConstructor.originalSpec = spec;
1003
+ return ConvenienceConstructor;
1004
+ },
1005
+
1006
+ /**
1007
+ * Checks if a value is a valid component constructor.
1008
+ *
1009
+ * @param {*}
1010
+ * @return {boolean}
1011
+ * @public
1012
+ */
1013
+ isValidClass: function(componentClass) {
1014
+ return componentClass instanceof Function &&
1015
+ 'componentConstructor' in componentClass &&
1016
+ componentClass.componentConstructor instanceof Function;
1017
+ }
1018
+ };
1019
+
1020
+ module.exports = ReactCompositeComponent;