react 0.12.2 → 0.13.0-alpha.1

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 (77) hide show
  1. package/dist/JSXTransformer.js +6 -4
  2. package/dist/react-with-addons.js +4022 -3267
  3. package/dist/react-with-addons.min.js +6 -6
  4. package/dist/react.js +3853 -3358
  5. package/dist/react.min.js +6 -6
  6. package/lib/BeforeInputEventPlugin.js +388 -111
  7. package/lib/CSSPropertyOperations.js +20 -0
  8. package/lib/ChangeEventPlugin.js +2 -2
  9. package/lib/Danger.js +1 -1
  10. package/lib/DefaultEventPluginOrder.js +0 -1
  11. package/lib/ExecutionEnvironment.js +2 -3
  12. package/lib/FallbackCompositionState.js +87 -0
  13. package/lib/HTMLDOMPropertyConfig.js +1 -0
  14. package/lib/Object.assign.js +3 -1
  15. package/lib/React.js +14 -49
  16. package/lib/ReactBrowserComponentMixin.js +2 -12
  17. package/lib/ReactBrowserEventEmitter.js +2 -4
  18. package/lib/ReactCSSTransitionGroup.js +3 -0
  19. package/lib/ReactCSSTransitionGroupChild.js +8 -0
  20. package/lib/ReactChildReconciler.js +121 -0
  21. package/lib/ReactClass.js +916 -0
  22. package/lib/ReactComponent.js +36 -286
  23. package/lib/ReactComponentBrowserEnvironment.js +9 -82
  24. package/lib/ReactComponentEnvironment.js +57 -0
  25. package/lib/ReactCompositeComponent.js +608 -1026
  26. package/lib/ReactContext.js +5 -1
  27. package/lib/ReactDOM.js +2 -7
  28. package/lib/ReactDOMButton.js +4 -5
  29. package/lib/ReactDOMComponent.js +97 -69
  30. package/lib/ReactDOMForm.js +4 -5
  31. package/lib/ReactDOMIDOperations.js +55 -73
  32. package/lib/ReactDOMImg.js +3 -5
  33. package/lib/ReactDOMInput.js +4 -5
  34. package/lib/ReactDOMOption.js +4 -5
  35. package/lib/ReactDOMSelect.js +55 -63
  36. package/lib/ReactDOMSelection.js +5 -1
  37. package/lib/{ReactTextComponent.js → ReactDOMTextComponent.js} +54 -34
  38. package/lib/ReactDOMTextarea.js +4 -5
  39. package/lib/ReactDefaultInjection.js +13 -7
  40. package/lib/ReactDefaultPerf.js +6 -5
  41. package/lib/ReactDefaultPerfAnalysis.js +1 -1
  42. package/lib/ReactElement.js +17 -11
  43. package/lib/ReactElementValidator.js +74 -37
  44. package/lib/ReactEmptyComponent.js +17 -10
  45. package/lib/ReactInjection.js +6 -4
  46. package/lib/ReactInputSelection.js +2 -3
  47. package/lib/ReactInstanceMap.js +47 -0
  48. package/lib/ReactMount.js +193 -64
  49. package/lib/ReactMultiChild.js +32 -42
  50. package/lib/ReactNativeComponent.js +45 -8
  51. package/lib/ReactOwner.js +3 -47
  52. package/lib/ReactPerf.js +20 -0
  53. package/lib/ReactPropTransferer.js +0 -55
  54. package/lib/ReactPropTypes.js +1 -17
  55. package/lib/ReactRef.js +96 -0
  56. package/lib/ReactServerRendering.js +3 -2
  57. package/lib/ReactTestUtils.js +82 -25
  58. package/lib/ReactTransitionGroup.js +47 -6
  59. package/lib/ReactUpdates.js +43 -42
  60. package/lib/SyntheticMouseEvent.js +1 -3
  61. package/lib/ViewportMetrics.js +1 -4
  62. package/lib/accumulate.js +47 -0
  63. package/lib/cloneWithProps.js +2 -2
  64. package/lib/copyProperties.js +2 -0
  65. package/lib/createFullPageComponent.js +2 -2
  66. package/lib/findDOMNode.js +52 -0
  67. package/lib/flattenChildren.js +1 -14
  68. package/lib/getIteratorFn.js +42 -0
  69. package/lib/instantiateReactComponent.js +88 -65
  70. package/lib/isNode.js +3 -4
  71. package/lib/isTextInputElement.js +1 -2
  72. package/lib/shouldUpdateReactComponent.js +13 -5
  73. package/lib/traverseAllChildren.js +110 -54
  74. package/package.json +1 -1
  75. package/lib/CompositionEventPlugin.js +0 -257
  76. package/lib/ReactLegacyElement.js +0 -243
  77. package/lib/deprecated.js +0 -47
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright 2014, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactComponentEnvironment
10
+ */
11
+
12
+ "use strict";
13
+
14
+ var invariant = require("./invariant");
15
+
16
+ var injected = false;
17
+
18
+ var ReactComponentEnvironment = {
19
+
20
+ /**
21
+ * Optionally injectable environment dependent cleanup hook. (server vs.
22
+ * browser etc). Example: A browser system caches DOM nodes based on component
23
+ * ID and must remove that cache entry when this instance is unmounted.
24
+ */
25
+ unmountIDFromEnvironment: null,
26
+
27
+ /**
28
+ * Optionally injectable hook for swapping out mount images in the middle of
29
+ * the tree.
30
+ */
31
+ replaceNodeWithMarkupByID: null,
32
+
33
+ /**
34
+ * Optionally injectable hook for processing a queue of child updates. Will
35
+ * later move into MultiChildComponents.
36
+ */
37
+ processChildrenUpdates: null,
38
+
39
+ injection: {
40
+ injectEnvironment: function(environment) {
41
+ ("production" !== process.env.NODE_ENV ? invariant(
42
+ !injected,
43
+ 'ReactCompositeComponent: injectEnvironment() can only be called once.'
44
+ ) : invariant(!injected));
45
+ ReactComponentEnvironment.unmountIDFromEnvironment =
46
+ environment.unmountIDFromEnvironment;
47
+ ReactComponentEnvironment.replaceNodeWithMarkupByID =
48
+ environment.replaceNodeWithMarkupByID;
49
+ ReactComponentEnvironment.processChildrenUpdates =
50
+ environment.processChildrenUpdates;
51
+ injected = true;
52
+ }
53
+ },
54
+
55
+ };
56
+
57
+ module.exports = ReactComponentEnvironment;
@@ -12,446 +12,36 @@
12
12
  "use strict";
13
13
 
14
14
  var ReactComponent = require("./ReactComponent");
15
+ var ReactComponentEnvironment = require("./ReactComponentEnvironment");
15
16
  var ReactContext = require("./ReactContext");
16
17
  var ReactCurrentOwner = require("./ReactCurrentOwner");
17
18
  var ReactElement = require("./ReactElement");
18
- var ReactElementValidator = require("./ReactElementValidator");
19
- var ReactEmptyComponent = require("./ReactEmptyComponent");
20
- var ReactErrorUtils = require("./ReactErrorUtils");
21
- var ReactLegacyElement = require("./ReactLegacyElement");
22
- var ReactOwner = require("./ReactOwner");
19
+ var ReactInstanceMap = require("./ReactInstanceMap");
23
20
  var ReactPerf = require("./ReactPerf");
24
- var ReactPropTransferer = require("./ReactPropTransferer");
25
21
  var ReactPropTypeLocations = require("./ReactPropTypeLocations");
26
- var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
27
22
  var ReactUpdates = require("./ReactUpdates");
28
23
 
29
24
  var assign = require("./Object.assign");
30
- var instantiateReactComponent = require("./instantiateReactComponent");
25
+ var emptyObject = require("./emptyObject");
31
26
  var invariant = require("./invariant");
32
27
  var keyMirror = require("./keyMirror");
33
- var keyOf = require("./keyOf");
34
- var monitorCodeUse = require("./monitorCodeUse");
35
- var mapObject = require("./mapObject");
36
28
  var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
37
29
  var warning = require("./warning");
38
30
 
