react 0.8.0 → 0.9.0-rc1

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 (107) hide show
  1. package/README.md +0 -8
  2. package/addons.js +0 -3
  3. package/lib/AutoFocusMixin.js +30 -0
  4. package/lib/CSSCore.js +22 -21
  5. package/lib/CSSProperty.js +31 -0
  6. package/lib/ChangeEventPlugin.js +26 -4
  7. package/lib/ClientReactRootIndex.js +30 -0
  8. package/lib/CompositionEventPlugin.js +57 -9
  9. package/lib/DOMChildrenOperations.js +32 -2
  10. package/lib/DOMProperty.js +2 -0
  11. package/lib/DOMPropertyOperations.js +14 -1
  12. package/lib/Danger.js +8 -7
  13. package/lib/DefaultDOMPropertyConfig.js +12 -2
  14. package/lib/EnterLeaveEventPlugin.js +37 -4
  15. package/lib/EventConstants.js +3 -0
  16. package/lib/EventListener.js +42 -34
  17. package/lib/EventPluginHub.js +113 -12
  18. package/lib/EventPluginRegistry.js +39 -16
  19. package/lib/EventPluginUtils.js +32 -3
  20. package/lib/EventPropagators.js +6 -42
  21. package/lib/ExecutionEnvironment.js +3 -0
  22. package/lib/LinkedValueUtils.js +161 -0
  23. package/lib/PooledClass.js +6 -0
  24. package/lib/React.js +27 -3
  25. package/lib/ReactCSSTransitionGroup.js +65 -0
  26. package/lib/{ReactTransitionableChild.js → ReactCSSTransitionGroupChild.js} +21 -35
  27. package/lib/ReactComponent.js +87 -52
  28. package/lib/ReactComponentBrowserEnvironment.js +67 -49
  29. package/lib/ReactComponentEnvironment.js +2 -0
  30. package/lib/ReactCompositeComponent.js +547 -112
  31. package/lib/ReactContext.js +67 -0
  32. package/lib/ReactDOM.js +13 -0
  33. package/lib/ReactDOMButton.js +4 -0
  34. package/lib/ReactDOMComponent.js +46 -21
  35. package/lib/ReactDOMForm.js +9 -2
  36. package/lib/ReactDOMIDOperations.js +105 -60
  37. package/lib/ReactDOMImg.js +58 -0
  38. package/lib/ReactDOMInput.js +26 -14
  39. package/lib/ReactDOMOption.js +1 -0
  40. package/lib/ReactDOMSelect.js +36 -17
  41. package/lib/ReactDOMTextarea.js +12 -8
  42. package/lib/ReactDefaultInjection.js +50 -26
  43. package/lib/ReactDefaultPerf.js +207 -370
  44. package/lib/ReactDefaultPerfAnalysis.js +199 -0
  45. package/lib/ReactErrorUtils.js +5 -14
  46. package/lib/ReactEventEmitter.js +141 -145
  47. package/lib/ReactEventEmitterMixin.js +0 -32
  48. package/lib/ReactEventTopLevelCallback.js +32 -12
  49. package/lib/ReactInjection.js +39 -0
  50. package/lib/ReactInstanceHandles.js +35 -19
  51. package/lib/ReactLink.js +1 -1
  52. package/lib/ReactMount.js +127 -103
  53. package/lib/ReactMountReady.js +1 -1
  54. package/lib/ReactMultiChild.js +30 -46
  55. package/lib/ReactMultiChildUpdateTypes.js +2 -0
  56. package/lib/ReactOwner.js +10 -2
  57. package/lib/ReactPerf.js +5 -8
  58. package/lib/ReactPropTransferer.js +40 -21
  59. package/lib/ReactPropTypeLocationNames.js +31 -0
  60. package/lib/ReactPropTypeLocations.js +29 -0
  61. package/lib/ReactPropTypes.js +248 -47
  62. package/lib/ReactPutListenerQueue.js +61 -0
  63. package/lib/ReactReconcileTransaction.js +20 -0
  64. package/lib/ReactRootIndex.js +36 -0
  65. package/lib/ReactServerRendering.js +8 -11
  66. package/lib/ReactTextComponent.js +8 -3
  67. package/lib/{ReactTransitionKeySet.js → ReactTransitionChildMapping.js} +42 -47
  68. package/lib/ReactTransitionGroup.js +132 -57
  69. package/lib/ReactUpdates.js +14 -11
  70. package/lib/ReactWithAddons.js +7 -2
  71. package/lib/SelectEventPlugin.js +22 -39
  72. package/lib/ServerReactRootIndex.js +36 -0
  73. package/lib/SimpleEventPlugin.js +54 -6
  74. package/lib/SyntheticClipboardEvent.js +7 -1
  75. package/lib/SyntheticDragEvent.js +44 -0
  76. package/lib/SyntheticEvent.js +2 -1
  77. package/lib/SyntheticKeyboardEvent.js +4 -2
  78. package/lib/SyntheticWheelEvent.js +10 -7
  79. package/lib/Transaction.js +61 -36
  80. package/lib/cloneWithProps.js +59 -0
  81. package/lib/createArrayFrom.js +10 -13
  82. package/lib/createFullPageComponent.js +63 -0
  83. package/lib/cx.js +2 -2
  84. package/lib/flattenChildren.js +5 -2
  85. package/lib/getActiveElement.js +4 -3
  86. package/lib/getEventKey.js +85 -0
  87. package/lib/getMarkupWrap.js +10 -0
  88. package/lib/getTextContentAccessor.js +5 -3
  89. package/lib/getUnboundedScrollPosition.js +2 -2
  90. package/lib/invariant.js +12 -4
  91. package/lib/isEventSupported.js +7 -11
  92. package/lib/mergeHelpers.js +5 -6
  93. package/lib/onlyChild.js +43 -0
  94. package/lib/shouldUpdateReactComponent.js +58 -0
  95. package/lib/toArray.js +75 -0
  96. package/lib/traverseAllChildren.js +69 -7
  97. package/lib/warning.js +40 -0
  98. package/package.json +2 -3
  99. package/react.js +0 -3
  100. package/ReactJSErrors.js +0 -40
  101. package/lib/$.js +0 -46
  102. package/lib/CallbackRegistry.js +0 -91
  103. package/lib/LinkedValueMixin.js +0 -68
  104. package/lib/ex.js +0 -49
  105. package/lib/filterAttributes.js +0 -45
  106. package/lib/ge.js +0 -76
  107. package/lib/mutateHTMLNodeWithMarkup.js +0 -100
