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
@@ -11,12 +11,16 @@
11
11
 
12
12
  "use strict";
13
13
 
14
+ var ReactClass = require("./ReactClass");
15
+ var ReactElement = require("./ReactElement");
16
+
14
17
  var assign = require("./Object.assign");
15
18
  var invariant = require("./invariant");
16
19
 
17
20
  var genericComponentClass = null;
18
21
  // This registry keeps track of wrapper classes around native tags
19
22
  var tagToComponentClass = {};
23
+ var textComponentClass = null;
20
24
 
21
25
  var ReactNativeComponentInjection = {
22
26
  // This accepts a class that receives the tag string. This is a catch all
@@ -24,6 +28,11 @@ var ReactNativeComponentInjection = {
24
28
  injectGenericComponentClass: function(componentClass) {
25
29
  genericComponentClass = componentClass;
26
30
  },
31
+ // This accepts a text component class that takes the text string to be
32
+ // rendered as props.
33
+ injectTextComponentClass: function(componentClass) {
34
+ textComponentClass = componentClass;
35
+ },
27
36
  // This accepts a keyed object with classes as values. Each key represents a
28
37
  // tag. That particular tag will use this class instead of the generic one.
29
38
  injectComponentClasses: function(componentClasses) {
@@ -31,6 +40,22 @@ var ReactNativeComponentInjection = {
31
40
  }
32
41
  };
33
42
 
43
+ function autoGenerateWrapperClass(type) {
44
+ return ReactClass.createClass({
45
+ tagName: type.toUpperCase(),
46
+ render: function() {
47
+ return new ReactElement(
48
+ type,
49
+ null,
50
+ null,
51
+ null,
52
+ null,
53
+ this.props
54
+ );
55
+ }
56
+ });
57
+ }
58
+
34
59
  /**
35
60
  * Create an internal class for a specific tag.
36
61
  *
@@ -41,12 +66,7 @@ var ReactNativeComponentInjection = {
41
66
  function createInstanceForTag(tag, props, parentType) {
42
67
  var componentClass = tagToComponentClass[tag];
43
68
  if (componentClass == null) {
44
- ("production" !== process.env.NODE_ENV ? invariant(
45
- genericComponentClass,
46
- 'There is no registered component for the tag %s',
47
- tag
48
- ) : invariant(genericComponentClass));
49
- return new genericComponentClass(tag, props);
69
+ tagToComponentClass[tag] = componentClass = autoGenerateWrapperClass(tag);
50
70
  }
51
71
  if (parentType === tag) {
52
72
  // Avoid recursion
@@ -57,12 +77,29 @@ function createInstanceForTag(tag, props, parentType) {
57
77
  ) : invariant(genericComponentClass));
58
78
  return new genericComponentClass(tag, props);
59
79
  }
60
- // Unwrap legacy factories
61
- return new componentClass.type(props);
80
+ return new componentClass(props);
81
+ }
82
+
83
+ /**
84
+ * @param {ReactText} text
85
+ * @return {ReactComponent}
86
+ */
87
+ function createInstanceForText(text) {
88
+ return new textComponentClass(text);
89
+ }
90
+
91
+ /**
92
+ * @param {ReactComponent} component
93
+ * @return {boolean}
94
+ */
95
+ function isTextComponent(component) {
96
+ return component instanceof textComponentClass;
62
97
  }
63
98
 
64
99
  var ReactNativeComponent = {
65
100
  createInstanceForTag: createInstanceForTag,
101
+ createInstanceForText: createInstanceForText,
102
+ isTextComponent: isTextComponent,
66
103
  injection: ReactNativeComponentInjection
67
104
  };
68
105
 
package/lib/ReactOwner.js CHANGED
@@ -11,7 +11,6 @@
11
11
 
12
12
  "use strict";
13
13
 
14
- var emptyObject = require("./emptyObject");
15
14
  var invariant = require("./invariant");
16
15
 
17
16
  /**
@@ -53,9 +52,8 @@ var ReactOwner = {
53
52
  */
54
53
  isValidOwner: function(object) {
55
54
  return !!(
56
- object &&
57
- typeof object.attachRef === 'function' &&
58
- typeof object.detachRef === 'function'
55
+ (object &&
56
+ typeof object.attachRef === 'function' && typeof object.detachRef === 'function')
59
57
  );
60
58
  },
61
59
 
@@ -100,51 +98,9 @@ var ReactOwner = {
100
98
  ) : invariant(ReactOwner.isValidOwner(owner)));
101
99
  // Check that `component` is still the current ref because we do not want to
102
100
  // detach the ref if another component stole it.
103
- if (owner.refs[ref] === component) {
101
+ if (owner.getPublicInstance().refs[ref] === component.getPublicInstance()) {
104
102
  owner.detachRef(ref);
105
103
  }
106
- },
107
-
108
- /**
109
- * A ReactComponent must mix this in to have refs.
110
- *
111
- * @lends {ReactOwner.prototype}
112
- */
113
- Mixin: {
114
-
115
- construct: function() {
116
- this.refs = emptyObject;
117
- },
118
-
119
- /**
120
- * Lazily allocates the refs object and stores `component` as `ref`.
121
- *
122
- * @param {string} ref Reference name.
123
- * @param {component} component Component to store as `ref`.
124
- * @final
125
- * @private
126
- */
127
- attachRef: function(ref, component) {
128
- ("production" !== process.env.NODE_ENV ? invariant(
129
- component.isOwnedBy(this),
130
- 'attachRef(%s, ...): Only a component\'s owner can store a ref to it.',
131
- ref
132
- ) : invariant(component.isOwnedBy(this)));
133
- var refs = this.refs === emptyObject ? (this.refs = {}) : this.refs;
134
- refs[ref] = component;
135
- },
136
-
137
- /**
138
- * Detaches a reference name.
139
- *
140
- * @param {string} ref Name to dereference.
141
- * @final
142
- * @private
143
- */
144
- detachRef: function(ref) {
145
- delete this.refs[ref];
146
- }
147
-
148
104
  }
149
105
 
150
106
  };