39
- var MIXINS_KEY = keyOf({mixins: null});
40
-
41
- /**
42
- * Policies that describe methods in `ReactCompositeComponentInterface`.
43
- */
44
- var SpecPolicy = keyMirror({
45
- /**
46
- * These methods may be defined only once by the class specification or mixin.
47
- */
48
- DEFINE_ONCE: null,
49
- /**
50
- * These methods may be defined by both the class specification and mixins.
51
- * Subsequent definitions will be chained. These methods must return void.
52
- */
53
- DEFINE_MANY: null,
54
- /**
55
- * These methods are overriding the base ReactCompositeComponent class.
56
- */
57
- OVERRIDE_BASE: null,
58
- /**
59
- * These methods are similar to DEFINE_MANY, except we assume they return
60
- * objects. We try to merge the keys of the return values of all the mixed in
61
- * functions. If there is a key conflict we throw.
62
- */
63
- DEFINE_MANY_MERGED: null
64
- });
65
-
66
-
67
- var injectedMixins = [];
68
-
69
- /**
70
- * Composite components are higher-level components that compose other composite
71
- * or native components.
72
- *
73
- * To create a new type of `ReactCompositeComponent`, pass a specification of
74
- * your new class to `React.createClass`. The only requirement of your class
75
- * specification is that you implement a `render` method.
76
- *
77
- * var MyComponent = React.createClass({
78
- * render: function() {
79
- * return <div>Hello World</div>;
80
- * }
81
- * });
82
- *
83
- * The class specification supports a specific protocol of methods that have
84
- * special meaning (e.g. `render`). See `ReactCompositeComponentInterface` for
85
- * more the comprehensive protocol. Any other properties and methods in the
86
- * class specification will available on the prototype.
87
- *
88
- * @interface ReactCompositeComponentInterface
89
- * @internal
90
- */
91
- var ReactCompositeComponentInterface = {
92
-
93
- /**
94
- * An array of Mixin objects to include when defining your component.
95
- *
96
- * @type {array}
97
- * @optional
98
- */
99
- mixins: SpecPolicy.DEFINE_MANY,
100
-
101
- /**
102
- * An object containing properties and methods that should be defined on
103
- * the component's constructor instead of its prototype (static methods).
104
- *
105
- * @type {object}
106
- * @optional
107
- */
108
- statics: SpecPolicy.DEFINE_MANY,
109
-
110
- /**
111
- * Definition of prop types for this component.
112
- *
113
- * @type {object}
114
- * @optional
115
- */
116
- propTypes: SpecPolicy.DEFINE_MANY,
117
-
118
- /**
119
- * Definition of context types for this component.
120
- *
121
- * @type {object}
122
- * @optional
123
- */
124
- contextTypes: SpecPolicy.DEFINE_MANY,
125
-
126
- /**
127
- * Definition of context types this component sets for its children.
128
- *
129
- * @type {object}
130
- * @optional
131
- */
132
- childContextTypes: SpecPolicy.DEFINE_MANY,
133
-
134
- // ==== Definition methods ====
135
-
136
- /**
137
- * Invoked when the component is mounted. Values in the mapping will be set on
138
- * `this.props` if that prop is not specified (i.e. using an `in` check).
139
- *
140
- * This method is invoked before `getInitialState` and therefore cannot rely
141
- * on `this.state` or use `this.setState`.
142
- *
143
- * @return {object}
144
- * @optional
145
- */
146
- getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,
147
-
148
- /**
149
- * Invoked once before the component is mounted. The return value will be used
150
- * as the initial value of `this.state`.
151
- *
152
- * getInitialState: function() {
153
- * return {
154
- * isOn: false,
155
- * fooBaz: new BazFoo()
156
- * }
157
- * }
158
- *
159
- * @return {object}
160
- * @optional
161
- */
162
- getInitialState: SpecPolicy.DEFINE_MANY_MERGED,
163
-
164
- /**
165
- * @return {object}
166
- * @optional
167
- */
168
- getChildContext: SpecPolicy.DEFINE_MANY_MERGED,
169
-
170
- /**
171
- * Uses props from `this.props` and state from `this.state` to render the
172
- * structure of the component.
173
- *
174
- * No guarantees are made about when or how often this method is invoked, so
175
- * it must not have side effects.
176
- *
177
- * render: function() {
178
- * var name = this.props.name;
179
- * return <div>Hello, {name}!</div>;
180
- * }
181
- *
182
- * @return {ReactComponent}
183
- * @nosideeffects
184
- * @required
185
- */
186
- render: SpecPolicy.DEFINE_ONCE,
187
-
188
-
189
-
190
- // ==== Delegate methods ====
191
-
192
- /**
193
- * Invoked when the component is initially created and about to be mounted.
194
- * This may have side effects, but any external subscriptions or data created
195
- * by this method must be cleaned up in `componentWillUnmount`.
196
- *
197
- * @optional
198
- */
199
- componentWillMount: SpecPolicy.DEFINE_MANY,
200
-
201
- /**
202
- * Invoked when the component has been mounted and has a DOM representation.
203
- * However, there is no guarantee that the DOM node is in the document.
204
- *
205
- * Use this as an opportunity to operate on the DOM when the component has
206
- * been mounted (initialized and rendered) for the first time.
207
- *
208
- * @param {DOMElement} rootNode DOM element representing the component.
209
- * @optional
210
- */
211
- componentDidMount: SpecPolicy.DEFINE_MANY,
212
-
213
- /**
214
- * Invoked before the component receives new props.
215
- *
216
- * Use this as an opportunity to react to a prop transition by updating the
217
- * state using `this.setState`. Current props are accessed via `this.props`.
218
- *
219
- * componentWillReceiveProps: function(nextProps, nextContext) {
220
- * this.setState({
221
- * likesIncreasing: nextProps.likeCount > this.props.likeCount
222
- * });
223
- * }
224
- *
225
- * NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop
226
- * transition may cause a state change, but the opposite is not true. If you
227
- * need it, you are probably looking for `componentWillUpdate`.
228
- *
229
- * @param {object} nextProps
230
- * @optional
231
- */
232
- componentWillReceiveProps: SpecPolicy.DEFINE_MANY,
233
-
234
- /**
235
- * Invoked while deciding if the component should be updated as a result of
236
- * receiving new props, state and/or context.
237
- *
238
- * Use this as an opportunity to `return false` when you're certain that the
239
- * transition to the new props/state/context will not require a component
240
- * update.
241
- *
242
- * shouldComponentUpdate: function(nextProps, nextState, nextContext) {
243
- * return !equal(nextProps, this.props) ||
244
- * !equal(nextState, this.state) ||
245
- * !equal(nextContext, this.context);
246
- * }
247
- *
248
- * @param {object} nextProps
249
- * @param {?object} nextState
250
- * @param {?object} nextContext
251
- * @return {boolean} True if the component should update.
252
- * @optional
253
- */
254
- shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,
255
-
256
- /**
257
- * Invoked when the component is about to update due to a transition from
258
- * `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`
259
- * and `nextContext`.
260
- *
261
- * Use this as an opportunity to perform preparation before an update occurs.
262
- *
263
- * NOTE: You **cannot** use `this.setState()` in this method.
264
- *
265
- * @param {object} nextProps
266
- * @param {?object} nextState
267
- * @param {?object} nextContext
268
- * @param {ReactReconcileTransaction} transaction
269
- * @optional
270
- */
271
- componentWillUpdate: SpecPolicy.DEFINE_MANY,
272
-
273
- /**
274
- * Invoked when the component's DOM representation has been updated.
275
- *
276
- * Use this as an opportunity to operate on the DOM when the component has
277
- * been updated.
278
- *
279
- * @param {object} prevProps
280
- * @param {?object} prevState
281
- * @param {?object} prevContext
282
- * @param {DOMElement} rootNode DOM element representing the component.
283
- * @optional
284
- */
285
- componentDidUpdate: SpecPolicy.DEFINE_MANY,
286
-
287
- /**
288
- * Invoked when the component is about to be removed from its parent and have
289
- * its DOM representation destroyed.
290
- *
291
- * Use this as an opportunity to deallocate any external resources.
292
- *
293
- * NOTE: There is no `componentDidUnmount` since your component will have been
294
- * destroyed by that point.
295
- *
296
- * @optional
297
- */
298
- componentWillUnmount: SpecPolicy.DEFINE_MANY,
299
-
300
-
301
-
302
- // ==== Advanced methods ====
303
-
304
- /**
305
- * Updates the component's currently mounted DOM representation.
306
- *
307
- * By default, this implements React's rendering and reconciliation algorithm.
308
- * Sophisticated clients may wish to override this.
309
- *
310
- * @param {ReactReconcileTransaction} transaction
311
- * @internal
312
- * @overridable
313
- */
314
- updateComponent: SpecPolicy.OVERRIDE_BASE
315
-
316
- };
317
-
318
- /**
319
- * Mapping from class specification keys to special processing functions.
320
- *
321
- * Although these are declared like instance properties in the specification
322
- * when defining classes using `React.createClass`, they are actually static
323
- * and are accessible on the constructor instead of the prototype. Despite
324
- * being static, they must be defined outside of the "statics" key under
325
- * which all other static methods are defined.
326
- */
327
- var RESERVED_SPEC_KEYS = {
328
- displayName: function(Constructor, displayName) {
329
- Constructor.displayName = displayName;
330
- },
331
- mixins: function(Constructor, mixins) {
332
- if (mixins) {
333
- for (var i = 0; i < mixins.length; i++) {
334
- mixSpecIntoComponent(Constructor, mixins[i]);
335
- }
336
- }
337
- },
338
- childContextTypes: function(Constructor, childContextTypes) {
339
- validateTypeDef(
340
- Constructor,
341
- childContextTypes,
342
- ReactPropTypeLocations.childContext
343
- );
344
- Constructor.childContextTypes = assign(
345
- {},
346
- Constructor.childContextTypes,
347
- childContextTypes
348
- );
349
- },
350
- contextTypes: function(Constructor, contextTypes) {
351
- validateTypeDef(
352
- Constructor,
353
- contextTypes,
354
- ReactPropTypeLocations.context
355
- );
356
- Constructor.contextTypes = assign(
357
- {},
358
- Constructor.contextTypes,
359
- contextTypes
360
- );
361
- },
362
- /**
363
- * Special case getDefaultProps which should move into statics but requires
364
- * automatic merging.
365
- */
366
- getDefaultProps: function(Constructor, getDefaultProps) {
367
- if (Constructor.getDefaultProps) {
368
- Constructor.getDefaultProps = createMergedResultFunction(
369
- Constructor.getDefaultProps,
370
- getDefaultProps
371
- );
372
- } else {
373
- Constructor.getDefaultProps = getDefaultProps;
374
- }
375
- },
376
- propTypes: function(Constructor, propTypes) {
377
- validateTypeDef(
378
- Constructor,
379
- propTypes,
380
- ReactPropTypeLocations.prop
381
- );
382
- Constructor.propTypes = assign(
383
- {},
384
- Constructor.propTypes,
385
- propTypes
386
- );
387
- },
388
- statics: function(Constructor, statics) {
389
- mixStaticSpecIntoComponent(Constructor, statics);
390
- }
391
- };
392
-
393
31
  function getDeclarationErrorAddendum(component) {
394
- var owner = component._owner || null;
395
- if (owner && owner.constructor && owner.constructor.displayName) {
396
- return ' Check the render method of `' + owner.constructor.displayName +
397
- '`.';
398
- }
399
- return '';
400
- }
401
-
402
- function validateTypeDef(Constructor, typeDef, location) {
403
- for (var propName in typeDef) {
404
- if (typeDef.hasOwnProperty(propName)) {
405
- ("production" !== process.env.NODE_ENV ? invariant(
406
- typeof typeDef[propName] == 'function',
407
- '%s: %s type `%s` is invalid; it must be a function, usually from ' +
408
- 'React.PropTypes.',
409
- Constructor.displayName || 'ReactCompositeComponent',
410
- ReactPropTypeLocationNames[location],
411
- propName
412
- ) : invariant(typeof typeDef[propName] == 'function'));
32
+ var owner = component._currentElement._owner || null;
33
+ if (owner) {
34
+ var constructor = owner._instance.constructor;
35
+ var name = constructor && (constructor.displayName || constructor.name);
36
+ if (name) {
37
+ return ' Check the render method of `' + name + '`.';
413
38
  }
414
39
  }
415
- }
416
-
417
- function validateMethodOverride(proto, name) {
418
- var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
419
- ReactCompositeComponentInterface[name] :
420
- null;
421
-
422
- // Disallow overriding of base class methods unless explicitly allowed.
423
- if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
424
- ("production" !== process.env.NODE_ENV ? invariant(
425
- specPolicy === SpecPolicy.OVERRIDE_BASE,
426
- 'ReactCompositeComponentInterface: You are attempting to override ' +
427
- '`%s` from your class specification. Ensure that your method names ' +
428
- 'do not overlap with React methods.',
429
- name
430
- ) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE));
431
- }
432
-
433
- // Disallow defining methods more than once unless explicitly allowed.
434
- if (proto.hasOwnProperty(name)) {
435
- ("production" !== process.env.NODE_ENV ? invariant(
436
- specPolicy === SpecPolicy.DEFINE_MANY ||
437
- specPolicy === SpecPolicy.DEFINE_MANY_MERGED,
438
- 'ReactCompositeComponentInterface: You are attempting to define ' +
439
- '`%s` on your component more than once. This conflict may be due ' +
440
- 'to a mixin.',
441
- name
442
- ) : invariant(specPolicy === SpecPolicy.DEFINE_MANY ||
443
- specPolicy === SpecPolicy.DEFINE_MANY_MERGED));
444
- }
40
+ return '';
445
41
  }
