react 0.14.0-beta3 → 0.14.2

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 (89) hide show
  1. package/README.md +4 -4
  2. package/addons.js +2 -0
  3. package/dist/react-with-addons.js +1941 -1364
  4. package/dist/react-with-addons.min.js +6 -6
  5. package/dist/react.js +1704 -1242
  6. package/dist/react.min.js +6 -6
  7. package/lib/CSSProperty.js +15 -3
  8. package/lib/CSSPropertyOperations.js +15 -2
  9. package/lib/ChangeEventPlugin.js +5 -2
  10. package/lib/DOMChildrenOperations.js +12 -1
  11. package/lib/DOMPropertyOperations.js +14 -1
  12. package/lib/Danger.js +9 -4
  13. package/lib/EnterLeaveEventPlugin.js +13 -5
  14. package/lib/EventConstants.js +1 -1
  15. package/lib/EventPluginHub.js +18 -10
  16. package/lib/EventPluginUtils.js +23 -27
  17. package/lib/EventPropagators.js +1 -1
  18. package/lib/FallbackCompositionState.js +6 -0
  19. package/lib/HTMLDOMPropertyConfig.js +26 -2
  20. package/lib/PooledClass.js +1 -3
  21. package/lib/React.js +14 -3
  22. package/lib/ReactBrowserComponentMixin.js +1 -1
  23. package/lib/ReactBrowserEventEmitter.js +9 -3
  24. package/lib/ReactCSSTransitionGroup.js +33 -18
  25. package/lib/ReactCSSTransitionGroupChild.js +42 -25
  26. package/lib/ReactChildReconciler.js +3 -5
  27. package/lib/ReactChildren.js +70 -30
  28. package/lib/ReactClass.js +6 -6
  29. package/lib/ReactComponent.js +7 -6
  30. package/lib/ReactCompositeComponent.js +58 -7
  31. package/lib/ReactDOM.js +7 -5
  32. package/lib/ReactDOMComponent.js +146 -46
  33. package/lib/ReactDOMFeatureFlags.js +18 -0
  34. package/lib/ReactDOMIDOperations.js +1 -60
  35. package/lib/ReactDOMInput.js +10 -1
  36. package/lib/ReactDOMSelect.js +1 -1
  37. package/lib/ReactDOMSelection.js +16 -0
  38. package/lib/ReactDOMServer.js +3 -1
  39. package/lib/ReactDOMTextComponent.js +23 -10
  40. package/lib/ReactDOMTextarea.js +3 -1
  41. package/lib/ReactDefaultInjection.js +0 -2
  42. package/lib/ReactDefaultPerf.js +10 -4
  43. package/lib/ReactDefaultPerfAnalysis.js +7 -3
  44. package/lib/ReactElement.js +72 -35
  45. package/lib/ReactElementValidator.js +31 -75
  46. package/lib/ReactEmptyComponent.js +25 -61
  47. package/lib/ReactEmptyComponentRegistry.js +48 -0
  48. package/lib/ReactErrorUtils.js +56 -9
  49. package/lib/ReactEventEmitterMixin.js +1 -1
  50. package/lib/ReactEventListener.js +16 -9
  51. package/lib/ReactFragment.js +25 -116
  52. package/lib/ReactInjection.js +0 -2
  53. package/lib/ReactIsomorphic.js +4 -0
  54. package/lib/ReactLink.js +1 -1
  55. package/lib/ReactMount.js +127 -41
  56. package/lib/ReactMultiChild.js +37 -4
  57. package/lib/ReactOwner.js +2 -2
  58. package/lib/ReactPropTransferer.js +1 -1
  59. package/lib/ReactPropTypes.js +11 -8
  60. package/lib/ReactReconcileTransaction.js +4 -2
  61. package/lib/ReactReconciler.js +16 -17
  62. package/lib/ReactRef.js +13 -1
  63. package/lib/ReactServerRenderingTransaction.js +1 -0
  64. package/lib/ReactTestUtils.js +27 -15
  65. package/lib/ReactTransitionChildMapping.js +3 -6
  66. package/lib/ReactUpdateQueue.js +4 -4
  67. package/lib/ReactUpdates.js +1 -1
  68. package/lib/ReactVersion.js +14 -0
  69. package/lib/ReactWithAddons.js +10 -1
  70. package/lib/ResponderEventPlugin.js +1 -1
  71. package/lib/SelectEventPlugin.js +11 -1
  72. package/lib/SimpleEventPlugin.js +2 -23
  73. package/lib/SyntheticEvent.js +15 -1
  74. package/lib/Transaction.js +1 -1
  75. package/lib/canDefineProperty.js +24 -0
  76. package/lib/createHierarchyRenderer.js +1 -1
  77. package/lib/deprecated.js +3 -2
  78. package/lib/findDOMNode.js +1 -1
  79. package/lib/getTestDocument.js +4 -11
  80. package/lib/instantiateReactComponent.js +3 -5
  81. package/lib/reactComponentExpect.js +6 -0
  82. package/lib/shouldUpdateReactComponent.js +12 -8
  83. package/lib/sliceChildren.js +3 -20
  84. package/lib/traverseAllChildren.js +15 -9
  85. package/package.json +2 -2
  86. package/react.js +1 -51
  87. package/dist/JSXTransformer.js +0 -17949
  88. package/lib/joinClasses.js +0 -39
  89. package/lib/memoizeStringOnly.js +0 -31
