react 0.14.0-alpha3 → 0.14.0-beta1
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.
- package/README.md +5 -2
- package/addons.js +2 -2
- package/dist/JSXTransformer.js +69 -70
- package/dist/react-with-addons.js +2047 -2078
- package/dist/react-with-addons.min.js +6 -6
- package/dist/react.js +1861 -1904
- package/dist/react.min.js +5 -5
- package/lib/{AutoFocusMixin.js → AutoFocusUtils.js} +13 -3
- package/lib/ChangeEventPlugin.js +4 -2
- package/lib/DOMProperty.js +81 -116
- package/lib/DOMPropertyOperations.js +70 -25
- package/lib/EnterLeaveEventPlugin.js +3 -3
- package/lib/EventPluginHub.js +2 -2
- package/lib/EventPluginUtils.js +6 -6
- package/lib/HTMLDOMPropertyConfig.js +8 -1
- package/lib/LinkedValueUtils.js +45 -33
- package/lib/PooledClass.js +12 -0
- package/lib/React.js +1 -1
- package/lib/ReactCSSTransitionGroupChild.js +8 -0
- package/lib/ReactChildren.js +3 -3
- package/lib/ReactClass.js +29 -47
- package/lib/ReactComponent.js +11 -6
- package/lib/ReactComponentWithPureRenderMixin.js +2 -2
- package/lib/ReactCompositeComponent.js +45 -72
- package/lib/ReactDOM.js +1 -0
- package/lib/ReactDOMButton.js +15 -26
- package/lib/ReactDOMClient.js +9 -4
- package/lib/ReactDOMComponent.js +302 -24
- package/lib/ReactDOMIDOperations.js +14 -0
- package/lib/ReactDOMInput.js +78 -94
- package/lib/ReactDOMOption.js +19 -38
- package/lib/ReactDOMSelect.js +85 -95
- package/lib/ReactDOMTextarea.js +39 -52
- package/lib/ReactDefaultInjection.js +0 -47
- package/lib/ReactElement.js +18 -79
- package/lib/ReactElementValidator.js +29 -98
- package/lib/ReactErrorUtils.js +1 -1
- package/lib/ReactEventEmitterMixin.js +2 -3
- package/lib/ReactEventListener.js +43 -3
- package/lib/ReactFragment.js +12 -7
- package/lib/ReactInputSelection.js +4 -3
- package/lib/ReactInstanceHandles.js +3 -2
- package/lib/ReactMount.js +20 -40
- package/lib/ReactNativeComponent.js +0 -5
- package/lib/ReactNoopUpdateQueue.js +118 -0
- package/lib/ReactPropTypes.js +3 -3
- package/lib/ReactReconcileTransaction.js +2 -2
- package/lib/ReactReconciler.js +8 -10
- package/lib/ReactServerBatchingStrategy.js +23 -0
- package/lib/ReactServerRendering.js +13 -0
- package/lib/ReactServerRenderingTransaction.js +2 -2
- package/lib/ReactTestUtils.js +56 -33
- package/lib/ReactUpdateQueue.js +51 -26
- package/lib/ReactUpdates.js +0 -3
- package/lib/ReactWithAddons.js +0 -2
- package/lib/SelectEventPlugin.js +6 -7
- package/lib/SimpleEventPlugin.js +4 -4
- package/lib/SyntheticClipboardEvent.js +2 -2
- package/lib/SyntheticCompositionEvent.js +2 -2
- package/lib/SyntheticDragEvent.js +2 -2
- package/lib/SyntheticEvent.js +6 -5
- package/lib/SyntheticFocusEvent.js +2 -2
- package/lib/SyntheticInputEvent.js +2 -2
- package/lib/SyntheticKeyboardEvent.js +2 -2
- package/lib/SyntheticMouseEvent.js +2 -2
- package/lib/SyntheticTouchEvent.js +2 -2
- package/lib/SyntheticUIEvent.js +2 -2
- package/lib/SyntheticWheelEvent.js +2 -2
- package/lib/Transaction.js +10 -4
- package/lib/cloneWithProps.js +1 -1
- package/lib/deprecated.js +47 -0
- package/lib/findDOMNode.js +2 -3
- package/lib/forEachAccumulated.js +1 -1
- package/lib/getEventCharCode.js +1 -1
- package/lib/getEventModifierState.js +0 -1
- package/lib/getMarkupWrap.js +13 -35
- package/lib/instantiateReactComponent.js +13 -9
- package/lib/isTextInputElement.js +2 -1
- package/lib/joinClasses.js +1 -1
- package/lib/setInnerHTML.js +1 -1
- package/lib/traverseAllChildren.js +1 -1
- package/lib/warning.js +0 -4
- package/package.json +1 -1
- package/react.js +53 -1
- package/addons/CSSTransitionGroup.js +0 -1
- package/addons/LinkedStateMixin.js +0 -1
- package/addons/Perf.js +0 -1
- package/addons/PureRenderMixin.js +0 -1
- package/addons/TestUtils.js +0 -1
- package/addons/TransitionGroup.js +0 -1
- package/addons/batchedUpdates.js +0 -1
- package/addons/cloneWithProps.js +0 -1
- package/addons/createFragment.js +0 -1
- package/addons/renderSubtreeIntoContainer.js +0 -1
- package/addons/shallowCompare.js +0 -1
- package/addons/update.js +0 -1
- package/lib/LocalEventTrapMixin.js +0 -46
- package/lib/ReactContext.js +0 -32
- package/lib/ReactDOMForm.js +0 -47
- package/lib/ReactDOMIframe.js +0 -43
- package/lib/ReactDOMImg.js +0 -44
- package/lib/ReactLifeCycle.js +0 -35
- package/lib/createFullPageComponent.js +0 -51
package/lib/ReactComponent.js
CHANGED
|
@@ -11,17 +11,22 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var ReactNoopUpdateQueue = require("./ReactNoopUpdateQueue");
|
|
15
15
|
|
|
16
|
+
var emptyObject = require("./emptyObject");
|
|
16
17
|
var invariant = require("./invariant");
|
|
17
18
|
var warning = require("./warning");
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Base class helpers for the updating state of a component.
|
|
21
22
|
*/
|
|
22
|
-
function ReactComponent(props, context) {
|
|
23
|
+
function ReactComponent(props, context, updater) {
|
|
23
24
|
this.props = props;
|
|
24
25
|
this.context = context;
|
|
26
|
+
this.refs = emptyObject;
|
|
27
|
+
// We initialize the default updater but the real one gets injected by the
|
|
28
|
+
// renderer.
|
|
29
|
+
this.updater = updater || ReactNoopUpdateQueue;
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
/**
|
|
@@ -54,9 +59,9 @@ ReactComponent.prototype.setState = function (partialState, callback) {
|
|
|
54
59
|
if ('production' !== process.env.NODE_ENV) {
|
|
55
60
|
'production' !== process.env.NODE_ENV ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : undefined;
|
|
56
61
|
}
|
|
57
|
-
|
|
62
|
+
this.updater.enqueueSetState(this, partialState);
|
|
58
63
|
if (callback) {
|
|
59
|
-
|
|
64
|
+
this.updater.enqueueCallback(this, callback);
|
|
60
65
|
}
|
|
61
66
|
};
|
|
62
67
|
|
|
@@ -75,9 +80,9 @@ ReactComponent.prototype.setState = function (partialState, callback) {
|
|
|
75
80
|
* @protected
|
|
76
81
|
*/
|
|
77
82
|
ReactComponent.prototype.forceUpdate = function (callback) {
|
|
78
|
-
|
|
83
|
+
this.updater.enqueueForceUpdate(this);
|
|
79
84
|
if (callback) {
|
|
80
|
-
|
|
85
|
+
this.updater.enqueueCallback(this, callback);
|
|
81
86
|
}
|
|
82
87
|
};
|
|
83
88
|
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
7
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
8
|
*
|
|
9
|
-
* @providesModule ReactComponentWithPureRenderMixin
|
|
10
|
-
*/
|
|
9
|
+
* @providesModule ReactComponentWithPureRenderMixin
|
|
10
|
+
*/
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
@@ -12,18 +12,14 @@
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
14
|
var ReactComponentEnvironment = require("./ReactComponentEnvironment");
|
|
15
|
-
var ReactContext = require("./ReactContext");
|
|
16
15
|
var ReactCurrentOwner = require("./ReactCurrentOwner");
|
|
17
16
|
var ReactElement = require("./ReactElement");
|
|
18
|
-
var ReactElementValidator = require("./ReactElementValidator");
|
|
19
17
|
var ReactInstanceMap = require("./ReactInstanceMap");
|
|
20
|
-
var ReactLifeCycle = require("./ReactLifeCycle");
|
|
21
|
-
var ReactNativeComponent = require("./ReactNativeComponent");
|
|
22
18
|
var ReactPerf = require("./ReactPerf");
|
|
23
19
|
var ReactPropTypeLocations = require("./ReactPropTypeLocations");
|
|
24
20
|
var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
|
|
25
21
|
var ReactReconciler = require("./ReactReconciler");
|
|
26
|
-
var
|
|
22
|
+
var ReactUpdateQueue = require("./ReactUpdateQueue");
|
|
27
23
|
|
|
28
24
|
var assign = require("./Object.assign");
|
|
29
25
|
var emptyObject = require("./emptyObject");
|
|
@@ -104,7 +100,7 @@ var ReactCompositeComponentMixin = {
|
|
|
104
100
|
|
|
105
101
|
this._context = null;
|
|
106
102
|
this._mountOrder = 0;
|
|
107
|
-
this.
|
|
103
|
+
this._topLevelWrapper = null;
|
|
108
104
|
|
|
109
105
|
// See ReactUpdates and ReactUpdateQueue.
|
|
110
106
|
this._pendingCallbacks = null;
|
|
@@ -127,10 +123,10 @@ var ReactCompositeComponentMixin = {
|
|
|
127
123
|
var publicProps = this._processProps(this._currentElement.props);
|
|
128
124
|
var publicContext = this._processContext(context);
|
|
129
125
|
|
|
130
|
-
var Component =
|
|
126
|
+
var Component = this._currentElement.type;
|
|
131
127
|
|
|
132
128
|
// Initialize the public class
|
|
133
|
-
var inst = new Component(publicProps, publicContext);
|
|
129
|
+
var inst = new Component(publicProps, publicContext, ReactUpdateQueue);
|
|
134
130
|
|
|
135
131
|
if ('production' !== process.env.NODE_ENV) {
|
|
136
132
|
// This will throw later in _renderValidatedComponent, but add an early
|
|
@@ -143,6 +139,7 @@ var ReactCompositeComponentMixin = {
|
|
|
143
139
|
inst.props = publicProps;
|
|
144
140
|
inst.context = publicContext;
|
|
145
141
|
inst.refs = emptyObject;
|
|
142
|
+
inst.updater = ReactUpdateQueue;
|
|
146
143
|
|
|
147
144
|
this._instance = inst;
|
|
148
145
|
|
|
@@ -158,6 +155,8 @@ var ReactCompositeComponentMixin = {
|
|
|
158
155
|
'production' !== process.env.NODE_ENV ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : undefined;
|
|
159
156
|
'production' !== process.env.NODE_ENV ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : undefined;
|
|
160
157
|
'production' !== process.env.NODE_ENV ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : undefined;
|
|
158
|
+
'production' !== process.env.NODE_ENV ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : undefined;
|
|
159
|
+
'production' !== process.env.NODE_ENV ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : undefined;
|
|
161
160
|
}
|
|
162
161
|
|
|
163
162
|
var initialState = inst.state;
|
|
@@ -170,27 +169,18 @@ var ReactCompositeComponentMixin = {
|
|
|
170
169
|
this._pendingReplaceState = false;
|
|
171
170
|
this._pendingForceUpdate = false;
|
|
172
171
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
inst.componentWillMount();
|
|
180
|
-
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
181
|
-
// `this._pendingStateQueue` without triggering a re-render.
|
|
182
|
-
if (this._pendingStateQueue) {
|
|
183
|
-
inst.state = this._processPendingState(inst.props, inst.context);
|
|
184
|
-
}
|
|
172
|
+
if (inst.componentWillMount) {
|
|
173
|
+
inst.componentWillMount();
|
|
174
|
+
// When mounting, calls to `setState` by `componentWillMount` will set
|
|
175
|
+
// `this._pendingStateQueue` without triggering a re-render.
|
|
176
|
+
if (this._pendingStateQueue) {
|
|
177
|
+
inst.state = this._processPendingState(inst.props, inst.context);
|
|
185
178
|
}
|
|
186
|
-
|
|
187
|
-
renderedElement = this._renderValidatedComponent();
|
|
188
|
-
} finally {
|
|
189
|
-
ReactLifeCycle.currentlyMountingInstance = previouslyMounting;
|
|
190
179
|
}
|
|
191
180
|
|
|
192
|
-
|
|
193
|
-
|
|
181
|
+
var renderedElement = this._renderValidatedComponent();
|
|
182
|
+
|
|
183
|
+
this._renderedComponent = this._instantiateReactComponent(renderedElement);
|
|
194
184
|
|
|
195
185
|
var markup = ReactReconciler.mountComponent(this._renderedComponent, rootID, transaction, this._processChildContext(context));
|
|
196
186
|
if (inst.componentDidMount) {
|
|
@@ -210,19 +200,15 @@ var ReactCompositeComponentMixin = {
|
|
|
210
200
|
var inst = this._instance;
|
|
211
201
|
|
|
212
202
|
if (inst.componentWillUnmount) {
|
|
213
|
-
|
|
214
|
-
ReactLifeCycle.currentlyUnmountingInstance = this;
|
|
215
|
-
try {
|
|
216
|
-
inst.componentWillUnmount();
|
|
217
|
-
} finally {
|
|
218
|
-
ReactLifeCycle.currentlyUnmountingInstance = previouslyUnmounting;
|
|
219
|
-
}
|
|
203
|
+
inst.componentWillUnmount();
|
|
220
204
|
}
|
|
221
205
|
|
|
222
206
|
ReactReconciler.unmountComponent(this._renderedComponent);
|
|
223
207
|
this._renderedComponent = null;
|
|
224
208
|
|
|
225
209
|
// Reset pending fields
|
|
210
|
+
// Even if this component is scheduled for another update in ReactUpdates,
|
|
211
|
+
// it would still be ignored because these fields are reset.
|
|
226
212
|
this._pendingStateQueue = null;
|
|
227
213
|
this._pendingReplaceState = false;
|
|
228
214
|
this._pendingForceUpdate = false;
|
|
@@ -233,6 +219,7 @@ var ReactCompositeComponentMixin = {
|
|
|
233
219
|
// longer accessible.
|
|
234
220
|
this._context = null;
|
|
235
221
|
this._rootNodeID = null;
|
|
222
|
+
this._topLevelWrapper = null;
|
|
236
223
|
|
|
237
224
|
// Delete the reference from the instance to this internal representation
|
|
238
225
|
// which allow the internals to be properly cleaned up even if the user
|
|
@@ -246,22 +233,6 @@ var ReactCompositeComponentMixin = {
|
|
|
246
233
|
// TODO: inst.context = null;
|
|
247
234
|
},
|
|
248
235
|
|
|
249
|
-
/**
|
|
250
|
-
* Schedule a partial update to the props. Only used for internal testing.
|
|
251
|
-
*
|
|
252
|
-
* @param {object} partialProps Subset of the next props.
|
|
253
|
-
* @param {?function} callback Called after props are updated.
|
|
254
|
-
* @final
|
|
255
|
-
* @internal
|
|
256
|
-
*/
|
|
257
|
-
_setPropsInternal: function (partialProps, callback) {
|
|
258
|
-
// This is a deoptimized path. We optimize for always having an element.
|
|
259
|
-
// This creates an extra internal element.
|
|
260
|
-
var element = this._pendingElement || this._currentElement;
|
|
261
|
-
this._pendingElement = ReactElement.cloneAndReplaceProps(element, assign({}, element.props, partialProps));
|
|
262
|
-
ReactUpdates.enqueueUpdate(this, callback);
|
|
263
|
-
},
|
|
264
|
-
|
|
265
236
|
/**
|
|
266
237
|
* Filters the context object to only contain keys specified in
|
|
267
238
|
* `contextTypes`
|
|
@@ -272,7 +243,7 @@ var ReactCompositeComponentMixin = {
|
|
|
272
243
|
*/
|
|
273
244
|
_maskContext: function (context) {
|
|
274
245
|
var maskedContext = null;
|
|
275
|
-
var Component =
|
|
246
|
+
var Component = this._currentElement.type;
|
|
276
247
|
var contextTypes = Component.contextTypes;
|
|
277
248
|
if (!contextTypes) {
|
|
278
249
|
return emptyObject;
|
|
@@ -295,7 +266,7 @@ var ReactCompositeComponentMixin = {
|
|
|
295
266
|
_processContext: function (context) {
|
|
296
267
|
var maskedContext = this._maskContext(context);
|
|
297
268
|
if ('production' !== process.env.NODE_ENV) {
|
|
298
|
-
var Component =
|
|
269
|
+
var Component = this._currentElement.type;
|
|
299
270
|
if (Component.contextTypes) {
|
|
300
271
|
this._checkPropTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);
|
|
301
272
|
}
|
|
@@ -309,15 +280,16 @@ var ReactCompositeComponentMixin = {
|
|
|
309
280
|
* @private
|
|
310
281
|
*/
|
|
311
282
|
_processChildContext: function (currentContext) {
|
|
283
|
+
var Component = this._currentElement.type;
|
|
312
284
|
var inst = this._instance;
|
|
313
285
|
var childContext = inst.getChildContext && inst.getChildContext();
|
|
314
286
|
if (childContext) {
|
|
315
|
-
!(typeof
|
|
287
|
+
!(typeof Component.childContextTypes === 'object') ? 'production' !== process.env.NODE_ENV ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined;
|
|
316
288
|
if ('production' !== process.env.NODE_ENV) {
|
|
317
|
-
this._checkPropTypes(
|
|
289
|
+
this._checkPropTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);
|
|
318
290
|
}
|
|
319
291
|
for (var name in childContext) {
|
|
320
|
-
!(name in
|
|
292
|
+
!(name in Component.childContextTypes) ? 'production' !== process.env.NODE_ENV ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : invariant(false) : undefined;
|
|
321
293
|
}
|
|
322
294
|
return assign({}, currentContext, childContext);
|
|
323
295
|
}
|
|
@@ -335,7 +307,7 @@ var ReactCompositeComponentMixin = {
|
|
|
335
307
|
*/
|
|
336
308
|
_processProps: function (newProps) {
|
|
337
309
|
if ('production' !== process.env.NODE_ENV) {
|
|
338
|
-
var Component =
|
|
310
|
+
var Component = this._currentElement.type;
|
|
339
311
|
if (Component.propTypes) {
|
|
340
312
|
this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop);
|
|
341
313
|
}
|
|
@@ -405,10 +377,6 @@ var ReactCompositeComponentMixin = {
|
|
|
405
377
|
}
|
|
406
378
|
|
|
407
379
|
if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
|
|
408
|
-
if ('production' !== process.env.NODE_ENV) {
|
|
409
|
-
ReactElementValidator.checkAndWarnForMutatedProps(this._currentElement);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
380
|
this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);
|
|
413
381
|
}
|
|
414
382
|
},
|
|
@@ -431,14 +399,16 @@ var ReactCompositeComponentMixin = {
|
|
|
431
399
|
updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
|
|
432
400
|
var inst = this._instance;
|
|
433
401
|
|
|
434
|
-
var nextContext = inst.context;
|
|
435
|
-
var nextProps
|
|
402
|
+
var nextContext = this._context === nextUnmaskedContext ? inst.context : this._processContext(nextUnmaskedContext);
|
|
403
|
+
var nextProps;
|
|
436
404
|
|
|
437
405
|
// Distinguish between a props update versus a simple state update
|
|
438
|
-
if (prevParentElement
|
|
439
|
-
|
|
406
|
+
if (prevParentElement === nextParentElement) {
|
|
407
|
+
// Skip checking prop types again -- we don't read inst.props to avoid
|
|
408
|
+
// warning for DOM component props in this upgrade
|
|
409
|
+
nextProps = nextParentElement.props;
|
|
410
|
+
} else {
|
|
440
411
|
nextProps = this._processProps(nextParentElement.props);
|
|
441
|
-
|
|
442
412
|
// An update here will schedule an update but immediately set
|
|
443
413
|
// _pendingStateQueue which will ensure that any state updates gets
|
|
444
414
|
// immediately reconciled instead of waiting for the next batch.
|
|
@@ -510,9 +480,15 @@ var ReactCompositeComponentMixin = {
|
|
|
510
480
|
_performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
|
|
511
481
|
var inst = this._instance;
|
|
512
482
|
|
|
513
|
-
var
|
|
514
|
-
var
|
|
515
|
-
var
|
|
483
|
+
var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
|
|
484
|
+
var prevProps;
|
|
485
|
+
var prevState;
|
|
486
|
+
var prevContext;
|
|
487
|
+
if (hasComponentDidUpdate) {
|
|
488
|
+
prevProps = inst.props;
|
|
489
|
+
prevState = inst.state;
|
|
490
|
+
prevContext = inst.context;
|
|
491
|
+
}
|
|
516
492
|
|
|
517
493
|
if (inst.componentWillUpdate) {
|
|
518
494
|
inst.componentWillUpdate(nextProps, nextState, nextContext);
|
|
@@ -526,7 +502,7 @@ var ReactCompositeComponentMixin = {
|
|
|
526
502
|
|
|
527
503
|
this._updateRenderedComponent(transaction, unmaskedContext);
|
|
528
504
|
|
|
529
|
-
if (
|
|
505
|
+
if (hasComponentDidUpdate) {
|
|
530
506
|
transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
|
|
531
507
|
}
|
|
532
508
|
},
|
|
@@ -549,7 +525,7 @@ var ReactCompositeComponentMixin = {
|
|
|
549
525
|
var prevComponentID = prevComponentInstance._rootNodeID;
|
|
550
526
|
ReactReconciler.unmountComponent(prevComponentInstance);
|
|
551
527
|
|
|
552
|
-
this._renderedComponent = this._instantiateReactComponent(nextRenderedElement
|
|
528
|
+
this._renderedComponent = this._instantiateReactComponent(nextRenderedElement);
|
|
553
529
|
var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, thisID, transaction, this._processChildContext(context));
|
|
554
530
|
this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
|
|
555
531
|
}
|
|
@@ -585,13 +561,10 @@ var ReactCompositeComponentMixin = {
|
|
|
585
561
|
*/
|
|
586
562
|
_renderValidatedComponent: function () {
|
|
587
563
|
var renderedComponent;
|
|
588
|
-
var previousContext = ReactContext.current;
|
|
589
|
-
ReactContext.current = this._processChildContext(this._currentElement._context);
|
|
590
564
|
ReactCurrentOwner.current = this;
|
|
591
565
|
try {
|
|
592
566
|
renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();
|
|
593
567
|
} finally {
|
|
594
|
-
ReactContext.current = previousContext;
|
|
595
568
|
ReactCurrentOwner.current = null;
|
|
596
569
|
}
|
|
597
570
|
!(
|
package/lib/ReactDOM.js
CHANGED
package/lib/ReactDOMButton.js
CHANGED
|
@@ -11,51 +11,40 @@
|
|
|
11
11
|
|
|
12
12
|
'use strict';
|
|
13
13
|
|
|
14
|
-
var
|
|
15
|
-
var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
|
|
16
|
-
var ReactClass = require("./ReactClass");
|
|
17
|
-
var ReactElement = require("./ReactElement");
|
|
18
|
-
|
|
19
|
-
var keyMirror = require("./keyMirror");
|
|
20
|
-
|
|
21
|
-
var button = ReactElement.createFactory('button');
|
|
22
|
-
|
|
23
|
-
var mouseListenerNames = keyMirror({
|
|
14
|
+
var mouseListenerNames = {
|
|
24
15
|
onClick: true,
|
|
25
16
|
onDoubleClick: true,
|
|
26
17
|
onMouseDown: true,
|
|
27
18
|
onMouseMove: true,
|
|
28
19
|
onMouseUp: true,
|
|
20
|
+
|
|
29
21
|
onClickCapture: true,
|
|
30
22
|
onDoubleClickCapture: true,
|
|
31
23
|
onMouseDownCapture: true,
|
|
32
24
|
onMouseMoveCapture: true,
|
|
33
25
|
onMouseUpCapture: true
|
|
34
|
-
}
|
|
26
|
+
};
|
|
35
27
|
|
|
36
28
|
/**
|
|
37
29
|
* Implements a <button> native component that does not receive mouse events
|
|
38
30
|
* when `disabled` is set.
|
|
39
31
|
*/
|
|
40
|
-
var ReactDOMButton =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
render: function () {
|
|
47
|
-
var props = {};
|
|
32
|
+
var ReactDOMButton = {
|
|
33
|
+
getNativeProps: function (inst, props, context) {
|
|
34
|
+
if (!props.disabled) {
|
|
35
|
+
return props;
|
|
36
|
+
}
|
|
48
37
|
|
|
49
|
-
// Copy the props
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
// Copy the props, except the mouse listeners
|
|
39
|
+
var nativeProps = {};
|
|
40
|
+
for (var key in props) {
|
|
41
|
+
if (props.hasOwnProperty(key) && !mouseListenerNames[key]) {
|
|
42
|
+
nativeProps[key] = props[key];
|
|
53
43
|
}
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
return
|
|
46
|
+
return nativeProps;
|
|
57
47
|
}
|
|
58
|
-
|
|
59
|
-
});
|
|
48
|
+
};
|
|
60
49
|
|
|
61
50
|
module.exports = ReactDOMButton;
|
package/lib/ReactDOMClient.js
CHANGED
|
@@ -20,8 +20,10 @@ var ReactInstanceHandles = require("./ReactInstanceHandles");
|
|
|
20
20
|
var ReactMount = require("./ReactMount");
|
|
21
21
|
var ReactPerf = require("./ReactPerf");
|
|
22
22
|
var ReactReconciler = require("./ReactReconciler");
|
|
23
|
+
var ReactUpdates = require("./ReactUpdates");
|
|
23
24
|
|
|
24
25
|
var findDOMNode = require("./findDOMNode");
|
|
26
|
+
var renderSubtreeIntoContainer = require("./renderSubtreeIntoContainer");
|
|
25
27
|
var warning = require("./warning");
|
|
26
28
|
|
|
27
29
|
ReactDefaultInjection.inject();
|
|
@@ -29,11 +31,13 @@ ReactDefaultInjection.inject();
|
|
|
29
31
|
var render = ReactPerf.measure('React', 'render', ReactMount.render);
|
|
30
32
|
|
|
31
33
|
var React = {
|
|
32
|
-
constructAndRenderComponent: ReactMount.constructAndRenderComponent,
|
|
33
|
-
constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID,
|
|
34
34
|
findDOMNode: findDOMNode,
|
|
35
35
|
render: render,
|
|
36
|
-
unmountComponentAtNode: ReactMount.unmountComponentAtNode
|
|
36
|
+
unmountComponentAtNode: ReactMount.unmountComponentAtNode,
|
|
37
|
+
|
|
38
|
+
/* eslint-disable camelcase */
|
|
39
|
+
unstable_batchedUpdates: ReactUpdates.batchedUpdates,
|
|
40
|
+
unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
|
|
37
41
|
};
|
|
38
42
|
|
|
39
43
|
// Inject the runtime into a devtools global hook regardless of browser.
|
|
@@ -82,4 +86,5 @@ if ('production' !== process.env.NODE_ENV) {
|
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
module.exports = React;
|
|
89
|
+
module.exports = React;
|
|
90
|
+
/* eslint-enable camelcase */
|
package/lib/ReactDOMComponent.js
CHANGED
|
@@ -14,14 +14,22 @@
|
|
|
14
14
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
|
+
var AutoFocusUtils = require("./AutoFocusUtils");
|
|
17
18
|
var CSSPropertyOperations = require("./CSSPropertyOperations");
|
|
18
19
|
var DOMProperty = require("./DOMProperty");
|
|
19
20
|
var DOMPropertyOperations = require("./DOMPropertyOperations");
|
|
21
|
+
var EventConstants = require("./EventConstants");
|
|
20
22
|
var ReactBrowserEventEmitter = require("./ReactBrowserEventEmitter");
|
|
21
23
|
var ReactComponentBrowserEnvironment = require("./ReactComponentBrowserEnvironment");
|
|
24
|
+
var ReactDOMButton = require("./ReactDOMButton");
|
|
25
|
+
var ReactDOMInput = require("./ReactDOMInput");
|
|
26
|
+
var ReactDOMOption = require("./ReactDOMOption");
|
|
27
|
+
var ReactDOMSelect = require("./ReactDOMSelect");
|
|
28
|
+
var ReactDOMTextarea = require("./ReactDOMTextarea");
|
|
22
29
|
var ReactMount = require("./ReactMount");
|
|
23
30
|
var ReactMultiChild = require("./ReactMultiChild");
|
|
24
31
|
var ReactPerf = require("./ReactPerf");
|
|
32
|
+
var ReactUpdateQueue = require("./ReactUpdateQueue");
|
|
25
33
|
|
|
26
34
|
var assign = require("./Object.assign");
|
|
27
35
|
var escapeTextContentForBrowser = require("./escapeTextContentForBrowser");
|
|
@@ -43,6 +51,90 @@ var STYLE = keyOf({ style: null });
|
|
|
43
51
|
|
|
44
52
|
var ELEMENT_NODE_TYPE = 1;
|
|
45
53
|
|
|
54
|
+
var canDefineProperty = false;
|
|
55
|
+
try {
|
|
56
|
+
Object.defineProperty({}, 'test', { get: function () {} });
|
|
57
|
+
canDefineProperty = true;
|
|
58
|
+
} catch (e) {}
|
|
59
|
+
|
|
60
|
+
function getDeclarationErrorAddendum(internalInstance) {
|
|
61
|
+
if (internalInstance) {
|
|
62
|
+
var owner = internalInstance._currentElement._owner || null;
|
|
63
|
+
if (owner) {
|
|
64
|
+
var name = owner.getName();
|
|
65
|
+
if (name) {
|
|
66
|
+
return ' This DOM node was rendered by `' + name + '`.';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var legacyPropsDescriptor;
|
|
74
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
75
|
+
legacyPropsDescriptor = {
|
|
76
|
+
props: {
|
|
77
|
+
enumerable: false,
|
|
78
|
+
get: function () {
|
|
79
|
+
var component = this._reactInternalComponent;
|
|
80
|
+
'production' !== process.env.NODE_ENV ? warning(false, 'ReactDOMComponent: Do not access .props of a DOM node; instead, ' + 'recreate the props as `render` did originally or read the DOM ' + 'properties/attributes directly from this node (e.g., ' + 'this.refs.box.className).%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
81
|
+
return component._currentElement.props;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function legacyGetDOMNode() {
|
|
88
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
89
|
+
var component = this._reactInternalComponent;
|
|
90
|
+
'production' !== process.env.NODE_ENV ? warning(false, 'ReactDOMComponent: Do not access .getDOMNode() of a DOM node; ' + 'instead, use the node directly.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
91
|
+
}
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function legacyIsMounted() {
|
|
96
|
+
var component = this._reactInternalComponent;
|
|
97
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
98
|
+
'production' !== process.env.NODE_ENV ? warning(false, 'ReactDOMComponent: Do not access .isMounted() of a DOM node.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
99
|
+
}
|
|
100
|
+
return !!component;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function legacySetStateEtc() {
|
|
104
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
105
|
+
var component = this._reactInternalComponent;
|
|
106
|
+
'production' !== process.env.NODE_ENV ? warning(false, 'ReactDOMComponent: Do not access .setState(), .replaceState(), or ' + '.forceUpdate() of a DOM node. This is a no-op.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function legacySetProps(partialProps, callback) {
|
|
111
|
+
var component = this._reactInternalComponent;
|
|
112
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
113
|
+
'production' !== process.env.NODE_ENV ? warning(false, 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' + 'Instead, call React.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
114
|
+
}
|
|
115
|
+
if (!component) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
ReactUpdateQueue.enqueueSetPropsInternal(component, partialProps);
|
|
119
|
+
if (callback) {
|
|
120
|
+
ReactUpdateQueue.enqueueCallbackInternal(component, callback);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function legacyReplaceProps(partialProps, callback) {
|
|
125
|
+
var component = this._reactInternalComponent;
|
|
126
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
127
|
+
'production' !== process.env.NODE_ENV ? warning(false, 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' + 'Instead, call React.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
|
|
128
|
+
}
|
|
129
|
+
if (!component) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
ReactUpdateQueue.enqueueReplacePropsInternal(component, partialProps);
|
|
133
|
+
if (callback) {
|
|
134
|
+
ReactUpdateQueue.enqueueCallbackInternal(component, callback);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
46
138
|
var styleMutationWarning = {};
|
|
47
139
|
|
|
48
140
|
function checkAndWarnForMutatedStyle(style1, style2, component) {
|
|
@@ -77,6 +169,7 @@ function checkAndWarnForMutatedStyle(style1, style2, component) {
|
|
|
77
169
|
var BackendIDOperations = null;
|
|
78
170
|
|
|
79
171
|
/**
|
|
172
|
+
* @param {object} component
|
|
80
173
|
* @param {?object} props
|
|
81
174
|
*/
|
|
82
175
|
function assertValidProps(component, props) {
|
|
@@ -86,7 +179,7 @@ function assertValidProps(component, props) {
|
|
|
86
179
|
// Note the use of `==` which checks for null or undefined.
|
|
87
180
|
if ('production' !== process.env.NODE_ENV) {
|
|
88
181
|
if (voidElementTags[component._tag]) {
|
|
89
|
-
'production' !== process.env.NODE_ENV ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML
|
|
182
|
+
'production' !== process.env.NODE_ENV ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : undefined;
|
|
90
183
|
}
|
|
91
184
|
}
|
|
92
185
|
if (props.dangerouslySetInnerHTML != null) {
|
|
@@ -123,6 +216,31 @@ function putListener() {
|
|
|
123
216
|
ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
|
|
124
217
|
}
|
|
125
218
|
|
|
219
|
+
function trapBubbledEventsLocal() {
|
|
220
|
+
var inst = this;
|
|
221
|
+
// If a component renders to null or if another component fatals and causes
|
|
222
|
+
// the state of the tree to be corrupted, `node` here can be null.
|
|
223
|
+
!inst._rootNodeID ? 'production' !== process.env.NODE_ENV ? invariant(false, 'Must be mounted to trap events') : invariant(false) : undefined;
|
|
224
|
+
var node = ReactMount.getNode(inst._rootNodeID);
|
|
225
|
+
!node ? 'production' !== process.env.NODE_ENV ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : invariant(false) : undefined;
|
|
226
|
+
|
|
227
|
+
switch (inst._tag) {
|
|
228
|
+
case 'iframe':
|
|
229
|
+
inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
|
|
230
|
+
break;
|
|
231
|
+
case 'img':
|
|
232
|
+
inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
|
|
233
|
+
break;
|
|
234
|
+
case 'form':
|
|
235
|
+
inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function postUpdateSelectWrapper() {
|
|
241
|
+
ReactDOMSelect.postUpdateWrapper(this);
|
|
242
|
+
}
|
|
243
|
+
|
|
126
244
|
// For HTML, certain tags should omit their close tag. We keep a whitelist for
|
|
127
245
|
// those special cased tags.
|
|
128
246
|
|
|
@@ -142,7 +260,6 @@ var omittedCloseTags = {
|
|
|
142
260
|
'source': true,
|
|
143
261
|
'track': true,
|
|
144
262
|
'wbr': true
|
|
145
|
-
// NOTE: menuitem's close tag should be omitted, but that causes problems.
|
|
146
263
|
};
|
|
147
264
|
|
|
148
265
|
var newlineEatingTags = {
|
|
@@ -183,6 +300,10 @@ function processChildContext(context, inst) {
|
|
|
183
300
|
return context;
|
|
184
301
|
}
|
|
185
302
|
|
|
303
|
+
function isCustomComponent(tagName, props) {
|
|
304
|
+
return tagName.indexOf('-') >= 0 || props.is != null;
|
|
305
|
+
}
|
|
306
|
+
|
|
186
307
|
/**
|
|
187
308
|
* Creates a new React class that is idempotent and capable of containing other
|
|
188
309
|
* React components. It accepts event listeners and DOM properties that are
|
|
@@ -199,11 +320,14 @@ function processChildContext(context, inst) {
|
|
|
199
320
|
*/
|
|
200
321
|
function ReactDOMComponent(tag) {
|
|
201
322
|
validateDangerousTag(tag);
|
|
202
|
-
this._tag = tag;
|
|
323
|
+
this._tag = tag.toLowerCase();
|
|
203
324
|
this._renderedChildren = null;
|
|
204
325
|
this._previousStyle = null;
|
|
205
326
|
this._previousStyleCopy = null;
|
|
206
327
|
this._rootNodeID = null;
|
|
328
|
+
this._wrapperState = null;
|
|
329
|
+
this._topLevelWrapper = null;
|
|
330
|
+
this._nodeWithLegacyProperties = null;
|
|
207
331
|
}
|
|
208
332
|
|
|
209
333
|
ReactDOMComponent.displayName = 'ReactDOMComponent';
|
|
@@ -227,19 +351,64 @@ ReactDOMComponent.Mixin = {
|
|
|
227
351
|
mountComponent: function (rootID, transaction, context) {
|
|
228
352
|
this._rootNodeID = rootID;
|
|
229
353
|
|
|
230
|
-
|
|
354
|
+
var props = this._currentElement.props;
|
|
355
|
+
|
|
356
|
+
switch (this._tag) {
|
|
357
|
+
case 'iframe':
|
|
358
|
+
case 'img':
|
|
359
|
+
case 'form':
|
|
360
|
+
this._wrapperState = {
|
|
361
|
+
listeners: null
|
|
362
|
+
};
|
|
363
|
+
transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
|
|
364
|
+
break;
|
|
365
|
+
case 'button':
|
|
366
|
+
props = ReactDOMButton.getNativeProps(this, props, context);
|
|
367
|
+
break;
|
|
368
|
+
case 'input':
|
|
369
|
+
ReactDOMInput.mountWrapper(this, props, context);
|
|
370
|
+
props = ReactDOMInput.getNativeProps(this, props, context);
|
|
371
|
+
break;
|
|
372
|
+
case 'option':
|
|
373
|
+
ReactDOMOption.mountWrapper(this, props, context);
|
|
374
|
+
props = ReactDOMOption.getNativeProps(this, props, context);
|
|
375
|
+
break;
|
|
376
|
+
case 'select':
|
|
377
|
+
ReactDOMSelect.mountWrapper(this, props, context);
|
|
378
|
+
props = ReactDOMSelect.getNativeProps(this, props, context);
|
|
379
|
+
context = ReactDOMSelect.processChildContext(this, props, context);
|
|
380
|
+
break;
|
|
381
|
+
case 'textarea':
|
|
382
|
+
ReactDOMTextarea.mountWrapper(this, props, context);
|
|
383
|
+
props = ReactDOMTextarea.getNativeProps(this, props, context);
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
assertValidProps(this, props);
|
|
231
388
|
if ('production' !== process.env.NODE_ENV) {
|
|
232
389
|
if (context[validateDOMNesting.ancestorInfoContextKey]) {
|
|
233
390
|
validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
|
|
234
391
|
}
|
|
235
392
|
}
|
|
236
393
|
|
|
237
|
-
var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction);
|
|
238
|
-
var tagContent = this._createContentMarkup(transaction, context);
|
|
394
|
+
var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
|
|
395
|
+
var tagContent = this._createContentMarkup(transaction, props, context);
|
|
396
|
+
|
|
397
|
+
switch (this._tag) {
|
|
398
|
+
case 'button':
|
|
399
|
+
case 'input':
|
|
400
|
+
case 'select':
|
|
401
|
+
case 'textarea':
|
|
402
|
+
if (props.autoFocus) {
|
|
403
|
+
transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
|
|
404
|
+
}
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
|
|
239
408
|
if (!tagContent && omittedCloseTags[this._tag]) {
|
|
240
409
|
return tagOpen + '/>';
|
|
241
410
|
}
|
|
242
|
-
return tagOpen + '>' + tagContent + '</' + this.
|
|
411
|
+
return tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
|
|
243
412
|
},
|
|
244
413
|
|
|
245
414
|
/**
|
|
@@ -252,11 +421,11 @@ ReactDOMComponent.Mixin = {
|
|
|
252
421
|
*
|
|
253
422
|
* @private
|
|
254
423
|
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
424
|
+
* @param {object} props
|
|
255
425
|
* @return {string} Markup of opening tag.
|
|
256
426
|
*/
|
|
257
|
-
_createOpenTagMarkupAndPutListeners: function (transaction) {
|
|
258
|
-
var
|
|
259
|
-
var ret = '<' + this._tag;
|
|
427
|
+
_createOpenTagMarkupAndPutListeners: function (transaction, props) {
|
|
428
|
+
var ret = '<' + this._currentElement.type;
|
|
260
429
|
|
|
261
430
|
for (var propKey in props) {
|
|
262
431
|
if (!props.hasOwnProperty(propKey)) {
|
|
@@ -279,7 +448,12 @@ ReactDOMComponent.Mixin = {
|
|
|
279
448
|
}
|
|
280
449
|
propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
|
|
281
450
|
}
|
|
282
|
-
var markup =
|
|
451
|
+
var markup = null;
|
|
452
|
+
if (this._tag != null && isCustomComponent(this._tag, props)) {
|
|
453
|
+
markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
|
|
454
|
+
} else {
|
|
455
|
+
markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
|
|
456
|
+
}
|
|
283
457
|
if (markup) {
|
|
284
458
|
ret += ' ' + markup;
|
|
285
459
|
}
|
|
@@ -301,12 +475,12 @@ ReactDOMComponent.Mixin = {
|
|
|
301
475
|
*
|
|
302
476
|
* @private
|
|
303
477
|
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
|
|
478
|
+
* @param {object} props
|
|
304
479
|
* @param {object} context
|
|
305
480
|
* @return {string} Content markup.
|
|
306
481
|
*/
|
|
307
|
-
_createContentMarkup: function (transaction, context) {
|
|
482
|
+
_createContentMarkup: function (transaction, props, context) {
|
|
308
483
|
var ret = '';
|
|
309
|
-
var props = this._currentElement.props;
|
|
310
484
|
|
|
311
485
|
// Intentional use of != to avoid catching zero/false.
|
|
312
486
|
var innerHTML = props.dangerouslySetInnerHTML;
|
|
@@ -367,9 +541,47 @@ ReactDOMComponent.Mixin = {
|
|
|
367
541
|
* @overridable
|
|
368
542
|
*/
|
|
369
543
|
updateComponent: function (transaction, prevElement, nextElement, context) {
|
|
370
|
-
|
|
371
|
-
this.
|
|
372
|
-
|
|
544
|
+
var lastProps = prevElement.props;
|
|
545
|
+
var nextProps = this._currentElement.props;
|
|
546
|
+
|
|
547
|
+
switch (this._tag) {
|
|
548
|
+
case 'button':
|
|
549
|
+
lastProps = ReactDOMButton.getNativeProps(this, lastProps);
|
|
550
|
+
nextProps = ReactDOMButton.getNativeProps(this, nextProps);
|
|
551
|
+
break;
|
|
552
|
+
case 'input':
|
|
553
|
+
ReactDOMInput.updateWrapper(this);
|
|
554
|
+
lastProps = ReactDOMInput.getNativeProps(this, lastProps);
|
|
555
|
+
nextProps = ReactDOMInput.getNativeProps(this, nextProps);
|
|
556
|
+
break;
|
|
557
|
+
case 'option':
|
|
558
|
+
lastProps = ReactDOMOption.getNativeProps(this, lastProps);
|
|
559
|
+
nextProps = ReactDOMOption.getNativeProps(this, nextProps);
|
|
560
|
+
break;
|
|
561
|
+
case 'select':
|
|
562
|
+
lastProps = ReactDOMSelect.getNativeProps(this, lastProps);
|
|
563
|
+
nextProps = ReactDOMSelect.getNativeProps(this, nextProps);
|
|
564
|
+
break;
|
|
565
|
+
case 'textarea':
|
|
566
|
+
ReactDOMTextarea.updateWrapper(this);
|
|
567
|
+
lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
|
|
568
|
+
nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
|
|
569
|
+
break;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
assertValidProps(this, nextProps);
|
|
573
|
+
this._updateDOMProperties(lastProps, nextProps, transaction);
|
|
574
|
+
this._updateDOMChildren(lastProps, nextProps, transaction, processChildContext(context, this));
|
|
575
|
+
|
|
576
|
+
if (!canDefineProperty && this._nodeWithLegacyProperties) {
|
|
577
|
+
this._nodeWithLegacyProperties.props = nextProps;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (this._tag === 'select') {
|
|
581
|
+
// <select> value update needs to occur after <option> children
|
|
582
|
+
// reconciliation
|
|
583
|
+
transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
|
|
584
|
+
}
|
|
373
585
|
},
|
|
374
586
|
|
|
375
587
|
/**
|
|
@@ -385,10 +597,10 @@ ReactDOMComponent.Mixin = {
|
|
|
385
597
|
*
|
|
386
598
|
* @private
|
|
387
599
|
* @param {object} lastProps
|
|
600
|
+
* @param {object} nextProps
|
|
388
601
|
* @param {ReactReconcileTransaction} transaction
|
|
389
602
|
*/
|
|
390
|
-
_updateDOMProperties: function (lastProps, transaction) {
|
|
391
|
-
var nextProps = this._currentElement.props;
|
|
603
|
+
_updateDOMProperties: function (lastProps, nextProps, transaction) {
|
|
392
604
|
var propKey;
|
|
393
605
|
var styleName;
|
|
394
606
|
var styleUpdates;
|
|
@@ -412,7 +624,7 @@ ReactDOMComponent.Mixin = {
|
|
|
412
624
|
// listener (e.g., onClick={null})
|
|
413
625
|
deleteListener(this._rootNodeID, propKey);
|
|
414
626
|
}
|
|
415
|
-
} else if (DOMProperty.
|
|
627
|
+
} else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
|
|
416
628
|
BackendIDOperations.deletePropertyByID(this._rootNodeID, propKey);
|
|
417
629
|
}
|
|
418
630
|
}
|
|
@@ -457,7 +669,9 @@ ReactDOMComponent.Mixin = {
|
|
|
457
669
|
} else if (lastProp) {
|
|
458
670
|
deleteListener(this._rootNodeID, propKey);
|
|
459
671
|
}
|
|
460
|
-
} else if (
|
|
672
|
+
} else if (isCustomComponent(this._tag, nextProps)) {
|
|
673
|
+
BackendIDOperations.updateAttributeByID(this._rootNodeID, propKey, nextProp);
|
|
674
|
+
} else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
|
|
461
675
|
BackendIDOperations.updatePropertyByID(this._rootNodeID, propKey, nextProp);
|
|
462
676
|
}
|
|
463
677
|
}
|
|
@@ -471,11 +685,11 @@ ReactDOMComponent.Mixin = {
|
|
|
471
685
|
* children content.
|
|
472
686
|
*
|
|
473
687
|
* @param {object} lastProps
|
|
688
|
+
* @param {object} nextProps
|
|
474
689
|
* @param {ReactReconcileTransaction} transaction
|
|
690
|
+
* @param {object} context
|
|
475
691
|
*/
|
|
476
|
-
_updateDOMChildren: function (lastProps, transaction, context) {
|
|
477
|
-
var nextProps = this._currentElement.props;
|
|
478
|
-
|
|
692
|
+
_updateDOMChildren: function (lastProps, nextProps, transaction, context) {
|
|
479
693
|
var lastContent = CONTENT_TYPES[typeof lastProps.children] ? lastProps.children : null;
|
|
480
694
|
var nextContent = CONTENT_TYPES[typeof nextProps.children] ? nextProps.children : null;
|
|
481
695
|
|
|
@@ -516,10 +730,73 @@ ReactDOMComponent.Mixin = {
|
|
|
516
730
|
* @internal
|
|
517
731
|
*/
|
|
518
732
|
unmountComponent: function () {
|
|
733
|
+
switch (this._tag) {
|
|
734
|
+
case 'iframe':
|
|
735
|
+
case 'img':
|
|
736
|
+
case 'form':
|
|
737
|
+
var listeners = this._wrapperState.listeners;
|
|
738
|
+
if (listeners) {
|
|
739
|
+
for (var i = 0; i < listeners.length; i++) {
|
|
740
|
+
listeners[i].remove();
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
break;
|
|
744
|
+
case 'input':
|
|
745
|
+
ReactDOMInput.unmountWrapper(this);
|
|
746
|
+
break;
|
|
747
|
+
case 'html':
|
|
748
|
+
case 'head':
|
|
749
|
+
case 'body':
|
|
750
|
+
/**
|
|
751
|
+
* Components like <html> <head> and <body> can't be removed or added
|
|
752
|
+
* easily in a cross-browser way, however it's valuable to be able to
|
|
753
|
+
* take advantage of React's reconciliation for styling and <title>
|
|
754
|
+
* management. So we just document it and throw in dangerous cases.
|
|
755
|
+
*/
|
|
756
|
+
!false ? 'production' !== process.env.NODE_ENV ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is ' + 'impossible to unmount some top-level components (eg <html>, ' + '<head>, and <body>) reliably and efficiently. To fix this, have a ' + 'single top-level component that never unmounts render these ' + 'elements.', this._tag) : invariant(false) : undefined;
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
|
|
519
760
|
this.unmountChildren();
|
|
520
761
|
ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
|
|
521
762
|
ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
|
|
522
763
|
this._rootNodeID = null;
|
|
764
|
+
this._wrapperState = null;
|
|
765
|
+
if (this._nodeWithLegacyProperties) {
|
|
766
|
+
var node = this._nodeWithLegacyProperties;
|
|
767
|
+
node._reactInternalComponent = null;
|
|
768
|
+
this._nodeWithLegacyProperties = null;
|
|
769
|
+
}
|
|
770
|
+
},
|
|
771
|
+
|
|
772
|
+
getPublicInstance: function () {
|
|
773
|
+
if (!this._nodeWithLegacyProperties) {
|
|
774
|
+
var node = ReactMount.getNode(this._rootNodeID);
|
|
775
|
+
|
|
776
|
+
node._reactInternalComponent = this;
|
|
777
|
+
node.getDOMNode = legacyGetDOMNode;
|
|
778
|
+
node.isMounted = legacyIsMounted;
|
|
779
|
+
node.setState = legacySetStateEtc;
|
|
780
|
+
node.replaceState = legacySetStateEtc;
|
|
781
|
+
node.forceUpdate = legacySetStateEtc;
|
|
782
|
+
node.setProps = legacySetProps;
|
|
783
|
+
node.replaceProps = legacyReplaceProps;
|
|
784
|
+
|
|
785
|
+
if ('production' !== process.env.NODE_ENV) {
|
|
786
|
+
if (canDefineProperty) {
|
|
787
|
+
Object.defineProperties(node, legacyPropsDescriptor);
|
|
788
|
+
} else {
|
|
789
|
+
// updateComponent will update this property on subsequent renders
|
|
790
|
+
node.props = this._currentElement.props;
|
|
791
|
+
}
|
|
792
|
+
} else {
|
|
793
|
+
// updateComponent will update this property on subsequent renders
|
|
794
|
+
node.props = this._currentElement.props;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
this._nodeWithLegacyProperties = node;
|
|
798
|
+
}
|
|
799
|
+
return this._nodeWithLegacyProperties;
|
|
523
800
|
}
|
|
524
801
|
|
|
525
802
|
};
|
|
@@ -537,4 +814,5 @@ ReactDOMComponent.injection = {
|
|
|
537
814
|
}
|
|
538
815
|
};
|
|
539
816
|
|
|
540
|
-
module.exports = ReactDOMComponent;
|
|
817
|
+
module.exports = ReactDOMComponent;
|
|
818
|
+
// NOTE: menuitem's close tag should be omitted, but that causes problems.
|