package/lib/ReactPerf.js CHANGED
@@ -29,6 +29,26 @@ var ReactPerf = {
29
29
  */
30
30
  storedMeasure: _noMeasure,
31
31
 
32
+ /**
33
+ * @param {object} object
34
+ * @param {string} objectName
35
+ * @param {object<string>} methodNames
36
+ */
37
+ measureMethods: function(object, objectName, methodNames) {
38
+ if ("production" !== process.env.NODE_ENV) {
39
+ for (var key in methodNames) {
40
+ if (!methodNames.hasOwnProperty(key)) {
41
+ continue;
42
+ }
43
+ object[key] = ReactPerf.measure(
44
+ objectName,
45
+ methodNames[key],
46
+ object[key]
47
+ );
48
+ }
49
+ }
50
+ },
51
+
32
52
  /**
33
53
  * Use this to wrap methods you want to measure. Zero overhead in production.
34
54
  *
@@ -13,11 +13,7 @@
13
13
 
14
14
  var assign = require("./Object.assign");
15
15
  var emptyFunction = require("./emptyFunction");
16
- var invariant = require("./invariant");
17
16
  var joinClasses = require("./joinClasses");
18
- var warning = require("./warning");
19
-
20
- var didWarn = false;
21
17
 
22
18
  /**
23
19
  * Creates a transfer strategy that will merge prop values using the supplied
@@ -96,8 +92,6 @@ function transferInto(props, newProps) {
96
92
  */
97
93
  var ReactPropTransferer = {
98
94
 
99
- TransferStrategies: TransferStrategies,
100
-
101
95
  /**
102
96
  * Merge two props objects using TransferStrategies.
103
97
  *
@@ -109,55 +103,6 @@ var ReactPropTransferer = {
109
103
  return transferInto(assign({}, oldProps), newProps);
110
104
  },
111
105
 
112
- /**
113
- * @lends {ReactPropTransferer.prototype}
114
- */
115
- Mixin: {
116
-
117
- /**
118
- * Transfer props from this component to a target component.
119
- *
120
- * Props that do not have an explicit transfer strategy will be transferred
121
- * only if the target component does not already have the prop set.
122
- *
123
- * This is usually used to pass down props to a returned root component.
124
- *
125
- * @param {ReactElement} element Component receiving the properties.
126
- * @return {ReactElement} The supplied `component`.
127
- * @final
128
- * @protected
129
- */
130
- transferPropsTo: function(element) {
131
- ("production" !== process.env.NODE_ENV ? invariant(
132
- element._owner === this,
133
- '%s: You can\'t call transferPropsTo() on a component that you ' +
134
- 'don\'t own, %s. This usually means you are calling ' +
135
- 'transferPropsTo() on a component passed in as props or children.',
136
- this.constructor.displayName,
137
- typeof element.type === 'string' ?
138
- element.type :
139
- element.type.displayName
140
- ) : invariant(element._owner === this));
141
-
142
- if ("production" !== process.env.NODE_ENV) {
143
- if (!didWarn) {
144
- didWarn = true;
145
- ("production" !== process.env.NODE_ENV ? warning(
146
- false,
147
- 'transferPropsTo is deprecated. ' +
148
- 'See http://fb.me/react-transferpropsto for more information.'
149
- ) : null);
150
- }
151
- }
152
-
153
- // Because elements are immutable we have to merge into the existing
154
- // props object rather than clone it.
155
- transferInto(element.props, this.props);
156
-
157
- return element;
158
- }
159
-
160
- }
161
106
  };
162
107
 
163
108
  module.exports = ReactPropTransferer;
@@ -14,7 +14,6 @@
14
14
  var ReactElement = require("./ReactElement");
15
15
  var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
16
16
 
17
- var deprecated = require("./deprecated");
18
17
  var emptyFunction = require("./emptyFunction");
19
18
 
20
19
  /**
@@ -85,22 +84,7 @@ var ReactPropTypes = {
85
84
  objectOf: createObjectOfTypeChecker,
86
85
  oneOf: createEnumTypeChecker,
87
86
  oneOfType: createUnionTypeChecker,
88
- shape: createShapeTypeChecker,
89
-
90
- component: deprecated(
91
- 'React.PropTypes',
92
- 'component',
93
- 'element',
94
- this,
95
- elementTypeChecker
96
- ),
97
- renderable: deprecated(
98
- 'React.PropTypes',
99
- 'renderable',
100
- 'node',
101
- this,
102
- nodeTypeChecker
103
- )
87
+ shape: createShapeTypeChecker
104
88
  };
105
89
 
106
90
  function createChainableTypeChecker(validate) {
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Copyright 2013-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 ReactRef
10
+ */
11
+
12
+ "use strict";
13
+
14
+ var ReactUpdates = require("./ReactUpdates");
15
+
16
+ var accumulate = require("./accumulate");
17
+ var assign = require("./Object.assign");
18
+ var forEachAccumulated = require("./forEachAccumulated");
19
+ var invariant = require("./invariant");
20
+
21
+ function ReactRef() {
22
+ this._value = null;
23
+ this._successCallbacks = null;
24
+ this._failureCallbacks = null;
25
+ }
26
+
27
+ /**
28
+ * Call the enqueued success or failure callbacks for a ref, as appropriate.
29
+ */
30
+ function dispatchCallbacks() {
31
+ /*jshint validthis:true */
32
+ var successCallbacks = this._successCallbacks;
33
+ var failureCallbacks = this._failureCallbacks;
34
+ this._successCallbacks = null;
35
+ this._failureCallbacks = null;
36
+
37
+ if (this._value) {
38
+ forEachAccumulated(successCallbacks, callSuccess, this);
39
+ } else {
40
+ forEachAccumulated(failureCallbacks, callFailure);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Call a single success callback, passing the ref's value.
46
+ */
47
+ function callSuccess(cb) {
48
+ /*jshint validthis:true */
49
+ cb(this._value);
50
+ }
51
+
52
+ /**
53
+ * Call a single failure callback, passing no arguments.
54
+ */
55
+ function callFailure(cb) {
56
+ cb();
57
+ }
58
+
59
+ assign(ReactRef.prototype, {
60
+ /**
61
+ * Get the value of a ref asynchronously. Accepts a success callback and an
62
+ * optional failure callback. If the ref has been rendered, the success
63
+ * callback will be called with the component instance; otherwise, the failure
64
+ * callback will be executed.
65
+ *
66
+ * @param {function} success Callback in case of success
67
+ * @param {?function} failure Callback in case of failure
68
+ */
69
+ then: function(success, failure) {
70
+ ("production" !== process.env.NODE_ENV ? invariant(
71
+ typeof success === 'function',
72
+ 'ReactRef.then(...): Must provide a success callback.'
73
+ ) : invariant(typeof success === 'function'));
74
+ if (this._successCallbacks == null) {
75
+ ReactUpdates.asap(dispatchCallbacks, this);
76
+ }
77
+ this._successCallbacks = accumulate(this._successCallbacks, success);
78
+ if (failure) {
79
+ this._failureCallbacks = accumulate(this._failureCallbacks, failure);
80
+ }
81
+ }
82
+ });
83
+
84
+ ReactRef.attachRef = function(ref, value) {
85
+ ref._value = value.getPublicInstance();
86
+ };
87
+
88
+ ReactRef.detachRef = function(ref, value) {
89
+ // Check that `component` is still the current ref because we do not want to
90
+ // detach the ref if another component stole it.
91
+ if (ref._value === value) {
92
+ ref._value = null;
93
+ }
94
+ };
95
+
96
+ module.exports = ReactRef;
@@ -17,6 +17,7 @@ var ReactMarkupChecksum = require("./ReactMarkupChecksum");
17
17
  var ReactServerRenderingTransaction =
18
18
  require("./ReactServerRenderingTransaction");
19
19
 
20
+ var emptyObject = require("./emptyObject");
20
21
  var instantiateReactComponent = require("./instantiateReactComponent");
21
22
  var invariant = require("./invariant");
22
23
 
@@ -37,7 +38,7 @@ function renderToString(element) {
37
38
 
38
39
  return transaction.perform(function() {
39
40
  var componentInstance = instantiateReactComponent(element, null);
40
- var markup = componentInstance.mountComponent(id, transaction, 0);
41
+ var markup = componentInstance.mountComponent(id, transaction, emptyObject);
41
42
  return ReactMarkupChecksum.addChecksumToMarkup(markup);
42
43
  }, null);
43
44
  } finally {
@@ -63,7 +64,7 @@ function renderToStaticMarkup(element) {
63
64
 
64
65
  return transaction.perform(function() {
65
66
  var componentInstance = instantiateReactComponent(element, null);
66
- return componentInstance.mountComponent(id, transaction, 0);
67
+ return componentInstance.mountComponent(id, transaction, emptyObject);
67
68
  }, null);
68
69
  } finally {
69
70
  ReactServerRenderingTransaction.release(transaction);
@@ -17,8 +17,10 @@ var EventPropagators = require("./EventPropagators");
17
17
  var React = require("./React");
18
18
  var ReactElement = require("./ReactElement");
19
19
  var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
20
+ var ReactCompositeComponent = require("./ReactCompositeComponent");
21
+ var ReactInstanceHandles = require("./ReactInstanceHandles");
22
+ var ReactInstanceMap = require("./ReactInstanceMap");
20
23
  var ReactMount = require("./ReactMount");
21
- var ReactTextComponent = require("./ReactTextComponent");
22
24
  var ReactUpdates = require("./ReactUpdates");
23
25
  var SyntheticEvent = require("./SyntheticEvent");
24
26
 
@@ -55,12 +57,14 @@ var ReactTestUtils = {
55
57
  isElementOfType: function(inst, convenienceConstructor) {
56
58
  return (
57
59
  ReactElement.isValidElement(inst) &&
58
- inst.type === convenienceConstructor.type
60
+ inst.type === convenienceConstructor
59
61
  );
60
62
  },
61
63
 
62
64
  isDOMComponent: function(inst) {
63
- return !!(inst && inst.mountComponent && inst.tagName);
65
+ // TODO: Fix this heuristic. It's just here because composites can currently
66
+ // pretend to be DOM components.
67
+ return !!(inst && inst.getDOMNode && inst.tagName);
64
68
  },
65
69
 
66
70
  isDOMComponentElement: function(inst) {
@@ -76,7 +80,7 @@ var ReactTestUtils = {
76
80
 
77
81
  isCompositeComponentWithType: function(inst, type) {
78
82
  return !!(ReactTestUtils.isCompositeComponent(inst) &&
79
- (inst.constructor === type.type));
83
+ (inst.constructor === type));
80
84
  },
81
85
 
82
86
  isCompositeComponentElement: function(inst) {
@@ -97,8 +101,12 @@ var ReactTestUtils = {
97
101
  (inst.constructor === type));
98
102
  },
99
103
 
100
- isTextComponent: function(inst) {
101
- return inst instanceof ReactTextComponent.type;
104
+ getRenderedChildOfCompositeComponent: function(inst) {
105
+ if (!ReactTestUtils.isCompositeComponent(inst)) {
106
+ return null;
107
+ }
108
+ var internalInstance = ReactInstanceMap.get(inst);
109
+ return internalInstance._renderedComponent.getPublicInstance();
102
110
  },
103
111
 
104
112
  findAllInRenderedTree: function(inst, test) {
@@ -107,19 +115,31 @@ var ReactTestUtils = {
107
115
  }
108
116
  var ret = test(inst) ? [inst] : [];
109
117
  if (ReactTestUtils.isDOMComponent(inst)) {
110
- var renderedChildren = inst._renderedChildren;
118
+ var internalInstance = ReactInstanceMap.get(inst);
119
+ var renderedChildren = internalInstance
120
+ ._renderedComponent
121
+ ._renderedChildren;
111
122
  var key;
112
123
  for (key in renderedChildren) {
113
124
  if (!renderedChildren.hasOwnProperty(key)) {
114
125
  continue;
115
126
  }
127
+ if (!renderedChildren[key].getPublicInstance) {
128
+ continue;
129
+ }
116
130
  ret = ret.concat(
117
- ReactTestUtils.findAllInRenderedTree(renderedChildren[key], test)
131
+ ReactTestUtils.findAllInRenderedTree(
132
+ renderedChildren[key].getPublicInstance(),
133
+ test
134
+ )
118
135
  );
119
136
  }
120
137
  } else if (ReactTestUtils.isCompositeComponent(inst)) {
121
138
  ret = ret.concat(
122
- ReactTestUtils.findAllInRenderedTree(inst._renderedComponent, test)
139
+ ReactTestUtils.findAllInRenderedTree(
140
+ ReactTestUtils.getRenderedChildOfCompositeComponent(inst),
141
+ test
142
+ )
123
143
  );
124
144
  }
125
145
  return ret;
@@ -134,8 +154,7 @@ var ReactTestUtils = {
134
154
  return ReactTestUtils.findAllInRenderedTree(root, function(inst) {
135
155
  var instClassName = inst.props.className;
136
156
  return ReactTestUtils.isDOMComponent(inst) && (
137
- instClassName &&
138
- (' ' + instClassName + ' ').indexOf(' ' + className + ' ') !== -1
157
+ (instClassName && (' ' + instClassName + ' ').indexOf(' ' + className + ' ') !== -1)
139
158
  );
140
159
  });
141
160
  },
@@ -150,7 +169,9 @@ var ReactTestUtils = {
150
169
  var all =
151
170
  ReactTestUtils.scryRenderedDOMComponentsWithClass(root, className);
152
171
  if (all.length !== 1) {
153
- throw new Error('Did not find exactly one match for class:' + className);
172
+ throw new Error('Did not find exactly one match '+
173
+ '(found: ' + all.length + ') for class:' + className
174
+ );
154
175
  }
155
176
  return all[0];
156
177
  },
@@ -231,21 +252,14 @@ var ReactTestUtils = {
231
252
  mockComponent: function(module, mockTagName) {
232
253
  mockTagName = mockTagName || module.mockTagName || "div";
233
254
 
234
- var ConvenienceConstructor = React.createClass({displayName: "ConvenienceConstructor",
235
- render: function() {
236
- return React.createElement(
237
- mockTagName,
238
- null,
239
- this.props.children
240
- );
241
- }
255
+ module.prototype.render.mockImplementation(function() {
256
+ return React.createElement(
257
+ mockTagName,
258
+ null,
259
+ this.props.children
260
+ );
242
261
  });
243
262
 
244
- module.mockImplementation(ConvenienceConstructor);
245
-
246
- module.type = ConvenienceConstructor.type;
247
- module.isReactLegacyFactory = true;
248
-
249
263
  return this;
250
264
  },
251
265
 
@@ -290,10 +304,53 @@ var ReactTestUtils = {
290
304
  };
291
305
  },
292
306
 
307
+ createRenderer: function() {
308
+ return new ReactShallowRenderer();
309
+ },
310
+
293
311
  Simulate: null,
294
312
  SimulateNative: {}
295
313
  };
296
314
 
315
+ /**
316
+ * @class ReactShallowRenderer
317
+ */
318
+ var ReactShallowRenderer = function() {
319
+ this._instance = null;
320
+ };
321
+
322
+ ReactShallowRenderer.prototype.getRenderOutput = function() {
323
+ return (this._instance && this._instance._renderedComponent) || null;
324
+ };
325
+
326
+ var ShallowComponentWrapper = function(inst) {
327
+ this._instance = inst;
328
+ };
329
+ assign(
330
+ ShallowComponentWrapper.prototype,
331
+ ReactCompositeComponent.ShallowMixin
332
+ );
333
+
334
+ ReactShallowRenderer.prototype.render = function(element, context) {
335
+ var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
336
+ this._render(element, transaction, context);
337
+ ReactUpdates.ReactReconcileTransaction.release(transaction);
338
+ };
339
+
340
+ ReactShallowRenderer.prototype._render = function(element, transaction, context) {
341
+ if (!this._instance) {
342
+ var rootID = ReactInstanceHandles.createReactRootID();
343
+ var instance = new ShallowComponentWrapper(new element.type(element.props));
344
+ instance.construct(element);
345
+
346
+ instance.mountComponent(rootID, transaction, context);
347
+
348
+ this._instance = instance;
349
+ } else {
350
+ this._instance.receiveComponent(element, transaction, context);
351
+ }
352
+ };
353
+
297
354
  /**
298
355
  * Exports:
299
356
  *