@@ -35,6 +35,12 @@ function FallbackCompositionState(root) {
35
35
  }
36
36
 
37
37
  assign(FallbackCompositionState.prototype, {
38
+ destructor: function () {
39
+ this._root = null;
40
+ this._startText = null;
41
+ this._fallbackText = null;
42
+ },
43
+
38
44
  /**
39
45
  * Get current text of input.
40
46
  *
@@ -69,6 +69,7 @@ var HTMLDOMPropertyConfig = {
69
69
  crossOrigin: null,
70
70
  data: null, // For `<object />` acts as `src`.
71
71
  dateTime: MUST_USE_ATTRIBUTE,
72
+ 'default': HAS_BOOLEAN_VALUE,
72
73
  defer: HAS_BOOLEAN_VALUE,
73
74
  dir: null,
74
75
  disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
@@ -93,9 +94,11 @@ var HTMLDOMPropertyConfig = {
93
94
  icon: null,
94
95
  id: MUST_USE_PROPERTY,
95
96
  inputMode: MUST_USE_ATTRIBUTE,
97
+ integrity: null,
96
98
  is: MUST_USE_ATTRIBUTE,
97
99
  keyParams: MUST_USE_ATTRIBUTE,
98
100
  keyType: MUST_USE_ATTRIBUTE,
101
+ kind: null,
99
102
  label: null,
100
103
  lang: null,
101
104
  list: MUST_USE_ATTRIBUTE,
@@ -141,10 +144,12 @@ var HTMLDOMPropertyConfig = {
141
144
  spellCheck: null,
142
145
  src: null,
143
146
  srcDoc: MUST_USE_PROPERTY,
147
+ srcLang: null,
144
148
  srcSet: MUST_USE_ATTRIBUTE,
145
149
  start: HAS_NUMERIC_VALUE,
146
150
  step: null,
147
151
  style: null,
152
+ summary: null,
148
153
  tabIndex: null,
149
154
  target: null,
150
155
  title: null,
@@ -155,6 +160,19 @@ var HTMLDOMPropertyConfig = {
155
160
  wmode: MUST_USE_ATTRIBUTE,
156
161
  wrap: null,
157
162
 
163
+ /**
164
+ * RDFa Properties
165
+ */
166
+ about: MUST_USE_ATTRIBUTE,
167
+ datatype: MUST_USE_ATTRIBUTE,
168
+ inlist: MUST_USE_ATTRIBUTE,
169
+ prefix: MUST_USE_ATTRIBUTE,
170
+ // property is also supported for OpenGraph in meta tags.
171
+ property: MUST_USE_ATTRIBUTE,
172
+ resource: MUST_USE_ATTRIBUTE,
173
+ 'typeof': MUST_USE_ATTRIBUTE,
174
+ vocab: MUST_USE_ATTRIBUTE,
175
+
158
176
  /**
159
177
  * Non-standard Properties
160
178
  */
@@ -162,6 +180,10 @@ var HTMLDOMPropertyConfig = {
162
180
  // keyboard hints.
163
181
  autoCapitalize: null,
164
182
  autoCorrect: null,
183
+ // autoSave allows WebKit/Blink to persist values of input fields on page reloads
184
+ autoSave: null,
185
+ // color is for Safari mask-icon link
186
+ color: null,
165
187
  // itemProp, itemScope, itemType are for
166
188
  // Microdata support. See http://schema.org/docs/gs.html
167
189
  itemProp: MUST_USE_ATTRIBUTE,
@@ -172,8 +194,9 @@ var HTMLDOMPropertyConfig = {
172
194
  // https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api
173
195
  itemID: MUST_USE_ATTRIBUTE,
174
196
  itemRef: MUST_USE_ATTRIBUTE,
175
- // property is supported for OpenGraph in meta tags.
176
- property: null,
197
+ // results show looking glass icon and recent searches on input
198
+ // search fields in WebKit/Blink
199
+ results: null,
177
200
  // IE-only attribute that specifies security restrictions on an iframe
178
201
  // as an alternative to the sandbox attribute on IE<10
179
202
  security: MUST_USE_ATTRIBUTE,
@@ -192,6 +215,7 @@ var HTMLDOMPropertyConfig = {
192
215
  autoCorrect: 'autocorrect',
193
216
  autoFocus: 'autofocus',
194
217
  autoPlay: 'autoplay',
218
+ autoSave: 'autosave',
195
219
  // `encoding` is equivalent to `enctype`, IE8 lacks an `enctype` setter.
196
220
  // http://www.w3.org/TR/html5/forms.html#dom-fs-encoding
197
221
  encType: 'encoding',
@@ -78,9 +78,7 @@ var fiveArgumentPooler = function (a1, a2, a3, a4, a5) {
78
78
  var standardReleaser = function (instance) {
79
79
  var Klass = this;
80
80
  !(instance instanceof Klass) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : invariant(false) : undefined;
81
- if (instance.destructor) {
82
- instance.destructor();
83
- }
81
+ instance.destructor();
84
82
  if (Klass.instancePool.length < Klass.poolSize) {
85
83
  Klass.instancePool.push(instance);
86
84
  }
package/lib/React.js CHANGED
@@ -16,13 +16,24 @@ var ReactDOMServer = require('./ReactDOMServer');
16
16
  var ReactIsomorphic = require('./ReactIsomorphic');
17
17
 
18
18
  var assign = require('./Object.assign');
19
+ var deprecated = require('./deprecated');
19
20
 
21
+ // `version` will be added here by ReactIsomorphic.
20
22
  var React = {};
21
23
 
22
24
  assign(React, ReactIsomorphic);
23
- assign(React, ReactDOM);
24
- assign(React, ReactDOMServer);
25
25
 
26
- React.version = '0.14.0-beta3';
26
+ assign(React, {
27
+ // ReactDOM
28
+ findDOMNode: deprecated('findDOMNode', 'ReactDOM', 'react-dom', ReactDOM, ReactDOM.findDOMNode),
29
+ render: deprecated('render', 'ReactDOM', 'react-dom', ReactDOM, ReactDOM.render),
30
+ unmountComponentAtNode: deprecated('unmountComponentAtNode', 'ReactDOM', 'react-dom', ReactDOM, ReactDOM.unmountComponentAtNode),
31
+
32
+ // ReactDOMServer
33
+ renderToString: deprecated('renderToString', 'ReactDOMServer', 'react-dom/server', ReactDOMServer, ReactDOMServer.renderToString),
34
+ renderToStaticMarkup: deprecated('renderToStaticMarkup', 'ReactDOMServer', 'react-dom/server', ReactDOMServer, ReactDOMServer.renderToStaticMarkup)
35
+ });
36
+
37
+ React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ReactDOM;
27
38
 
28
39
  module.exports = React;
@@ -27,7 +27,7 @@ var ReactBrowserComponentMixin = {
27
27
  * @protected
28
28
  */
29
29
  getDOMNode: function () {
30
- process.env.NODE_ENV !== 'production' ? warning(this.constructor[didWarnKey], '%s.getDOMNode(...) is deprecated. Please use ' + 'React.findDOMNode(instance) instead.', ReactInstanceMap.get(this).getName() || this.tagName || 'Unknown') : undefined;
30
+ process.env.NODE_ENV !== 'production' ? warning(this.constructor[didWarnKey], '%s.getDOMNode(...) is deprecated. Please use ' + 'ReactDOM.findDOMNode(instance) instead.', ReactInstanceMap.get(this).getName() || this.tagName || 'Unknown') : undefined;
31
31
  this.constructor[didWarnKey] = true;
32
32
  return findDOMNode(this);
33
33
  }
@@ -16,6 +16,7 @@ var EventConstants = require('./EventConstants');
16
16
  var EventPluginHub = require('./EventPluginHub');
17
17
  var EventPluginRegistry = require('./EventPluginRegistry');
18
18
  var ReactEventEmitterMixin = require('./ReactEventEmitterMixin');
19
+ var ReactPerf = require('./ReactPerf');
19
20
  var ViewportMetrics = require('./ViewportMetrics');
20
21
 
21
22
  var assign = require('./Object.assign');
@@ -123,15 +124,15 @@ var topEventMapping = {
123
124
  topMouseOut: 'mouseout',
124
125
  topMouseOver: 'mouseover',
125
126
  topMouseUp: 'mouseup',
126
- topPause: 'pause',
127
127
  topPaste: 'paste',
128
+ topPause: 'pause',
128
129
  topPlay: 'play',
129
130
  topPlaying: 'playing',
130
131
  topProgress: 'progress',
131
132
  topRateChange: 'ratechange',
132
- topSeeking: 'seeking',
133
- topSeeked: 'seeked',
134
133
  topScroll: 'scroll',
134
+ topSeeked: 'seeked',
135
+ topSeeking: 'seeking',
135
136
  topSelectionChange: 'selectionchange',
136
137
  topStalled: 'stalled',
137
138
  topSuspend: 'suspend',
@@ -315,4 +316,9 @@ var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, {
315
316
 
316
317
  });
317
318
 
319
+ ReactPerf.measureMethods(ReactBrowserEventEmitter, 'ReactBrowserEventEmitter', {
320
+ putListener: 'putListener',
321
+ deleteListener: 'deleteListener'
322
+ });
323
+
318
324
  module.exports = ReactBrowserEventEmitter;
@@ -16,28 +16,40 @@ var React = require('./React');
16
16
 
17
17
  var assign = require('./Object.assign');
18
18
 
19
- var ReactTransitionGroup = React.createFactory(require('./ReactTransitionGroup'));
20
- var ReactCSSTransitionGroupChild = React.createFactory(require('./ReactCSSTransitionGroupChild'));
19
+ var ReactTransitionGroup = require('./ReactTransitionGroup');
20
+ var ReactCSSTransitionGroupChild = require('./ReactCSSTransitionGroupChild');
21
+
22
+ function createTransitionTimeoutPropValidator(transitionType) {
23
+ var timeoutPropName = 'transition' + transitionType + 'Timeout';
24
+ var enabledPropName = 'transition' + transitionType;
25
+
26
+ return function (props) {
27
+ // If the transition is enabled
28
+ if (props[enabledPropName]) {
29
+ // If no timeout duration is provided
30
+ if (props[timeoutPropName] == null) {
31
+ return new Error(timeoutPropName + ' wasn\'t supplied to ReactCSSTransitionGroup: ' + 'this can cause unreliable animations and won\'t be supported in ' + 'a future version of React. See ' + 'https://fb.me/react-animation-transition-group-timeout for more ' + 'information.');
32
+
33
+ // If the duration isn't a number
34
+ } else if (typeof props[timeoutPropName] !== 'number') {
35
+ return new Error(timeoutPropName + ' must be a number (in milliseconds)');
36
+ }
37
+ }
38
+ };
39
+ }
21
40
 
22
41
  var ReactCSSTransitionGroup = React.createClass({
23
42
  displayName: 'ReactCSSTransitionGroup',
24
43
 
25
44
  propTypes: {
26
- transitionName: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.shape({
27
- enter: React.PropTypes.string,
28
- leave: React.PropTypes.string,
29
- active: React.PropTypes.string
30
- }), React.PropTypes.shape({
31
- enter: React.PropTypes.string,
32
- enterActive: React.PropTypes.string,
33
- leave: React.PropTypes.string,
34
- leaveActive: React.PropTypes.string,
35
- appear: React.PropTypes.string,
36
- appearActive: React.PropTypes.string
37
- })]).isRequired,
45
+ transitionName: ReactCSSTransitionGroupChild.propTypes.name,
46
+
38
47
  transitionAppear: React.PropTypes.bool,
39
48
  transitionEnter: React.PropTypes.bool,
40
- transitionLeave: React.PropTypes.bool
49
+ transitionLeave: React.PropTypes.bool,
50
+ transitionAppearTimeout: createTransitionTimeoutPropValidator('Appear'),
51
+ transitionEnterTimeout: createTransitionTimeoutPropValidator('Enter'),
52
+ transitionLeaveTimeout: createTransitionTimeoutPropValidator('Leave')
41
53
  },
42
54
 
43
55
  getDefaultProps: function () {
@@ -52,16 +64,19 @@ var ReactCSSTransitionGroup = React.createClass({
52
64
  // We need to provide this childFactory so that
53
65
  // ReactCSSTransitionGroupChild can receive updates to name, enter, and
54
66
  // leave while it is leaving.
55
- return ReactCSSTransitionGroupChild({
67
+ return React.createElement(ReactCSSTransitionGroupChild, {
56
68
  name: this.props.transitionName,
57
69
  appear: this.props.transitionAppear,
58
70
  enter: this.props.transitionEnter,
59
- leave: this.props.transitionLeave
71
+ leave: this.props.transitionLeave,
72
+ appearTimeout: this.props.transitionAppearTimeout,
73
+ enterTimeout: this.props.transitionEnterTimeout,
74
+ leaveTimeout: this.props.transitionLeaveTimeout
60
75
  }, child);
61
76
  },
62
77
 
63
78
  render: function () {
64
- return ReactTransitionGroup(assign({}, this.props, { childFactory: this._wrapChild }));
79
+ return React.createElement(ReactTransitionGroup, assign({}, this.props, { childFactory: this._wrapChild }));
65
80
  }
66
81
  });
67
82
 
@@ -13,33 +13,49 @@
13
13
  'use strict';
14
14
 
15
15
  var React = require('./React');
16
+ var ReactDOM = require('./ReactDOM');
16
17
 
17
18
  var CSSCore = require('fbjs/lib/CSSCore');
18
19
  var ReactTransitionEvents = require('./ReactTransitionEvents');
19
20
 
20
21
  var onlyChild = require('./onlyChild');
21
- var warning = require('fbjs/lib/warning');
22
22
 
23
23
  // We don't remove the element from the DOM until we receive an animationend or
24
24
  // transitionend event. If the user screws up and forgets to add an animation
25
25
  // their node will be stuck in the DOM forever, so we detect if an animation
26
26
  // does not start and if it doesn't, we just call the end listener immediately.
27
27
  var TICK = 17;
28
- var NO_EVENT_TIMEOUT = 5000;
29
-
30
- var noEventListener = null;
31
-
32
- if (process.env.NODE_ENV !== 'production') {
33
- noEventListener = function () {
34
- process.env.NODE_ENV !== 'production' ? warning(false, 'transition(): tried to perform an animation without ' + 'an animationend or transitionend event after timeout (' + '%sms). You should either disable this ' + 'transition in JS or add a CSS animation/transition.', NO_EVENT_TIMEOUT) : undefined;
35
- };
36
- }
37
28
 
38
29
  var ReactCSSTransitionGroupChild = React.createClass({
39
30
  displayName: 'ReactCSSTransitionGroupChild',
40
31
 
41
- transition: function (animationType, finishCallback) {
42
- var node = React.findDOMNode(this);
32
+ propTypes: {
33
+ name: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.shape({
34
+ enter: React.PropTypes.string,
35
+ leave: React.PropTypes.string,
36
+ active: React.PropTypes.string
37
+ }), React.PropTypes.shape({
38
+ enter: React.PropTypes.string,
39
+ enterActive: React.PropTypes.string,
40
+ leave: React.PropTypes.string,
41
+ leaveActive: React.PropTypes.string,
42
+ appear: React.PropTypes.string,
43
+ appearActive: React.PropTypes.string
44
+ })]).isRequired,
45
+
46
+ // Once we require timeouts to be specified, we can remove the
47
+ // boolean flags (appear etc.) and just accept a number
48
+ // or a bool for the timeout flags (appearTimeout etc.)
49
+ appear: React.PropTypes.bool,
50
+ enter: React.PropTypes.bool,
51
+ leave: React.PropTypes.bool,
52
+ appearTimeout: React.PropTypes.number,
53
+ enterTimeout: React.PropTypes.number,
54
+ leaveTimeout: React.PropTypes.number
55
+ },
56
+
57
+ transition: function (animationType, finishCallback, userSpecifiedDelay) {
58
+ var node = ReactDOM.findDOMNode(this);
43
59
 
44
60
  if (!node) {
45
61
  if (finishCallback) {
@@ -50,16 +66,14 @@ var ReactCSSTransitionGroupChild = React.createClass({
50
66
 
51
67
  var className = this.props.name[animationType] || this.props.name + '-' + animationType;
52
68
  var activeClassName = this.props.name[animationType + 'Active'] || className + '-active';
53
-
54
- var noEventTimeout = null;
69
+ var timeout = null;
55
70
 
56
71
  var endListener = function (e) {
57
72
  if (e && e.target !== node) {
58
73
  return;
59
74
  }
60
- if (process.env.NODE_ENV !== 'production') {
61
- clearTimeout(noEventTimeout);
62
- }
75
+
76
+ clearTimeout(timeout);
63
77
 
64
78
  CSSCore.removeClass(node, className);
65
79
  CSSCore.removeClass(node, activeClassName);
@@ -73,15 +87,18 @@ var ReactCSSTransitionGroupChild = React.createClass({
73
87
  }
74
88
  };
75
89
 
76
- ReactTransitionEvents.addEndEventListener(node, endListener);
77
-
78
90
  CSSCore.addClass(node, className);
79
91
 
80
92
  // Need to do this to actually trigger a transition.
81
93
  this.queueClass(activeClassName);
82
94
 
83
- if (process.env.NODE_ENV !== 'production') {
84
- noEventTimeout = setTimeout(noEventListener, NO_EVENT_TIMEOUT);
95
+ // If the user specified a timeout delay.
96
+ if (userSpecifiedDelay) {
97
+ // Clean-up the animation after the specified delay
98
+ timeout = setTimeout(endListener, userSpecifiedDelay);
99
+ } else {
100
+ // DEPRECATED: this listener will be removed in a future version of react
101
+ ReactTransitionEvents.addEndEventListener(node, endListener);
85
102
  }
86
103
  },
87
104
 
@@ -95,7 +112,7 @@ var ReactCSSTransitionGroupChild = React.createClass({
95
112
 
96
113
  flushClassNameQueue: function () {
97
114
  if (this.isMounted()) {
98
- this.classNameQueue.forEach(CSSCore.addClass.bind(CSSCore, React.findDOMNode(this)));
115
+ this.classNameQueue.forEach(CSSCore.addClass.bind(CSSCore, ReactDOM.findDOMNode(this)));
99
116
  }
100
117
  this.classNameQueue.length = 0;
101
118
  this.timeout = null;
@@ -113,7 +130,7 @@ var ReactCSSTransitionGroupChild = React.createClass({
113
130
 
114
131
  componentWillAppear: function (done) {
115
132
  if (this.props.appear) {
116
- this.transition('appear', done);
133
+ this.transition('appear', done, this.props.appearTimeout);
117
134
  } else {
118
135
  done();
119
136
  }
@@ -121,7 +138,7 @@ var ReactCSSTransitionGroupChild = React.createClass({
121
138
 
122
139
  componentWillEnter: function (done) {
123
140
  if (this.props.enter) {
124
- this.transition('enter', done);
141
+ this.transition('enter', done, this.props.enterTimeout);
125
142
  } else {
126
143
  done();
127
144
  }
@@ -129,7 +146,7 @@ var ReactCSSTransitionGroupChild = React.createClass({
129
146
 
130
147
  componentWillLeave: function (done) {
131
148
  if (this.props.leave) {
132
- this.transition('leave', done);
149
+ this.transition('leave', done, this.props.leaveTimeout);
133
150
  } else {
134
151
  done();
135
152
  }
@@ -14,7 +14,6 @@
14
14
 
15
15
  var ReactReconciler = require('./ReactReconciler');
16
16
 
17
- var flattenChildren = require('./flattenChildren');
18
17
  var instantiateReactComponent = require('./instantiateReactComponent');
19
18
  var shouldUpdateReactComponent = require('./shouldUpdateReactComponent');
20
19
  var traverseAllChildren = require('./traverseAllChildren');
@@ -58,19 +57,18 @@ var ReactChildReconciler = {
58
57
  * Updates the rendered children and returns a new set of children.
59
58
  *
60
59
  * @param {?object} prevChildren Previously initialized set of children.
61
- * @param {?object} nextNestedChildrenElements Nested child element maps.
60
+ * @param {?object} nextChildren Flat child element maps.
62
61
  * @param {ReactReconcileTransaction} transaction
63
62
  * @param {object} context
64
63
  * @return {?object} A new set of child instances.
65
64
  * @internal
66
65
  */
67
- updateChildren: function (prevChildren, nextNestedChildrenElements, transaction, context) {
66
+ updateChildren: function (prevChildren, nextChildren, transaction, context) {
68
67
  // We currently don't have a way to track moves here but if we use iterators
69
68
  // instead of for..in we can zip the iterators and check if an item has
70
69
  // moved.
71
70
  // TODO: If nothing has changed, return the prevChildren object so that we
72
71
  // can quickly bailout if nothing has changed.
73
- var nextChildren = flattenChildren(nextNestedChildrenElements);
74
72
  if (!nextChildren && !prevChildren) {
75
73
  return null;
76
74
  }
@@ -82,7 +80,7 @@ var ReactChildReconciler = {
82
80
  var prevChild = prevChildren && prevChildren[name];
83
81
  var prevElement = prevChild && prevChild._currentElement;
84
82
  var nextElement = nextChildren[name];
85
- if (shouldUpdateReactComponent(prevElement, nextElement)) {
83
+ if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {
86
84
  ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);
87
85
  nextChildren[name] = prevChild;
88
86
  } else {
@@ -12,13 +12,18 @@
12
12
  'use strict';
13
13
 
14
14
  var PooledClass = require('./PooledClass');
15
- var ReactFragment = require('./ReactFragment');
15
+ var ReactElement = require('./ReactElement');
16
16
 
17
+ var emptyFunction = require('fbjs/lib/emptyFunction');
17
18
  var traverseAllChildren = require('./traverseAllChildren');
18
- var warning = require('fbjs/lib/warning');
19
19
 
20
20
  var twoArgumentPooler = PooledClass.twoArgumentPooler;
21
- var threeArgumentPooler = PooledClass.threeArgumentPooler;
21
+ var fourArgumentPooler = PooledClass.fourArgumentPooler;
22
+
23
+ var userProvidedKeyEscapeRegex = /\/(?!\/)/g;
24
+ function escapeUserProvidedKey(text) {
25
+ return ('' + text).replace(userProvidedKeyEscapeRegex, '//');
26
+ }
22
27
 
23
28
  /**
24
29
  * PooledClass representing the bookkeeping associated with performing a child
@@ -33,11 +38,18 @@ function ForEachBookKeeping(forEachFunction, forEachContext) {
33
38
  this.context = forEachContext;
34
39
  this.count = 0;
35
40
  }
41
+ ForEachBookKeeping.prototype.destructor = function () {
42
+ this.func = null;
43
+ this.context = null;
44
+ this.count = 0;
45
+ };
36
46
  PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler);
37
47
 
38
- function forEachSingleChild(traverseContext, child, name) {
39
- var bookKeeping = traverseContext;
40
- bookKeeping.func.call(bookKeeping.context, child, bookKeeping.count++);
48
+ function forEachSingleChild(bookKeeping, child, name) {
49
+ var func = bookKeeping.func;
50
+ var context = bookKeeping.context;
51
+
52
+ func.call(context, child, bookKeeping.count++);
41
53
  }
42
54
 
43
55
  /**
@@ -54,7 +66,6 @@ function forEachChildren(children, forEachFunc, forEachContext) {
54
66
  if (children == null) {
55
67
  return children;
56
68
  }
57
-
58
69
  var traverseContext = ForEachBookKeeping.getPooled(forEachFunc, forEachContext);
59
70
  traverseAllChildren(children, forEachSingleChild, traverseContext);
60
71
  ForEachBookKeeping.release(traverseContext);
@@ -69,27 +80,50 @@ function forEachChildren(children, forEachFunc, forEachContext) {
69
80
  * @param {!function} mapFunction Function to perform mapping with.
70
81
  * @param {?*} mapContext Context to perform mapping with.
71
82
  */
72
- function MapBookKeeping(mapResult, mapFunction, mapContext) {
83
+ function MapBookKeeping(mapResult, keyPrefix, mapFunction, mapContext) {
73
84
  this.result = mapResult;
85
+ this.keyPrefix = keyPrefix;
74
86
  this.func = mapFunction;
75
87
  this.context = mapContext;
76
88
  this.count = 0;
77
89
  }
78
- PooledClass.addPoolingTo(MapBookKeeping, threeArgumentPooler);
79
-
80
- function mapSingleChildIntoContext(traverseContext, child, name) {
81
- var bookKeeping = traverseContext;
82
- var mapResult = bookKeeping.result;
83
-
84
- var keyUnique = mapResult[name] === undefined;
85
- if (process.env.NODE_ENV !== 'production') {
86
- process.env.NODE_ENV !== 'production' ? warning(keyUnique, 'ReactChildren.map(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', name) : undefined;
90
+ MapBookKeeping.prototype.destructor = function () {
91
+ this.result = null;
92
+ this.keyPrefix = null;
93
+ this.func = null;
94
+ this.context = null;
95
+ this.count = 0;
96
+ };
97
+ PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);
98
+
99
+ function mapSingleChildIntoContext(bookKeeping, child, childKey) {
100
+ var result = bookKeeping.result;
101
+ var keyPrefix = bookKeeping.keyPrefix;
102
+ var func = bookKeeping.func;
103
+ var context = bookKeeping.context;
104
+
105
+ var mappedChild = func.call(context, child, bookKeeping.count++);
106
+ if (Array.isArray(mappedChild)) {
107
+ mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);
108
+ } else if (mappedChild != null) {
109
+ if (ReactElement.isValidElement(mappedChild)) {
110
+ mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,
111
+ // Keep both the (mapped) and old keys if they differ, just as
112
+ // traverseAllChildren used to do for objects as children
113
+ keyPrefix + (mappedChild !== child ? escapeUserProvidedKey(mappedChild.key || '') + '/' : '') + childKey);
114
+ }
115
+ result.push(mappedChild);
87
116
  }
117
+ }
88
118
 
89
- if (keyUnique) {
90
- var mappedChild = bookKeeping.func.call(bookKeeping.context, child, bookKeeping.count++);
91
- mapResult[name] = mappedChild;
119
+ function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
120
+ var escapedPrefix = '';
121
+ if (prefix != null) {
122
+ escapedPrefix = escapeUserProvidedKey(prefix) + '/';
92
123
  }
124
+ var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);
125
+ traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
126
+ MapBookKeeping.release(traverseContext);
93
127
  }
94
128
 
95
129
  /**
@@ -98,9 +132,6 @@ function mapSingleChildIntoContext(traverseContext, child, name) {
98
132
  * The provided mapFunction(child, key, index) will be called for each
99
133
  * leaf child.
100
134
  *
101
- * TODO: This may likely break any calls to `ReactChildren.map` that were
102
- * previously relying on the fact that we guarded against null children.
103
- *
104
135
  * @param {?*} children Children tree container.
105
136
  * @param {function(*, int)} func The map function.
106
137
  * @param {*} context Context for mapFunction.
@@ -110,12 +141,9 @@ function mapChildren(children, func, context) {
110
141
  if (children == null) {
111
142
  return children;
112
143
  }
113
-
114
- var mapResult = {};
115
- var traverseContext = MapBookKeeping.getPooled(mapResult, func, context);
116
- traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
117
- MapBookKeeping.release(traverseContext);
118
- return ReactFragment.create(mapResult);
144
+ var result = [];
145
+ mapIntoWithKeyPrefixInternal(children, result, null, func, context);
146
+ return result;
119
147
  }
120
148
 
121
149
  function forEachSingleChildDummy(traverseContext, child, name) {
@@ -133,10 +161,22 @@ function countChildren(children, context) {
133
161
  return traverseAllChildren(children, forEachSingleChildDummy, null);
134
162
  }
135
163
 
164
+ /**
165
+ * Flatten a children object (typically specified as `props.children`) and
166
+ * return an array with appropriately re-keyed children.
167
+ */
168
+ function toArray(children) {
169
+ var result = [];
170
+ mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);
171
+ return result;
172
+ }
173
+
136
174
  var ReactChildren = {
137
175
  forEach: forEachChildren,
138
176
  map: mapChildren,
139
- count: countChildren
177
+ mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,
178
+ count: countChildren,
179
+ toArray: toArray
140
180
  };
141
181
 
142
182
  module.exports = ReactChildren;