@@ -18,6 +18,8 @@
18
18
 
19
19
  "use strict";
20
20
 
21
+ var invariant = require("./invariant");
22
+
21
23
  /**
22
24
  * Static poolers. Several custom versions for each potential number of
23
25
  * arguments. A completely generic pooler is easy to implement, but would
@@ -71,6 +73,10 @@ var fiveArgumentPooler = function(a1, a2, a3, a4, a5) {
71
73
 
72
74
  var standardReleaser = function(instance) {
73
75
  var Klass = this;
76
+ ("production" !== process.env.NODE_ENV ? invariant(
77
+ instance instanceof Klass,
78
+ 'Trying to release an instance into a pool of a different type.'
79
+ ) : invariant(instance instanceof Klass));
74
80
  if (instance.destructor) {
75
81
  instance.destructor();
76
82
  }
package/lib/React.js CHANGED
@@ -18,8 +18,12 @@
18
18
 
19
19
  "use strict";
20
20
 
21
+ var DOMPropertyOperations = require("./DOMPropertyOperations");
22
+ var EventPluginUtils = require("./EventPluginUtils");
23
+ var ReactChildren = require("./ReactChildren");
21
24
  var ReactComponent = require("./ReactComponent");
22
25
  var ReactCompositeComponent = require("./ReactCompositeComponent");
26
+ var ReactContext = require("./ReactContext");
23
27
  var ReactCurrentOwner = require("./ReactCurrentOwner");
24
28
  var ReactDOM = require("./ReactDOM");
25
29
  var ReactDOMComponent = require("./ReactDOMComponent");
@@ -32,13 +36,20 @@ var ReactPropTypes = require("./ReactPropTypes");
32
36
  var ReactServerRendering = require("./ReactServerRendering");
33
37
  var ReactTextComponent = require("./ReactTextComponent");
34
38
 
39
+ var onlyChild = require("./onlyChild");
40
+
35
41
  ReactDefaultInjection.inject();
36
42
 
37
43
  var React = {
44
+ Children: {
45
+ map: ReactChildren.map,
46
+ forEach: ReactChildren.forEach,
47
+ only: onlyChild
48
+ },
38
49
  DOM: ReactDOM,
39
50
  PropTypes: ReactPropTypes,
40
51
  initializeTouchEvents: function(shouldUseTouch) {
41
- ReactMount.useTouchEvents = shouldUseTouch;
52
+ EventPluginUtils.useTouchEvents = shouldUseTouch;
42
53
  },
43
54
  createClass: ReactCompositeComponent.createClass,
44
55
  constructAndRenderComponent: ReactMount.constructAndRenderComponent,
@@ -50,13 +61,14 @@ var React = {
50
61
  ),
51
62
  renderComponentToString: ReactServerRendering.renderComponentToString,
52
63
  unmountComponentAtNode: ReactMount.unmountComponentAtNode,
53
- unmountAndReleaseReactRootNode: ReactMount.unmountAndReleaseReactRootNode,
54
64
  isValidClass: ReactCompositeComponent.isValidClass,
55
65
  isValidComponent: ReactComponent.isValidComponent,
66
+ withContext: ReactContext.withContext,
56
67
  __internals: {
57
68
  Component: ReactComponent,
58
69
  CurrentOwner: ReactCurrentOwner,
59
70
  DOMComponent: ReactDOMComponent,
71
+ DOMPropertyOperations: DOMPropertyOperations,
60
72
  InstanceHandles: ReactInstanceHandles,
61
73
  Mount: ReactMount,
62
74
  MultiChild: ReactMultiChild,
@@ -64,8 +76,20 @@ var React = {
64
76
  }
65
77
  };
66
78
 
79
+ if ("production" !== process.env.NODE_ENV) {
80
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
81
+ if (ExecutionEnvironment.canUseDOM &&
82
+ window.top === window.self &&
83
+ navigator.userAgent.indexOf('Chrome') > -1) {
84
+ console.debug(
85
+ 'Download the React DevTools for a better development experience: ' +
86
+ 'http://fb.me/react-devtools'
87
+ );
88
+ }
89
+ }
90
+
67
91
  // Version exists only in the open-source version of React, not in Facebook's
68
92
  // internal version.
69
- React.version = '0.8.0';
93
+ React.version = '0.9.0-rc1';
70
94
 
71
95
  module.exports = React;
@@ -0,0 +1,65 @@
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
+ * @typechecks
17
+ * @providesModule ReactCSSTransitionGroup
18
+ * @jsx React.DOM
19
+ */
20
+
21
+ "use strict";
22
+
23
+ var React = require("./React");
24
+
25
+ var ReactTransitionGroup = require("./ReactTransitionGroup");
26
+ var ReactCSSTransitionGroupChild = require("./ReactCSSTransitionGroupChild");
27
+
28
+ var ReactCSSTransitionGroup = React.createClass({displayName: 'ReactCSSTransitionGroup',
29
+ propTypes: {
30
+ transitionName: React.PropTypes.string.isRequired,
31
+ transitionEnter: React.PropTypes.bool,
32
+ transitionLeave: React.PropTypes.bool
33
+ },
34
+
35
+ getDefaultProps: function() {
36
+ return {
37
+ transitionEnter: true,
38
+ transitionLeave: true
39
+ };
40
+ },
41
+
42
+ _wrapChild: function(child) {
43
+ // We need to provide this childFactory so that
44
+ // ReactCSSTransitionGroupChild can receive updates to name, enter, and
45
+ // leave while it is leaving.
46
+ return (
47
+ ReactCSSTransitionGroupChild(
48
+ {name:this.props.transitionName,
49
+ enter:this.props.transitionEnter,
50
+ leave:this.props.transitionLeave},
51
+ child
52
+ )
53
+ );
54
+ },
55
+
56
+ render: function() {
57
+ return this.transferPropsTo(
58
+ ReactTransitionGroup( {childFactory:this._wrapChild},
59
+ this.props.children
60
+ )
61
+ );
62
+ }
63
+ });
64
+
65
+ module.exports = ReactCSSTransitionGroup;
@@ -13,15 +13,19 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  *
16
- * @providesModule ReactTransitionableChild
16
+ * @typechecks
17
+ * @providesModule ReactCSSTransitionGroupChild
17
18
  */