446
42
 
447
43
  function validateLifeCycleOnReplaceState(instance) {
448
44
  var compositeLifeCycleState = instance._compositeLifeCycleState;
449
- ("production" !== process.env.NODE_ENV ? invariant(
450
- instance.isMounted() ||
451
- compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
452
- 'replaceState(...): Can only update a mounted or mounting component.'
453
- ) : invariant(instance.isMounted() ||
454
- compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
455
45
  ("production" !== process.env.NODE_ENV ? invariant(
456
46
  ReactCurrentOwner.current == null,
457
47
  'replaceState(...): Cannot update during an existing state transition ' +
@@ -464,215 +54,12 @@ function validateLifeCycleOnReplaceState(instance) {
464
54
  ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
465
55
  }
466
56
 
467
- /**
468
- * Mixin helper which handles policy validation and reserved
469
- * specification keys when building `ReactCompositeComponent` classses.
470
- */
471
- function mixSpecIntoComponent(Constructor, spec) {
472
- if (!spec) {
473
- return;
474
- }
475
-
476
- ("production" !== process.env.NODE_ENV ? invariant(
477
- !ReactLegacyElement.isValidFactory(spec),
478
- 'ReactCompositeComponent: You\'re attempting to ' +
479
- 'use a component class as a mixin. Instead, just use a regular object.'
480
- ) : invariant(!ReactLegacyElement.isValidFactory(spec)));
481
- ("production" !== process.env.NODE_ENV ? invariant(
482
- !ReactElement.isValidElement(spec),
483
- 'ReactCompositeComponent: You\'re attempting to ' +
484
- 'use a component as a mixin. Instead, just use a regular object.'
485
- ) : invariant(!ReactElement.isValidElement(spec)));
486
-
487
- var proto = Constructor.prototype;
488
-
489
- // By handling mixins before any other properties, we ensure the same
490
- // chaining order is applied to methods with DEFINE_MANY policy, whether
491
- // mixins are listed before or after these methods in the spec.
492
- if (spec.hasOwnProperty(MIXINS_KEY)) {
493
- RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
494
- }
495
-
496
- for (var name in spec) {
497
- if (!spec.hasOwnProperty(name)) {
498
- continue;
499
- }
500
-
501
- if (name === MIXINS_KEY) {
502
- // We have already handled mixins in a special case above
503
- continue;
504
- }
505
-
506
- var property = spec[name];
507
- validateMethodOverride(proto, name);
508
-
509
- if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
510
- RESERVED_SPEC_KEYS[name](Constructor, property);
511
- } else {
512
- // Setup methods on prototype:
513
- // The following member methods should not be automatically bound:
514
- // 1. Expected ReactCompositeComponent methods (in the "interface").
515
- // 2. Overridden methods (that were mixed in).
516
- var isCompositeComponentMethod =
517
- ReactCompositeComponentInterface.hasOwnProperty(name);
518
- var isAlreadyDefined = proto.hasOwnProperty(name);
519
- var markedDontBind = property && property.__reactDontBind;
520
- var isFunction = typeof property === 'function';
521
- var shouldAutoBind =
522
- isFunction &&
523
- !isCompositeComponentMethod &&
524
- !isAlreadyDefined &&
525
- !markedDontBind;
526
-
527
- if (shouldAutoBind) {
528
- if (!proto.__reactAutoBindMap) {
529
- proto.__reactAutoBindMap = {};
530
- }
531
- proto.__reactAutoBindMap[name] = property;
532
- proto[name] = property;
533
- } else {
534
- if (isAlreadyDefined) {
535
- var specPolicy = ReactCompositeComponentInterface[name];
536
-
537
- // These cases should already be caught by validateMethodOverride
538
- ("production" !== process.env.NODE_ENV ? invariant(
539
- isCompositeComponentMethod && (
540
- specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
541
- specPolicy === SpecPolicy.DEFINE_MANY
542
- ),
543
- 'ReactCompositeComponent: Unexpected spec policy %s for key %s ' +
544
- 'when mixing in component specs.',
545
- specPolicy,
546
- name
547
- ) : invariant(isCompositeComponentMethod && (
548
- specPolicy === SpecPolicy.DEFINE_MANY_MERGED ||
549
- specPolicy === SpecPolicy.DEFINE_MANY
550
- )));
551
-
552
- // For methods which are defined more than once, call the existing
553
- // methods before calling the new property, merging if appropriate.
554
- if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
555
- proto[name] = createMergedResultFunction(proto[name], property);
556
- } else if (specPolicy === SpecPolicy.DEFINE_MANY) {
557
- proto[name] = createChainedFunction(proto[name], property);
558
- }
559
- } else {
560
- proto[name] = property;
561
- if ("production" !== process.env.NODE_ENV) {
562
- // Add verbose displayName to the function, which helps when looking
563
- // at profiling tools.
564
- if (typeof property === 'function' && spec.displayName) {
565
- proto[name].displayName = spec.displayName + '_' + name;
566
- }
567
- }
568
- }
569
- }
570
- }
571
- }
572
- }
573
-
574
- function mixStaticSpecIntoComponent(Constructor, statics) {
575
- if (!statics) {
576
- return;
577
- }
578
- for (var name in statics) {
579
- var property = statics[name];
580
- if (!statics.hasOwnProperty(name)) {
581
- continue;
582
- }
583
-
584
- var isReserved = name in RESERVED_SPEC_KEYS;
585
- ("production" !== process.env.NODE_ENV ? invariant(
586
- !isReserved,
587
- 'ReactCompositeComponent: You are attempting to define a reserved ' +
588
- 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
589
- 'as an instance property instead; it will still be accessible on the ' +
590
- 'constructor.',
591
- name
592
- ) : invariant(!isReserved));
593
-
594
- var isInherited = name in Constructor;
595
- ("production" !== process.env.NODE_ENV ? invariant(
596
- !isInherited,
597
- 'ReactCompositeComponent: You are attempting to define ' +
598
- '`%s` on your component more than once. This conflict may be ' +
599
- 'due to a mixin.',
600
- name
601
- ) : invariant(!isInherited));
602
- Constructor[name] = property;
603
- }
604
- }
605
-
606
- /**
607
- * Merge two objects, but throw if both contain the same key.
608
- *
609
- * @param {object} one The first object, which is mutated.
610
- * @param {object} two The second object
611
- * @return {object} one after it has been mutated to contain everything in two.
612
- */
613
- function mergeObjectsWithNoDuplicateKeys(one, two) {
614
- ("production" !== process.env.NODE_ENV ? invariant(
615
- one && two && typeof one === 'object' && typeof two === 'object',
616
- 'mergeObjectsWithNoDuplicateKeys(): Cannot merge non-objects'
617
- ) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));
618
-
619
- mapObject(two, function(value, key) {
620
- ("production" !== process.env.NODE_ENV ? invariant(
621
- one[key] === undefined,
622
- 'mergeObjectsWithNoDuplicateKeys(): ' +
623
- 'Tried to merge two objects with the same key: `%s`. This conflict ' +
624
- 'may be due to a mixin; in particular, this may be caused by two ' +
625
- 'getInitialState() or getDefaultProps() methods returning objects ' +
626
- 'with clashing keys.',
627
- key
628
- ) : invariant(one[key] === undefined));
629
- one[key] = value;
630
- });
631
- return one;
632
- }
633
-
634
- /**
635
- * Creates a function that invokes two functions and merges their return values.
636
- *
637
- * @param {function} one Function to invoke first.
638
- * @param {function} two Function to invoke second.
639
- * @return {function} Function that invokes the two argument functions.
640
- * @private
641
- */
642
- function createMergedResultFunction(one, two) {
643
- return function mergedResult() {
644
- var a = one.apply(this, arguments);
645
- var b = two.apply(this, arguments);
646
- if (a == null) {
647
- return b;
648
- } else if (b == null) {
649
- return a;
650
- }
651
- return mergeObjectsWithNoDuplicateKeys(a, b);
652
- };
653
- }
654
-
655
- /**
656
- * Creates a function that invokes two functions and ignores their return vales.
657
- *
658
- * @param {function} one Function to invoke first.
659
- * @param {function} two Function to invoke second.
660
- * @return {function} Function that invokes the two argument functions.
661
- * @private
662
- */
663
- function createChainedFunction(one, two) {
664
- return function chainedFunction() {
665
- one.apply(this, arguments);
666
- two.apply(this, arguments);
667
- };
668
- }
669
-
670
57
  /**
671
58
  * `ReactCompositeComponent` maintains an auxiliary life cycle state in
672
59
  * `this._compositeLifeCycleState` (which can be null).
673
60
  *
674
- * This is different from the life cycle state maintained by `ReactComponent` in
675
- * `this._lifeCycleState`. The following diagram shows how the states overlap in
61
+ * This is different from the life cycle state maintained by `ReactComponent`.
62
+ * The following diagram shows how the states overlap in
676
63
  * time. There are times when the CompositeLifeCycle is null - at those times it
677
64
  * is only meaningful to look at ComponentLifeCycle alone.
678
65
  *
@@ -711,10 +98,19 @@ var CompositeLifeCycle = keyMirror({
711
98
  RECEIVING_PROPS: null
712
99
  });
713
100
 
101
+ /**
102
+ * An incrementing ID assigned to each component when it is mounted. This is
103
+ * used to enforce the order in which `ReactUpdates` updates dirty components.
104
+ *
105
+ * @private
106
+ */
107
+ var nextMountID = 1;
108
+
714
109
  /**
715
110
  * @lends {ReactCompositeComponent.prototype}
716
111
  */
717
- var ReactCompositeComponentMixin = {
112
+ var ReactCompositeComponentMixin = assign({},
113
+ ReactComponent.Mixin, {
718
114
 
719
115
  /**
720
116
  * Base constructor for all composite component.
@@ -724,18 +120,30 @@ var ReactCompositeComponentMixin = {
724
120
  * @internal
725
121
  */
726
122
  construct: function(element) {
727
- // Children can be either an array or more than one argument
728
- ReactComponent.Mixin.construct.apply(this, arguments);
729
- ReactOwner.Mixin.construct.apply(this, arguments);
123
+ this._rootNodeID = null;
730
124
 
731
- this.state = null;
125
+ this._instance.props = element.props;
126
+ this._instance.state = null;
127
+ this._instance.context = null;
128
+ this._instance.refs = emptyObject;
129
+
130
+ this._pendingElement = null;
131
+ this._pendingContext = null;
732
132
  this._pendingState = null;
133
+ this._pendingForceUpdate = false;
134
+ this._compositeLifeCycleState = null;
733
135
 
734
- // This is the public post-processed context. The real context and pending
735
- // context lives on the element.
736
- this.context = null;
136
+ this._renderedComponent = null;
737
137
 
738
- this._compositeLifeCycleState = null;
138
+ // Children can be either an array or more than one argument
139
+ ReactComponent.Mixin.construct.apply(this, arguments);
140
+
141
+ this._context = null;
142
+ this._mountOrder = 0;
143
+ this._isTopLevel = false;
144
+
145
+ // See ReactUpdates.
146
+ this._pendingCallbacks = null;
739
147
  },
740
148
 
741
149
  /**
@@ -745,8 +153,7 @@ var ReactCompositeComponentMixin = {
745
153
  * @final
746
154
  */
747
155
  isMounted: function() {
748
- return ReactComponent.Mixin.isMounted.call(this) &&
749
- this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
156
+ return this._compositeLifeCycleState !== CompositeLifeCycle.MOUNTING;
750
157
  },
751
158
 
752
159
  /**
@@ -754,68 +161,83 @@ var ReactCompositeComponentMixin = {
754
161
  *
755
162
  * @param {string} rootID DOM ID of the root node.
756
163
  * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
757
- * @param {number} mountDepth number of components in the owner hierarchy
758
164
  * @return {?string} Rendered markup to be inserted into the DOM.
759
165
  * @final
760
166
  * @internal
761
167
  */
762
- mountComponent: ReactPerf.measure(
763
- 'ReactCompositeComponent',
764
- 'mountComponent',
765
- function(rootID, transaction, mountDepth) {
766
- ReactComponent.Mixin.mountComponent.call(
767
- this,
768
- rootID,
769
- transaction,
770
- mountDepth
771
- );
772
- this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
168
+ mountComponent: function(rootID, transaction, context) {
169
+ ReactComponent.Mixin.mountComponent.call(
170
+ this,
171
+ rootID,
172
+ transaction,
173
+ context
174
+ );
773
175
 
774
- if (this.__reactAutoBindMap) {
775
- this._bindAutoBindMethods();
776
- }
176
+ this._context = context;
177
+ this._mountOrder = nextMountID++;
178
+ this._rootNodeID = rootID;
777
179
 
778
- this.context = this._processContext(this._currentElement._context);
779
- this.props = this._processProps(this.props);
180
+ var inst = this._instance;
780
181
 
781
- this.state = this.getInitialState ? this.getInitialState() : null;
782
- ("production" !== process.env.NODE_ENV ? invariant(
783
- typeof this.state === 'object' && !Array.isArray(this.state),
784
- '%s.getInitialState(): must return an object or null',
785
- this.constructor.displayName || 'ReactCompositeComponent'
786
- ) : invariant(typeof this.state === 'object' && !Array.isArray(this.state)));
787
-
788
- this._pendingState = null;
789
- this._pendingForceUpdate = false;
790
-
791
- if (this.componentWillMount) {
792
- this.componentWillMount();
793
- // When mounting, calls to `setState` by `componentWillMount` will set
794
- // `this._pendingState` without triggering a re-render.
795
- if (this._pendingState) {
796
- this.state = this._pendingState;
797
- this._pendingState = null;
798
- }
799
- }
182
+ // Store a reference from the instance back to the internal representation
183
+ ReactInstanceMap.set(inst, this);
800
184
 
801
- this._renderedComponent = instantiateReactComponent(
802
- this._renderValidatedComponent(),
803
- this._currentElement.type // The wrapping type
804
- );
185
+ this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
805
186
 
806
- // Done with mounting, `setState` will now trigger UI changes.
807
- this._compositeLifeCycleState = null;
808
- var markup = this._renderedComponent.mountComponent(
809
- rootID,
810
- transaction,
811
- mountDepth + 1
812
- );
813
- if (this.componentDidMount) {
814
- transaction.getReactMountReady().enqueue(this.componentDidMount, this);
187
+ inst.context = this._processContext(this._currentElement._context);
188
+ if ("production" !== process.env.NODE_ENV) {
189
+ this._warnIfContextsDiffer(this._currentElement._context, context);
190
+ }
191
+ inst.props = this._processProps(this._currentElement.props);
192
+
193
+ var initialState = inst.getInitialState ? inst.getInitialState() : null;
194
+ 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
+ }
203
+ ("production" !== process.env.NODE_ENV ? invariant(
204
+ typeof initialState === 'object' && !Array.isArray(initialState),
205
+ '%s.getInitialState(): must return an object or null',
206
+ inst.constructor.displayName || 'ReactCompositeComponent'
207
+ ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
208
+ inst.state = initialState;
209
+
210
+ this._pendingState = null;
211
+ this._pendingForceUpdate = false;
212
+
213
+ if (inst.componentWillMount) {
214
+ inst.componentWillMount();
215
+ // When mounting, calls to `setState` by `componentWillMount` will set
216
+ // `this._pendingState` without triggering a re-render.
217
+ if (this._pendingState) {
218
+ inst.state = this._pendingState;
219
+ this._pendingState = null;
815
220
  }
816
- return markup;
817
221
  }
818
- ),
222
+
223
+ var renderedElement = this._renderValidatedComponent();
224
+ this._renderedComponent = this._instantiateReactComponent(
225
+ renderedElement,
226
+ this._currentElement.type // The wrapping type
227
+ );
228
+
229
+ // Done with mounting, `setState` will now trigger UI changes.
230
+ this._compositeLifeCycleState = null;
231
+ var markup = this._renderedComponent.mountComponent(
232
+ rootID,
233
+ transaction,
234
+ this._processChildContext(context)
235
+ );
236
+ if (inst.componentDidMount) {
237
+ transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
238
+ }
239
+ return markup;
240
+ },
819
241
 
820
242
  /**
821
243
  * Releases any resources allocated by `mountComponent`.
@@ -824,34 +246,110 @@ var ReactCompositeComponentMixin = {
824
246
  * @internal
825
247
  */
826
248
  unmountComponent: function() {
249
+ var inst = this._instance;
250
+
827
251
  this._compositeLifeCycleState = CompositeLifeCycle.UNMOUNTING;
828
- if (this.componentWillUnmount) {
829
- this.componentWillUnmount();
252
+ if (inst.componentWillUnmount) {
253
+ inst.componentWillUnmount();
830
254
  }
831
255
  this._compositeLifeCycleState = null;
832
256
 
833
257
  this._renderedComponent.unmountComponent();
834
258
  this._renderedComponent = null;
835
259
 
260
+ // Reset pending fields
261
+ this._pendingState = null;
262
+ this._pendingForceUpdate = false;
263
+ this._pendingCallbacks = null;
264
+ this._pendingElement = null;
265
+
836
266
  ReactComponent.Mixin.unmountComponent.call(this);
837
267
 
838
- // Some existing components rely on this.props even after they've been
268
+ ReactComponentEnvironment.unmountIDFromEnvironment(this._rootNodeID);
269
+
270
+ this._context = null;
271
+ this._rootNodeID = null;
272
+
273
+ // Delete the reference from the instance to this internal representation
274
+ // which allow the internals to be properly cleaned up even if the user
275
+ // leaks a reference to the public instance.
276
+ ReactInstanceMap.remove(inst);
277
+
278
+ // Some existing components rely on inst.props even after they've been
839
279
  // destroyed (in event handlers).
840
- // TODO: this.props = null;
841
- // TODO: this.state = null;
280
+ // TODO: inst.props = null;
281
+ // TODO: inst.state = null;
282
+ // TODO: inst.context = null;
842
283
  },
843
284
 
844
285
  /**
845
- * Sets a subset of the state. Always use this or `replaceState` to mutate
846
- * state. You should treat `this.state` as immutable.
286
+ * Sets a subset of the props.
847
287
  *
848
- * There is no guarantee that `this.state` will be immediately updated, so
849
- * accessing `this.state` after calling this method may return the old value.
288
+ * @param {object} partialProps Subset of the next props.
289
+ * @param {?function} callback Called after props are updated.
290
+ * @final
291
+ * @public
292
+ */
293
+ setProps: function(partialProps, callback) {
294
+ // Merge with the pending element if it exists, otherwise with existing
295
+ // element props.
296
+ var element = this._pendingElement || this._currentElement;
297
+ this.replaceProps(
298
+ assign({}, element.props, partialProps),
299
+ callback
300
+ );
301
+ },
302
+
303
+ /**
304
+ * Replaces all of the props.
305
+ *
306
+ * @param {object} props New props.
307
+ * @param {?function} callback Called after props are updated.
308
+ * @final
309
+ * @public
310
+ */
311
+ replaceProps: function(props, callback) {
312
+ ("production" !== process.env.NODE_ENV ? invariant(
313
+ this._isTopLevel,
314
+ 'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
315
+ 'component with a parent. This is an anti-pattern since props will ' +
316
+ 'get reactively updated when rendered. Instead, change the owner\'s ' +
317
+ '`render` method to pass the correct value as props to the component ' +
318
+ 'where it is created.'
319
+ ) : invariant(this._isTopLevel));
320
+ // This is a deoptimized path. We optimize for always having an element.
321
+ // This creates an extra internal element.
322
+ this._pendingElement = ReactElement.cloneAndReplaceProps(
323
+ this._pendingElement || this._currentElement,
324
+ props
325
+ );
326
+ ReactUpdates.enqueueUpdate(this, callback);
327
+ },
328
+
329
+ /**
330
+ * Schedule a partial update to the props. Only used for internal testing.
850
331
  *
851
- * There is no guarantee that calls to `setState` will run synchronously,
852
- * as they may eventually be batched together. You can provide an optional
853
- * callback that will be executed when the call to setState is actually
854
- * completed.
332
+ * @param {object} partialProps Subset of the next props.
333
+ * @param {?function} callback Called after props are updated.
334
+ * @final
335
+ * @internal
336
+ */
337
+ _setPropsInternal: function(partialProps, callback) {
338
+ // This is a deoptimized path. We optimize for always having an element.
339
+ // This creates an extra internal element.
340
+ var element = this._pendingElement || this._currentElement;
341
+ this._pendingElement = ReactElement.cloneAndReplaceProps(
342
+ element,
343
+ assign({}, element.props, partialProps)
344
+ );
345
+ ReactUpdates.enqueueUpdate(this, callback);
346
+ },
347
+
348
+ /**
349
+ * Sets a subset of the state. This only exists because _pendingState is
350
+ * internal. This provides a merging strategy that is not available to deep
351
+ * properties which is confusing. TODO: Expose pendingState or don't use it
352
+ * during the merge.
855
353
  *
856
354
  * @param {object} partialState Next partial state to be merged with state.
857
355
  * @param {?function} callback Called after state is updated.
@@ -859,20 +357,9 @@ var ReactCompositeComponentMixin = {
859
357
  * @protected
860
358
  */
861
359
  setState: function(partialState, callback) {
862
- ("production" !== process.env.NODE_ENV ? invariant(
863
- typeof partialState === 'object' || partialState == null,
864
- 'setState(...): takes an object of state variables to update.'
865
- ) : invariant(typeof partialState === 'object' || partialState == null));
866
- if ("production" !== process.env.NODE_ENV){
867
- ("production" !== process.env.NODE_ENV ? warning(
868
- partialState != null,
869
- 'setState(...): You passed an undefined or null state object; ' +
870
- 'instead, use forceUpdate().'
871
- ) : null);
872
- }
873
360
  // Merge with `_pendingState` if it exists, otherwise with existing state.
874
361
  this.replaceState(
875
- assign({}, this._pendingState || this.state, partialState),
362
+ assign({}, this._pendingState || this._instance.state, partialState),
876
363
  callback
877
364
  );
878
365
  },
@@ -903,6 +390,33 @@ var ReactCompositeComponentMixin = {
903
390
  }
904
391
  },
905
392
 
393
+ /**
394
+ * Forces an update. This should only be invoked when it is known with
395
+ * certainty that we are **not** in a DOM transaction.
396
+ *
397
+ * You may want to call this when you know that some deeper aspect of the
398
+ * component's state has changed but `setState` was not called.
399
+ *
400
+ * This will not invoke `shouldUpdateComponent`, but it will invoke
401
+ * `componentWillUpdate` and `componentDidUpdate`.
402
+ *
403
+ * @param {?function} callback Called after update is complete.isM
404
+ * @final
405
+ * @protected
406
+ */
407
+ forceUpdate: function(callback) {
408
+ var compositeLifeCycleState = this._compositeLifeCycleState;
409
+ ("production" !== process.env.NODE_ENV ? invariant(
410
+ compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
411
+ compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING,
412
+ 'forceUpdate(...): Cannot force an update while unmounting component ' +
413
+ 'or during an existing state transition (such as within `render`).'
414
+ ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.RECEIVING_STATE &&
415
+ compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING));
416
+ this._pendingForceUpdate = true;
417
+ ReactUpdates.enqueueUpdate(this, callback);
418
+ },
419
+
906
420
  /**
907
421
  * Filters the context object to only contain keys specified in
908
422
  * `contextTypes`, and asserts that they are valid.
@@ -913,19 +427,20 @@ var ReactCompositeComponentMixin = {
913
427
  */
914
428
  _processContext: function(context) {
915
429
  var maskedContext = null;
916
- var contextTypes = this.constructor.contextTypes;
917
- if (contextTypes) {
918
- maskedContext = {};
919
- for (var contextName in contextTypes) {
920
- maskedContext[contextName] = context[contextName];
921
- }
922
- if ("production" !== process.env.NODE_ENV) {
923
- this._checkPropTypes(
924
- contextTypes,
925
- maskedContext,
926
- ReactPropTypeLocations.context
927
- );
928
- }
430
+ var contextTypes = this._instance.constructor.contextTypes;
431
+ if (!contextTypes) {
432
+ return emptyObject;
433
+ }
434
+ maskedContext = {};
435
+ for (var contextName in contextTypes) {
436
+ maskedContext[contextName] = context[contextName];
437
+ }
438
+ if ("production" !== process.env.NODE_ENV) {
439
+ this._checkPropTypes(
440
+ contextTypes,
441
+ maskedContext,
442
+ ReactPropTypeLocations.context
443
+ );
929
444
  }
930
445
  return maskedContext;
931
446
  },
@@ -936,29 +451,30 @@ var ReactCompositeComponentMixin = {
936
451
  * @private
937
452
  */
938
453
  _processChildContext: function(currentContext) {
939
- var childContext = this.getChildContext && this.getChildContext();
940
- var displayName = this.constructor.displayName || 'ReactCompositeComponent';
454
+ var inst = this._instance;
455
+ var childContext = inst.getChildContext && inst.getChildContext();
456
+ var displayName = inst.constructor.displayName || 'ReactCompositeComponent';
941
457
  if (childContext) {
942
458
  ("production" !== process.env.NODE_ENV ? invariant(
943
- typeof this.constructor.childContextTypes === 'object',
459
+ typeof inst.constructor.childContextTypes === 'object',
944
460
  '%s.getChildContext(): childContextTypes must be defined in order to ' +
945
461
  'use getChildContext().',
946
462
  displayName
947
- ) : invariant(typeof this.constructor.childContextTypes === 'object'));
463
+ ) : invariant(typeof inst.constructor.childContextTypes === 'object'));
948
464
  if ("production" !== process.env.NODE_ENV) {
949
465
  this._checkPropTypes(
950
- this.constructor.childContextTypes,
466
+ inst.constructor.childContextTypes,
951
467
  childContext,
952
468
  ReactPropTypeLocations.childContext
953
469
  );
954
470
  }
955
471
  for (var name in childContext) {
956
472
  ("production" !== process.env.NODE_ENV ? invariant(
957
- name in this.constructor.childContextTypes,
473
+ name in inst.constructor.childContextTypes,
958
474
  '%s.getChildContext(): key "%s" is not defined in childContextTypes.',
959
475
  displayName,
960
476
  name
961
- ) : invariant(name in this.constructor.childContextTypes));
477
+ ) : invariant(name in inst.constructor.childContextTypes));
962
478
  }
963
479
  return assign({}, currentContext, childContext);
964
480
  }
@@ -976,7 +492,8 @@ var ReactCompositeComponentMixin = {
976
492
  */
977
493
  _processProps: function(newProps) {
978
494
  if ("production" !== process.env.NODE_ENV) {
979
- var propTypes = this.constructor.propTypes;
495
+ var inst = this._instance;
496
+ var propTypes = inst.constructor.propTypes;
980
497
  if (propTypes) {
981
498
  this._checkPropTypes(propTypes, newProps, ReactPropTypeLocations.prop);
982
499
  }
@@ -995,14 +512,15 @@ var ReactCompositeComponentMixin = {
995
512
  _checkPropTypes: function(propTypes, props, location) {
996
513
  // TODO: Stop validating prop types here and only use the element
997
514
  // validation.
998
- var componentName = this.constructor.displayName;
515
+ var componentName = this._instance.constructor.displayName ||
516
+ this._instance.constructor.name;
999
517
  for (var propName in propTypes) {
1000
518
  if (propTypes.hasOwnProperty(propName)) {
1001
519
  var error =
1002
520
  propTypes[propName](props, propName, componentName, location);
1003
521
  if (error instanceof Error) {
1004
522
  // We may want to extend this logic for similar errors in
1005
- // renderComponent calls, so I'm abstracting it away into
523
+ // React.render calls, so I'm abstracting it away into
1006
524
  // a function to minimize refactoring in the future
1007
525
  var addendum = getDeclarationErrorAddendum(this);
1008
526
  ("production" !== process.env.NODE_ENV ? warning(false, error.message + addendum) : null);
@@ -1011,6 +529,24 @@ var ReactCompositeComponentMixin = {
1011
529
  }
1012
530
  },
1013
531
 
532
+ receiveComponent: function(nextElement, transaction, context) {
533
+ if (nextElement === this._currentElement &&
534
+ nextElement._owner != null) {
535
+ // Since elements are immutable after the owner is rendered,
536
+ // we can do a cheap identity compare here to determine if this is a
537
+ // superfluous reconcile. It's possible for state to be mutable but such
538
+ // change should trigger an update of the owner which would recreate
539
+ // the element. We explicitly check for the existence of an owner since
540
+ // it's possible for an element created outside a composite to be
541
+ // deeply mutated and reused.
542
+ return;
543
+ }
544
+
545
+ this._pendingElement = nextElement;
546
+ this._pendingContext = context;
547
+ this.performUpdateIfNecessary(transaction);
548
+ },
549
+
1014
550
  /**
1015
551
  * If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate`
1016
552
  * is set, update the component.
@@ -1029,67 +565,161 @@ var ReactCompositeComponentMixin = {
1029
565
 
1030
566
  if (this._pendingElement == null &&
1031
567
  this._pendingState == null &&
568
+ this._pendingContext == null &&
1032
569
  !this._pendingForceUpdate) {
1033
570
  return;
1034
571
  }
1035
572
 
1036
- var nextContext = this.context;
1037
- var nextProps = this.props;
1038
- var nextElement = this._currentElement;
573
+ var prevElement = this._currentElement;
574
+ var nextElement = prevElement;
1039
575
  if (this._pendingElement != null) {
1040
576
  nextElement = this._pendingElement;
1041
- nextContext = this._processContext(nextElement._context);
1042
- nextProps = this._processProps(nextElement.props);
1043
577
  this._pendingElement = null;
578
+ }
579
+
580
+ var prevContext = this._context;
581
+ var nextContext = prevContext;
582
+ if (this._pendingContext != null) {
583
+ nextContext = this._pendingContext;
584
+ this._pendingContext = null;
585
+ }
586
+
587
+ this.updateComponent(
588
+ transaction,
589
+ prevElement,
590
+ nextElement,
591
+ prevContext,
592
+ nextContext
593
+ );
594
+ },
595
+
596
+ /**
597
+ * Compare two contexts, warning if they are different
598
+ * TODO: Remove this check when owner-context is removed
599
+ */
600
+ _warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) {
601
+ var ownerKeys = Object.keys(ownerBasedContext).sort();
602
+ var parentKeys = Object.keys(parentBasedContext).sort();
603
+ var displayName = this._instance.constructor.displayName || 'ReactCompositeComponent';
604
+ if (ownerKeys.length !== parentKeys.length ||
605
+ ownerKeys.toString() !== parentKeys.toString()) {
606
+ ("production" !== process.env.NODE_ENV ? warning(
607
+ ownerKeys.length === parentKeys.length &&
608
+ ownerKeys.toString() === parentKeys.toString(),
609
+ 'owner based context (keys: %s) does not equal parent based ' +
610
+ 'context (keys: %s) while mounting %s ' +
611
+ '(see: http://fb.me/react-context-by-parent)',
612
+ Object.keys(ownerBasedContext),
613
+ Object.keys(parentBasedContext),
614
+ displayName
615
+ ) : null);
616
+ } else {
617
+ for (var i = 0; i < parentKeys.length; i++) {
618
+ var key = parentKeys[i];
619
+ ("production" !== process.env.NODE_ENV ? warning(
620
+ ownerBasedContext[key] === parentBasedContext[key],
621
+ 'owner-based and parent-based contexts differ ' +
622
+ '(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
623
+ '(see: http://fb.me/react-context-by-parent)',
624
+ ownerBasedContext[key],
625
+ parentBasedContext[key],
626
+ key,
627
+ displayName
628
+ ) : null);
629
+ }
630
+ }
631
+ },
632
+
633
+ /**
634
+ * Perform an update to a mounted component. The componentWillReceiveProps and
635
+ * shouldComponentUpdate methods are called, then (assuming the update isn't
636
+ * skipped) the remaining update lifecycle methods are called and the DOM
637
+ * representation is updated.
638
+ *
639
+ * By default, this implements React's rendering and reconciliation algorithm.
640
+ * Sophisticated clients may wish to override this.
641
+ *
642
+ * @param {ReactReconcileTransaction} transaction
643
+ * @param {ReactElement} prevParentElement
644
+ * @param {ReactElement} nextParentElement
645
+ * @internal
646
+ * @overridable
647
+ */
648
+ updateComponent: function(
649
+ transaction,
650
+ prevParentElement,
651
+ nextParentElement,
652
+ prevUnmaskedContext,
653
+ nextUnmaskedContext
654
+ ) {
655
+ // Update refs regardless of what shouldComponentUpdate returns
656
+ ReactComponent.Mixin.updateComponent.call(
657
+ this,
658
+ transaction,
659
+ prevParentElement,
660
+ nextParentElement,
661
+ prevUnmaskedContext,
662
+ nextUnmaskedContext
663
+ );
664
+
665
+ var inst = this._instance;
666
+
667
+ var prevContext = inst.context;
668
+ var prevProps = inst.props;
669
+ var nextContext = prevContext;
670
+ var nextProps = prevProps;
671
+ // Distinguish between a props update versus a simple state update
672
+ if (prevParentElement !== nextParentElement) {
673
+ nextContext = this._processContext(nextParentElement._context);
674
+ nextProps = this._processProps(nextParentElement.props);
1044
675
 
1045
676
  this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
1046
- if (this.componentWillReceiveProps) {
1047
- this.componentWillReceiveProps(nextProps, nextContext);
677
+ if (inst.componentWillReceiveProps) {
678
+ inst.componentWillReceiveProps(nextProps, nextContext);
1048
679
  }
1049
680
  }
1050
681
 
1051
682
  this._compositeLifeCycleState = null;
1052
683
 
1053
- var nextState = this._pendingState || this.state;
684
+ var nextState = this._pendingState || inst.state;
1054
685
  this._pendingState = null;
1055
686
 
1056
687
  var shouldUpdate =
1057
688
  this._pendingForceUpdate ||
1058
- !this.shouldComponentUpdate ||
1059
- this.shouldComponentUpdate(nextProps, nextState, nextContext);
689
+ !inst.shouldComponentUpdate ||
690
+ inst.shouldComponentUpdate(nextProps, nextState, nextContext);
1060
691
 
1061
692
  if ("production" !== process.env.NODE_ENV) {
1062
693
  if (typeof shouldUpdate === "undefined") {
1063
694
  console.warn(
1064
- (this.constructor.displayName || 'ReactCompositeComponent') +
695
+ (inst.constructor.displayName || 'ReactCompositeComponent') +
1065
696
  '.shouldComponentUpdate(): Returned undefined instead of a ' +
1066
697
  'boolean value. Make sure to return true or false.'
1067
698
  );
1068
699
  }
1069
700
  }
1070
701
 
1071
- if (shouldUpdate) {
1072
- this._pendingForceUpdate = false;
1073
- // Will set `this.props`, `this.state` and `this.context`.
1074
- this._performComponentUpdate(
1075
- nextElement,
1076
- nextProps,
1077
- nextState,
1078
- nextContext,
1079
- transaction
1080
- );
1081
- } else {
702
+ if (!shouldUpdate) {
1082
703
  // If it's determined that a component should not update, we still want
1083
- // to set props and state.
1084
- this._currentElement = nextElement;
1085
- this.props = nextProps;
1086
- this.state = nextState;
1087
- this.context = nextContext;
1088
-
1089
- // Owner cannot change because shouldUpdateReactComponent doesn't allow
1090
- // it. TODO: Remove this._owner completely.
1091
- this._owner = nextElement._owner;
704
+ // to set props and state but we shortcut the rest of the update.
705
+ this._currentElement = nextParentElement;
706
+ this._context = nextUnmaskedContext;
707
+ inst.props = nextProps;
708
+ inst.state = nextState;
709
+ inst.context = nextContext;
710
+ return;
1092
711
  }
712
+
713
+ this._pendingForceUpdate = false;
714
+ // Will set `this.props`, `this.state` and `this.context`.
715
+ this._performComponentUpdate(
716
+ nextParentElement,
717
+ nextProps,
718
+ nextState,
719
+ nextContext,
720
+ transaction,
721
+ nextUnmaskedContext
722
+ );
1093
723
  },
1094
724
 
1095
725
  /**
@@ -1101,6 +731,7 @@ var ReactCompositeComponentMixin = {
1101
731
  * @param {?object} nextState Next object to set as state.
1102
732
  * @param {?object} nextContext Next public object to set as context.
1103
733
  * @param {ReactReconcileTransaction} transaction
734
+ * @param {?object} unmaskedContext
1104
735
  * @private
1105
736
  */
1106
737
  _performComponentUpdate: function(
@@ -1108,329 +739,280 @@ var ReactCompositeComponentMixin = {
1108
739
  nextProps,
1109
740
  nextState,
1110
741
  nextContext,
1111
- transaction
742
+ transaction,
743
+ unmaskedContext
1112
744
  ) {
1113
- var prevElement = this._currentElement;
1114
- var prevProps = this.props;
1115
- var prevState = this.state;
1116
- var prevContext = this.context;
745
+ var inst = this._instance;
746
+
747
+ var prevProps = inst.props;
748
+ var prevState = inst.state;
749
+ var prevContext = inst.context;
1117
750
 
1118
- if (this.componentWillUpdate) {
1119
- this.componentWillUpdate(nextProps, nextState, nextContext);
751
+ if (inst.componentWillUpdate) {
752
+ inst.componentWillUpdate(nextProps, nextState, nextContext);
1120
753
  }
1121
754
 
1122
755
  this._currentElement = nextElement;
1123
- this.props = nextProps;
1124
- this.state = nextState;
1125
- this.context = nextContext;
756
+ this._context = unmaskedContext;
757
+ inst.props = nextProps;
758
+ inst.state = nextState;
759
+ inst.context = nextContext;
1126
760
 
1127
- // Owner cannot change because shouldUpdateReactComponent doesn't allow
1128
- // it. TODO: Remove this._owner completely.
1129
- this._owner = nextElement._owner;
761
+ this._updateRenderedComponent(transaction, nextContext);
1130
762
 
1131
- this.updateComponent(
1132
- transaction,
1133
- prevElement
1134
- );
1135
-
1136
- if (this.componentDidUpdate) {
763
+ if (inst.componentDidUpdate) {
1137
764
  transaction.getReactMountReady().enqueue(
1138
- this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
1139
- this
765
+ inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext),
766
+ inst
1140
767
  );
1141
768
  }
1142
769
  },
1143
770
 
1144
- receiveComponent: function(nextElement, transaction) {
1145
- if (nextElement === this._currentElement &&
1146
- nextElement._owner != null) {
1147
- // Since elements are immutable after the owner is rendered,
1148
- // we can do a cheap identity compare here to determine if this is a
1149
- // superfluous reconcile. It's possible for state to be mutable but such
1150
- // change should trigger an update of the owner which would recreate
1151
- // the element. We explicitly check for the existence of an owner since
1152
- // it's possible for a element created outside a composite to be
1153
- // deeply mutated and reused.
1154
- return;
1155
- }
1156
-
1157
- ReactComponent.Mixin.receiveComponent.call(
1158
- this,
1159
- nextElement,
1160
- transaction
1161
- );
1162
- },
1163
-
1164
771
  /**
1165
- * Updates the component's currently mounted DOM representation.
1166
- *
1167
- * By default, this implements React's rendering and reconciliation algorithm.
1168
- * Sophisticated clients may wish to override this.
772
+ * Call the component's `render` method and update the DOM accordingly.
1169
773
  *
1170
774
  * @param {ReactReconcileTransaction} transaction
1171
- * @param {ReactElement} prevElement
1172
775
  * @internal
1173
- * @overridable
1174
776
  */
1175
- updateComponent: ReactPerf.measure(
1176
- 'ReactCompositeComponent',
1177
- 'updateComponent',
1178
- function(transaction, prevParentElement) {
1179
- ReactComponent.Mixin.updateComponent.call(
1180
- this,
777
+ _updateRenderedComponent: function(transaction, context) {
778
+ var prevComponentInstance = this._renderedComponent;
779
+ var prevRenderedElement = prevComponentInstance._currentElement;
780
+ var nextRenderedElement = this._renderValidatedComponent();
781
+ if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
782
+ prevComponentInstance.receiveComponent(
783
+ nextRenderedElement,
1181
784
  transaction,
1182
- prevParentElement
785
+ this._processChildContext(context)
786
+ );
787
+ } else {
788
+ // These two IDs are actually the same! But nothing should rely on that.
789
+ var thisID = this._rootNodeID;
790
+ var prevComponentID = prevComponentInstance._rootNodeID;
791
+ prevComponentInstance.unmountComponent();
792
+
793
+ this._renderedComponent = this._instantiateReactComponent(
794
+ nextRenderedElement,
795
+ this._currentElement.type
796
+ );
797
+ var nextMarkup = this._renderedComponent.mountComponent(
798
+ thisID,
799
+ transaction,
800
+ context
801
+ );
802
+ ReactComponentEnvironment.replaceNodeWithMarkupByID(
803
+ prevComponentID,
804
+ nextMarkup
1183
805
  );
1184
-
1185
- var prevComponentInstance = this._renderedComponent;
1186
- var prevElement = prevComponentInstance._currentElement;
1187
- var nextElement = this._renderValidatedComponent();
1188
- if (shouldUpdateReactComponent(prevElement, nextElement)) {
1189
- prevComponentInstance.receiveComponent(nextElement, transaction);
1190
- } else {
1191
- // These two IDs are actually the same! But nothing should rely on that.
1192
- var thisID = this._rootNodeID;
1193
- var prevComponentID = prevComponentInstance._rootNodeID;
1194
- prevComponentInstance.unmountComponent();
1195
- this._renderedComponent = instantiateReactComponent(
1196
- nextElement,
1197
- this._currentElement.type
1198
- );
1199
- var nextMarkup = this._renderedComponent.mountComponent(
1200
- thisID,
1201
- transaction,
1202
- this._mountDepth + 1
1203
- );
1204
- ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
1205
- prevComponentID,
1206
- nextMarkup
1207
- );
1208
- }
1209
806
  }
1210
- ),
807
+ },
1211
808
 
1212
809
  /**
1213
- * Forces an update. This should only be invoked when it is known with
1214
- * certainty that we are **not** in a DOM transaction.
1215
- *
1216
- * You may want to call this when you know that some deeper aspect of the
1217
- * component's state has changed but `setState` was not called.
1218
- *
1219
- * This will not invoke `shouldUpdateComponent`, but it will invoke
1220
- * `componentWillUpdate` and `componentDidUpdate`.
1221
- *
1222
- * @param {?function} callback Called after update is complete.
1223
- * @final
1224
- * @protected
810
+ * @private
1225
811
  */
1226
- forceUpdate: function(callback) {
1227
- var compositeLifeCycleState = this._compositeLifeCycleState;
1228
- ("production" !== process.env.NODE_ENV ? invariant(
1229
- this.isMounted() ||
1230
- compositeLifeCycleState === CompositeLifeCycle.MOUNTING,
1231
- 'forceUpdate(...): Can only force an update on mounted or mounting ' +
1232
- 'components.'
1233
- ) : invariant(this.isMounted() ||
1234
- compositeLifeCycleState === CompositeLifeCycle.MOUNTING));
1235
- ("production" !== process.env.NODE_ENV ? invariant(
1236
- compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
1237
- ReactCurrentOwner.current == null,
1238
- 'forceUpdate(...): Cannot force an update while unmounting component ' +
1239
- 'or within a `render` function.'
1240
- ) : invariant(compositeLifeCycleState !== CompositeLifeCycle.UNMOUNTING &&
1241
- ReactCurrentOwner.current == null));
1242
- this._pendingForceUpdate = true;
1243
- ReactUpdates.enqueueUpdate(this, callback);
812
+ _renderValidatedComponentWithoutOwnerOrContext: function() {
813
+ var inst = this._instance;
814
+ var renderedComponent = inst.render();
815
+ if ("production" !== process.env.NODE_ENV) {
816
+ // We allow auto-mocks to proceed as if they're returning null.
817
+ if (typeof renderedComponent === 'undefined' &&
818
+ inst.render._isMockFunction) {
819
+ // This is probably bad practice. Consider warning here and
820
+ // deprecating this convenience.
821
+ renderedComponent = null;
822
+ }
823
+ }
824
+
825
+ return renderedComponent;
1244
826
  },
1245
827
 
1246
828
  /**
1247
829
  * @private
1248
830
  */
1249
- _renderValidatedComponent: ReactPerf.measure(
1250
- 'ReactCompositeComponent',
1251
- '_renderValidatedComponent',
1252
- function() {
1253
- var renderedComponent;
1254
- var previousContext = ReactContext.current;
1255
- ReactContext.current = this._processChildContext(
1256
- this._currentElement._context
1257
- );
1258
- ReactCurrentOwner.current = this;
1259
- try {
1260
- renderedComponent = this.render();
1261
- if (renderedComponent === null || renderedComponent === false) {
1262
- renderedComponent = ReactEmptyComponent.getEmptyComponent();
1263
- ReactEmptyComponent.registerNullComponentID(this._rootNodeID);
1264
- } else {
1265
- ReactEmptyComponent.deregisterNullComponentID(this._rootNodeID);
1266
- }
1267
- } finally {
1268
- ReactContext.current = previousContext;
1269
- ReactCurrentOwner.current = null;
1270
- }
1271
- ("production" !== process.env.NODE_ENV ? invariant(
1272
- ReactElement.isValidElement(renderedComponent),
1273
- '%s.render(): A valid ReactComponent must be returned. You may have ' +
1274
- 'returned undefined, an array or some other invalid object.',
1275
- this.constructor.displayName || 'ReactCompositeComponent'
1276
- ) : invariant(ReactElement.isValidElement(renderedComponent)));
1277
- return renderedComponent;
831
+ _renderValidatedComponent: function() {
832
+ var renderedComponent;
833
+ var previousContext = ReactContext.current;
834
+ ReactContext.current = this._processChildContext(
835
+ this._currentElement._context
836
+ );
837
+ ReactCurrentOwner.current = this;
838
+ var inst = this._instance;
839
+ try {
840
+ renderedComponent =
841
+ this._renderValidatedComponentWithoutOwnerOrContext();
842
+ } finally {
843
+ ReactContext.current = previousContext;
844
+ ReactCurrentOwner.current = null;
1278
845
  }
1279
- ),
846
+ ("production" !== process.env.NODE_ENV ? invariant(
847
+ // TODO: An `isValidNode` function would probably be more appropriate
848
+ renderedComponent === null || renderedComponent === false ||
849
+ ReactElement.isValidElement(renderedComponent),
850
+ '%s.render(): A valid ReactComponent must be returned. You may have ' +
851
+ 'returned undefined, an array or some other invalid object.',
852
+ inst.constructor.displayName || 'ReactCompositeComponent'
853
+ ) : invariant(// TODO: An `isValidNode` function would probably be more appropriate
854
+ renderedComponent === null || renderedComponent === false ||
855
+ ReactElement.isValidElement(renderedComponent)));
856
+ return renderedComponent;
857
+ },
1280
858
 
1281
859
  /**
860
+ * Lazily allocates the refs object and stores `component` as `ref`.
861
+ *
862
+ * @param {string} ref Reference name.
863
+ * @param {component} component Component to store as `ref`.
864
+ * @final
1282
865
  * @private
1283
866
  */
1284
- _bindAutoBindMethods: function() {
1285
- for (var autoBindKey in this.__reactAutoBindMap) {
1286
- if (!this.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
1287
- continue;
1288
- }
1289
- var method = this.__reactAutoBindMap[autoBindKey];
1290
- this[autoBindKey] = this._bindAutoBindMethod(ReactErrorUtils.guard(
1291
- method,
1292
- this.constructor.displayName + '.' + autoBindKey
1293
- ));
1294
- }
867
+ attachRef: function(ref, component) {
868
+ var inst = this.getPublicInstance();
869
+ var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
870
+ refs[ref] = component.getPublicInstance();
1295
871
  },
1296
872
 
1297
873
  /**
1298
- * Binds a method to the component.
874
+ * Detaches a reference name.
1299
875
  *
1300
- * @param {function} method Method to be bound.
876
+ * @param {string} ref Name to dereference.
877
+ * @final
1301
878
  * @private
1302
879
  */
1303
- _bindAutoBindMethod: function(method) {
1304
- var component = this;
1305
- var boundMethod = method.bind(component);
1306
- if ("production" !== process.env.NODE_ENV) {
1307
- boundMethod.__reactBoundContext = component;
1308
- boundMethod.__reactBoundMethod = method;
1309
- boundMethod.__reactBoundArguments = null;
1310
- var componentName = component.constructor.displayName;
1311
- var _bind = boundMethod.bind;
1312
- boundMethod.bind = function(newThis ) {for (var args=[],$__0=1,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);
1313
- // User is trying to bind() an autobound method; we effectively will
1314
- // ignore the value of "this" that the user is trying to use, so
1315
- // let's warn.
1316
- if (newThis !== component && newThis !== null) {
1317
- monitorCodeUse('react_bind_warning', { component: componentName });
1318
- console.warn(
1319
- 'bind(): React component methods may only be bound to the ' +
1320
- 'component instance. See ' + componentName
1321
- );
1322
- } else if (!args.length) {
1323
- monitorCodeUse('react_bind_warning', { component: componentName });
1324
- console.warn(
1325
- 'bind(): You are binding a component method to the component. ' +
1326
- 'React does this for you automatically in a high-performance ' +
1327
- 'way, so you can safely remove this call. See ' + componentName
1328
- );
1329
- return boundMethod;
1330
- }
1331
- var reboundMethod = _bind.apply(boundMethod, arguments);
1332
- reboundMethod.__reactBoundContext = component;
1333
- reboundMethod.__reactBoundMethod = method;
1334
- reboundMethod.__reactBoundArguments = args;
1335
- return reboundMethod;
1336
- };
1337
- }
1338
- return boundMethod;
1339
- }
1340
- };
880
+ detachRef: function(ref) {
881
+ var refs = this.getPublicInstance().refs;
882
+ delete refs[ref];
883
+ },
1341
884
 
1342
- var ReactCompositeComponentBase = function() {};
1343
- assign(
1344
- ReactCompositeComponentBase.prototype,
1345
- ReactComponent.Mixin,
1346
- ReactOwner.Mixin,
1347
- ReactPropTransferer.Mixin,
1348
- ReactCompositeComponentMixin
1349
- );
885
+ /**
886
+ * Get the publicly accessible representation of this component - i.e. what
887
+ * is exposed by refs and returned by React.render. Can be null for stateless
888
+ * components.
889
+ *
890
+ * @return {ReactComponent} the public component instance.
891
+ * @internal
892
+ */
893
+ getPublicInstance: function() {
894
+ return this._instance;
895
+ },
1350
896
 
1351
- /**
1352
- * Module for creating composite components.
1353
- *
1354
- * @class ReactCompositeComponent
1355
- * @extends ReactComponent
1356
- * @extends ReactOwner
1357
- * @extends ReactPropTransferer
1358
- */
1359
- var ReactCompositeComponent = {
897
+ // Stub
898
+ _instantiateReactComponent: null
1360
899
 
1361
- LifeCycle: CompositeLifeCycle,
900
+ });
1362
901
 
1363
- Base: ReactCompositeComponentBase,
902
+ var ShallowMixin = assign({},
903
+ ReactCompositeComponentMixin, {
1364
904
 
1365
905
  /**
1366
- * Creates a composite component class given a class specification.
906
+ * Initializes the component, renders markup, and registers event listeners.
1367
907
  *
1368
- * @param {object} spec Class specification (which must define `render`).
1369
- * @return {function} Component constructor function.
1370
- * @public
908
+ * @param {string} rootID DOM ID of the root node.
909
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
910
+ * @return {ReactElement} Shallow rendering of the component.
911
+ * @final
912
+ * @internal
1371
913
  */
1372
- createClass: function(spec) {
1373
- var Constructor = function(props) {
1374
- // This constructor is overridden by mocks. The argument is used
1375
- // by mocks to assert on what gets mounted. This will later be used
1376
- // by the stand-alone class implementation.
1377
- };
1378
- Constructor.prototype = new ReactCompositeComponentBase();
1379
- Constructor.prototype.constructor = Constructor;
1380
-
1381
- injectedMixins.forEach(
1382
- mixSpecIntoComponent.bind(null, Constructor)
914
+ mountComponent: function(rootID, transaction, context) {
915
+ ReactComponent.Mixin.mountComponent.call(
916
+ this,
917
+ rootID,
918
+ transaction,
919
+ context
1383
920
  );
1384
921
 
1385
- mixSpecIntoComponent(Constructor, spec);
922
+ var inst = this._instance;
1386
923
 
1387
- // Initialize the defaultProps property after all mixins have been merged
1388
- if (Constructor.getDefaultProps) {
1389
- Constructor.defaultProps = Constructor.getDefaultProps();
1390
- }
924
+ // Store a reference from the instance back to the internal representation
925
+ ReactInstanceMap.set(inst, this);
1391
926
 
1392
- ("production" !== process.env.NODE_ENV ? invariant(
1393
- Constructor.prototype.render,
1394
- 'createClass(...): Class specification must implement a `render` method.'
1395
- ) : invariant(Constructor.prototype.render));
927
+ this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
1396
928
 
929
+ // No context for shallow-mounted components.
930
+ inst.props = this._processProps(this._currentElement.props);
931
+
932
+ var initialState = inst.getInitialState ? inst.getInitialState() : null;
1397
933
  if ("production" !== process.env.NODE_ENV) {
1398
- if (Constructor.prototype.componentShouldUpdate) {
1399
- monitorCodeUse(
1400
- 'react_component_should_update_warning',
1401
- { component: spec.displayName }
1402
- );
1403
- console.warn(
1404
- (spec.displayName || 'A component') + ' has a method called ' +
1405
- 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
1406
- 'The name is phrased as a question because the function is ' +
1407
- 'expected to return a value.'
1408
- );
934
+ // We allow auto-mocks to proceed as if they're returning null.
935
+ if (typeof initialState === 'undefined' &&
936
+ inst.getInitialState._isMockFunction) {
937
+ // This is probably bad practice. Consider warning here and
938
+ // deprecating this convenience.
939
+ initialState = null;
1409
940
  }
1410
941
  }
942
+ ("production" !== process.env.NODE_ENV ? invariant(
943
+ typeof initialState === 'object' && !Array.isArray(initialState),
944
+ '%s.getInitialState(): must return an object or null',
945
+ inst.constructor.displayName || 'ReactCompositeComponent'
946
+ ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
947
+ inst.state = initialState;
1411
948
 
1412
- // Reduce time spent doing lookups by setting these on the prototype.
1413
- for (var methodName in ReactCompositeComponentInterface) {
1414
- if (!Constructor.prototype[methodName]) {
1415
- Constructor.prototype[methodName] = null;
949
+ this._pendingState = null;
950
+ this._pendingForceUpdate = false;
951
+
952
+ if (inst.componentWillMount) {
953
+ inst.componentWillMount();
954
+ // When mounting, calls to `setState` by `componentWillMount` will set
955
+ // `this._pendingState` without triggering a re-render.
956
+ if (this._pendingState) {
957
+ inst.state = this._pendingState;
958
+ this._pendingState = null;
1416
959
  }
1417
960
  }
1418
961
 
1419
- if ("production" !== process.env.NODE_ENV) {
1420
- return ReactLegacyElement.wrapFactory(
1421
- ReactElementValidator.createFactory(Constructor)
1422
- );
962
+ // No recursive call to instantiateReactComponent for shallow rendering.
963
+ this._renderedComponent =
964
+ this._renderValidatedComponentWithoutOwnerOrContext();
965
+
966
+ // Done with mounting, `setState` will now trigger UI changes.
967
+ this._compositeLifeCycleState = null;
968
+
969
+ // No call to this._renderedComponent.mountComponent for shallow
970
+ // rendering.
971
+
972
+ if (inst.componentDidMount) {
973
+ transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
1423
974
  }
1424
- return ReactLegacyElement.wrapFactory(
1425
- ReactElement.createFactory(Constructor)
1426
- );
975
+
976
+ return this._renderedComponent;
1427
977
  },
1428
978
 
1429
- injection: {
1430
- injectMixin: function(mixin) {
1431
- injectedMixins.push(mixin);
1432
- }
979
+ /**
980
+ * Call the component's `render` method and update the DOM accordingly.
981
+ *
982
+ * @param {ReactReconcileTransaction} transaction
983
+ * @internal
984
+ */
985
+ _updateRenderedComponent: function(transaction) {
986
+ var prevComponentInstance = this._renderedComponent;
987
+ var prevRenderedElement = prevComponentInstance._currentElement;
988
+ // Use the without-owner-or-context variant of _rVC below:
989
+ var nextRenderedElement =
990
+ this._renderValidatedComponentWithoutOwnerOrContext();
991
+ // This is a noop in shallow render
992
+ shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement);
993
+ this._renderedComponent = nextRenderedElement;
994
+ }
995
+
996
+ });
997
+
998
+ ReactPerf.measureMethods(
999
+ ReactCompositeComponentMixin,
1000
+ 'ReactCompositeComponent',
1001
+ {
1002
+ mountComponent: 'mountComponent',
1003
+ updateComponent: 'updateComponent',
1004
+ _renderValidatedComponent: '_renderValidatedComponent'
1433
1005
  }
1006
+ );
1007
+
1008
+ var ReactCompositeComponent = {
1009
+
1010
+ LifeCycle: CompositeLifeCycle,
1011
+
1012
+ Mixin: ReactCompositeComponentMixin,
1013
+
1014
+ ShallowMixin: ShallowMixin
1015
+
1434
1016
  };
1435
1017
 
1436
1018
  module.exports = ReactCompositeComponent;