18
19
 
19
20
  "use strict";
20
21
 
21
22
  var React = require("./React");
23
+
22
24
  var CSSCore = require("./CSSCore");
23
25
  var ReactTransitionEvents = require("./ReactTransitionEvents");
24
26
 
27
+ var onlyChild = require("./onlyChild");
28
+
25
29
  // We don't remove the element from the DOM until we receive an animationend or
26
30
  // transitionend event. If the user screws up and forgets to add an animation
27
31
  // their node will be stuck in the DOM forever, so we detect if an animation
@@ -31,6 +35,7 @@ var NO_EVENT_TIMEOUT = 5000;
31
35
 
32
36
  var noEventListener = null;
33
37
 
38
+
34
39
  if ("production" !== process.env.NODE_ENV) {
35
40
  noEventListener = function() {
36
41
  console.warn(
@@ -42,20 +47,8 @@ if ("production" !== process.env.NODE_ENV) {
42
47
  };
43
48
  }
44
49
 
45
- /**
46
- * This component is simply responsible for watching when its single child
47
- * changes to undefined and animating the old child out. It does this by
48
- * recording its old child in savedChildren when it detects this event is about
49
- * to occur.
50
- */
51
- var ReactTransitionableChild = React.createClass({
52
- /**
53
- * Perform an actual DOM transition. This takes care of a few things:
54
- * - Adding the second CSS class to trigger the transition
55
- * - Listening for the finish event
56
- * - Cleaning up the css (unless noReset is true)
57
- */
58
- transition: function(animationType, noReset, finishCallback) {
50
+ var ReactCSSTransitionGroupChild = React.createClass({
51
+ transition: function(animationType, finishCallback) {
59
52
  var node = this.getDOMNode();
60
53
  var className = this.props.name + '-' + animationType;
61
54
  var activeClassName = className + '-active';
@@ -66,13 +59,8 @@ var ReactTransitionableChild = React.createClass({
66
59
  clearTimeout(noEventTimeout);
67
60
  }
68
61
 
69
- // If this gets invoked after the component is unmounted it's OK.
70
- if (!noReset) {
71
- // Usually this means you're about to remove the node if you want to
72
- // leave it in its animated state.
73
- CSSCore.removeClass(node, className);
74
- CSSCore.removeClass(node, activeClassName);
75
- }
62
+ CSSCore.removeClass(node, className);
63
+ CSSCore.removeClass(node, activeClassName);
76
64
 
77
65
  ReactTransitionEvents.removeEndEventListener(node, endListener);
78
66
 
@@ -126,27 +114,25 @@ var ReactTransitionableChild = React.createClass({
126
114
  }
127
115
  },
128
116
 
129
- componentWillReceiveProps: function(nextProps) {
130
- if (!nextProps.children && this.props.children) {
131
- this.savedChildren = this.props.children;
132
- }
133
- },
134
-
135
- componentDidMount: function(node) {
117
+ componentWillEnter: function(done) {
136
118
  if (this.props.enter) {
137
- this.transition('enter');
119
+ this.transition('enter', done);
120
+ } else {
121
+ done();
138
122
  }
139
123
  },
140
124
 
141
- componentDidUpdate: function(prevProps, prevState, node) {
142
- if (prevProps.children && !this.props.children) {
143
- this.transition('leave', true, this.props.onDoneLeaving);
125
+ componentWillLeave: function(done) {
126
+ if (this.props.leave) {
127
+ this.transition('leave', done);
128
+ } else {
129
+ done();
144
130
  }
145
131
  },
146
132
 
147
133
  render: function() {
148
- return this.props.children || this.savedChildren;
134
+ return onlyChild(this.props.children);
149
135
  }
150
136
  });
151
137
 
152
- module.exports = ReactTransitionableChild;
138
+ module.exports = ReactCSSTransitionGroupChild;
@@ -43,16 +43,20 @@ var ComponentLifeCycle = keyMirror({
43
43
  });
44
44
 
45
45
  /**
46
- * Warn if there's no key explicitly set on dynamic arrays of children.
47
- * This allows us to keep track of children between updates.
46
+ * Warn if there's no key explicitly set on dynamic arrays of children or
47
+ * object keys are not valid. This allows us to keep track of children between
48
+ * updates.
48
49
  */
49
50
 
50
- var ownerHasWarned = {};
51
+ var ownerHasExplicitKeyWarning = {};
52
+ var ownerHasPropertyWarning = {};
53
+
54
+ var NUMERIC_PROPERTY_REGEX = /^\d+$/;
51
55
 
52
56
  /**
53
57
  * Warn if the component doesn't have an explicit key assigned to it.
54
58
  * This component is in an array. The array could grow and shrink or be
55
- * reordered. All children, that hasn't already been validated, are required to
59
+ * reordered. All children that haven't already been validated are required to
56
60
  * have a "key" property assigned to it.
57
61
  *
58
62
  * @internal
@@ -71,18 +75,18 @@ function validateExplicitKey(component) {
71
75
 
72
76
  // Name of the component whose render method tried to pass children.
73
77
  var currentName = ReactCurrentOwner.current.constructor.displayName;
74
- if (ownerHasWarned.hasOwnProperty(currentName)) {
78
+ if (ownerHasExplicitKeyWarning.hasOwnProperty(currentName)) {
75
79
  return;
76
80
  }
77
- ownerHasWarned[currentName] = true;
81
+ ownerHasExplicitKeyWarning[currentName] = true;
78
82
 
79
83
  var message = 'Each child in an array should have a unique "key" prop. ' +
80
84
  'Check the render method of ' + currentName + '.';
81
85
  if (!component.isOwnedBy(ReactCurrentOwner.current)) {
82
86
  // Name of the component that originally created this child.
83
87
  var childOwnerName =
84
- component.props.__owner__ &&
85
- component.props.__owner__.constructor.displayName;
88
+ component._owner &&
89
+ component._owner.constructor.displayName;
86
90
 
87
91
  // Usually the current owner is the offender, but if it accepts
88
92
  // children as a property, it may be the creator of the child that's
@@ -90,12 +94,39 @@ function validateExplicitKey(component) {
90
94
  message += ' It was passed a child from ' + childOwnerName + '.';
91
95
  }
92
96
 
97
+ message += ' See http://fb.me/react-warning-keys for more information.';
93
98
  console.warn(message);
94
99
  }
95
100
 
96
101
  /**
97
- * Ensure that every component either is passed in a static location or, if
98
- * if it's passed in an array, has an explicit key property defined.
102
+ * Warn if the key is being defined as an object property but has an incorrect
103
+ * value.
104
+ *
105
+ * @internal
106
+ * @param {string} name Property name of the key.
107
+ * @param {ReactComponent} component Component that requires a key.
108
+ */
109
+ function validatePropertyKey(name) {
110
+ if (NUMERIC_PROPERTY_REGEX.test(name)) {
111
+ // Name of the component whose render method tried to pass children.
112
+ var currentName = ReactCurrentOwner.current.constructor.displayName;
113
+ if (ownerHasPropertyWarning.hasOwnProperty(currentName)) {
114
+ return;
115
+ }
116
+ ownerHasPropertyWarning[currentName] = true;
117
+
118
+ console.warn(
119
+ 'Child objects should have non-numeric keys so ordering is preserved. ' +
120
+ 'Check the render method of ' + currentName + '. ' +
121
+ 'See http://fb.me/react-warning-keys for more information.'
122
+ );
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Ensure that every component either is passed in a static location, in an
128
+ * array with an explicit keys property defined, or in an object literal
129
+ * with valid key property.
99
130
  *
100
131
  * @internal
101
132
  * @param {*} component Statically passed child of any type.
@@ -112,6 +143,10 @@ function validateChildKeys(component) {
112
143
  } else if (ReactComponent.isValidComponent(component)) {
113
144
  // This component was passed in a valid location.
114
145
  component.__keyValidated__ = true;
146
+ } else if (component && typeof component === 'object') {
147
+ for (var name in component) {
148
+ validatePropertyKey(name, component);
149
+ }
115
150
  }
116
151
  }
117
152
 
@@ -148,28 +183,18 @@ var ReactComponent = {
148
183
  * @final
149
184
  */
150
185
  isValidComponent: function(object) {
151
- return !!(
152
- object &&
153
- typeof object.mountComponentIntoNode === 'function' &&
154
- typeof object.receiveComponent === 'function'
155
- );
156
- },
157
-
158
- /**
159
- * Generate a key string that identifies a component within a set.
160
- *
161
- * @param {*} component A component that could contain a manual key.
162
- * @param {number} index Index that is used if a manual key is not provided.
163
- * @return {string}
164
- * @internal
165
- */
166
- getKey: function(component, index) {
167
- if (component && component.props && component.props.key != null) {
168
- // Explicit key
169
- return '{' + component.props.key + '}';
186
+ if (!object || !object.type || !object.type.prototype) {
187
+ return false;
170
188
  }
171
- // Implicit key determined by the index in the set
172
- return '[' + index + ']';
189
+ // This is the safer way of duck checking the type of instance this is.
190
+ // The object can be a generic descriptor but the type property refers to
191
+ // the constructor and it's prototype can be used to inspect the type that
192
+ // will actually get mounted.
193
+ var prototype = object.type.prototype;
194
+ return (
195
+ typeof prototype.mountComponentIntoNode === 'function' &&
196
+ typeof prototype.receiveComponent === 'function'
197
+ );
173
198
  },
174
199
 
175
200
  /**
@@ -184,7 +209,7 @@ var ReactComponent = {
184
209
  *
185
210
  * @internal
186
211
  */
187
- DOMIDOperations: ReactComponentEnvironment.DOMIDOperations,
212
+ BackendIDOperations: ReactComponentEnvironment.BackendIDOperations,
188
213
 
189
214
  /**
190
215
  * Optionally injectable environment dependent cleanup hook. (server vs.
@@ -260,23 +285,23 @@ var ReactComponent = {
260
285
  */
261
286
  replaceProps: function(props, callback) {
262
287
  ("production" !== process.env.NODE_ENV ? invariant(
263
- !this.props.__owner__,
288
+ this.isMounted(),
289
+ 'replaceProps(...): Can only update a mounted component.'
290
+ ) : invariant(this.isMounted()));
291
+ ("production" !== process.env.NODE_ENV ? invariant(
292
+ this._mountDepth === 0,
264
293
  'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
265
- 'component with an owner. This is an anti-pattern since props will ' +
294
+ 'component with a parent. This is an anti-pattern since props will ' +
266
295
  'get reactively updated when rendered. Instead, change the owner\'s ' +
267
296
  '`render` method to pass the correct value as props to the component ' +
268
297
  'where it is created.'
269
- ) : invariant(!this.props.__owner__));
270
- ("production" !== process.env.NODE_ENV ? invariant(
271
- this.isMounted(),
272
- 'replaceProps(...): Can only update a mounted component.'
273
- ) : invariant(this.isMounted()));
298
+ ) : invariant(this._mountDepth === 0));
274
299
  this._pendingProps = props;
275
300
  ReactUpdates.enqueueUpdate(this, callback);
276
301
  },
277
302
 
278
303
  /**
279
- * Base constructor for all React component.
304
+ * Base constructor for all React components.
280
305
  *
281
306
  * Subclasses that override this method should make sure to invoke
282
307
  * `ReactComponent.Mixin.construct.call(this, ...)`.
@@ -288,13 +313,19 @@ var ReactComponent = {
288
313
  construct: function(initialProps, children) {
289
314
  this.props = initialProps || {};
290
315
  // Record the component responsible for creating this component.
291
- this.props.__owner__ = ReactCurrentOwner.current;
316
+ this._owner = ReactCurrentOwner.current;
292
317
  // All components start unmounted.
293
318
  this._lifeCycleState = ComponentLifeCycle.UNMOUNTED;
294
319
 
295
320
  this._pendingProps = null;
296
321
  this._pendingCallbacks = null;
297
322
 
323
+ // Unlike _pendingProps and _pendingCallbacks, we won't use null to
324
+ // indicate that nothing is pending because it's possible for a component
325
+ // to have a null owner. Instead, an owner change is pending when
326
+ // this._owner !== this._pendingOwner.
327
+ this._pendingOwner = this._owner;
328
+
298
329
  // Children can be more than one argument
299
330
  var childrenLength = arguments.length - 1;
300
331
  if (childrenLength === 1) {
@@ -331,12 +362,14 @@ var ReactComponent = {
331
362
  mountComponent: function(rootID, transaction, mountDepth) {
332
363
  ("production" !== process.env.NODE_ENV ? invariant(
333
364
  !this.isMounted(),
334
- 'mountComponent(%s, ...): Can only mount an unmounted component.',
365
+ 'mountComponent(%s, ...): Can only mount an unmounted component. ' +
366
+ 'Make sure to avoid storing components between renders or reusing a ' +
367
+ 'single component instance in multiple places.',
335
368
  rootID
336
369
  ) : invariant(!this.isMounted()));
337
370
  var props = this.props;
338
371
  if (props.ref != null) {
339
- ReactOwner.addComponentAsRefTo(this, props.ref, props.__owner__);
372
+ ReactOwner.addComponentAsRefTo(this, props.ref, this._owner);
340
373
  }
341
374
  this._rootNodeID = rootID;
342
375
  this._lifeCycleState = ComponentLifeCycle.MOUNTED;
@@ -361,7 +394,7 @@ var ReactComponent = {
361
394
  ) : invariant(this.isMounted()));
362
395
  var props = this.props;
363
396
  if (props.ref != null) {
364
- ReactOwner.removeComponentAsRefFrom(this, props.ref, props.__owner__);
397
+ ReactOwner.removeComponentAsRefFrom(this, props.ref, this._owner);
365
398
  }
366
399
  ReactComponent.unmountIDFromEnvironment(this._rootNodeID);
367
400
  this._rootNodeID = null;
@@ -384,6 +417,7 @@ var ReactComponent = {
384
417
  this.isMounted(),
385
418
  'receiveComponent(...): Can only update a mounted component.'
386
419
  ) : invariant(this.isMounted()));
420
+ this._pendingOwner = nextComponent._owner;
387
421
  this._pendingProps = nextComponent.props;
388
422
  this._performUpdateIfNecessary(transaction);
389
423
  },
@@ -411,9 +445,11 @@ var ReactComponent = {
411
445
  return;
412
446
  }
413
447
  var prevProps = this.props;
448
+ var prevOwner = this._owner;
414
449
  this.props = this._pendingProps;
450
+ this._owner = this._pendingOwner;
415
451
  this._pendingProps = null;
416
- this.updateComponent(transaction, prevProps);
452
+ this.updateComponent(transaction, prevProps, prevOwner);
417
453
  },
418
454
 
419
455
  /**
@@ -423,21 +459,20 @@ var ReactComponent = {
423
459
  * @param {object} prevProps
424
460
  * @internal
425
461
  */
426
- updateComponent: function(transaction, prevProps) {
462
+ updateComponent: function(transaction, prevProps, prevOwner) {
427
463
  var props = this.props;
428
464
  // If either the owner or a `ref` has changed, make sure the newest owner
429
465
  // has stored a reference to `this`, and the previous owner (if different)
430
466
  // has forgotten the reference to `this`.
431
- if (props.__owner__ !== prevProps.__owner__ ||
432
- props.ref !== prevProps.ref) {
467
+ if (this._owner !== prevOwner || props.ref !== prevProps.ref) {
433
468
  if (prevProps.ref != null) {
434
469
  ReactOwner.removeComponentAsRefFrom(
435
- this, prevProps.ref, prevProps.__owner__
470
+ this, prevProps.ref, prevOwner
436
471
  );
437
472
  }
438
473
  // Correct, even if the owner is the same, and only the ref has changed.
439
474
  if (props.ref != null) {
440
- ReactOwner.addComponentAsRefTo(this, props.ref, props.__owner__);
475
+ ReactOwner.addComponentAsRefTo(this, props.ref, this._owner);
441
476
  }
442
477
  }
443
478
  },
@@ -491,7 +526,7 @@ var ReactComponent = {
491
526
  * @internal
492
527
  */
493
528
  isOwnedBy: function(owner) {
494
- return this.props.__owner__ === owner;
529
+ return this._owner === owner;
495
530
  },
496
531
 
497
532
  /**
@@ -503,7 +538,7 @@ var ReactComponent = {
503
538
  * @internal
504
539
  */
505
540
  getSiblingByRef: function(ref) {
506
- var owner = this.props.__owner__;
541
+ var owner = this._owner;
507
542
  if (!owner || !owner.refs) {
508
543
  return null;
509
544
  }